1 /*************************************************************************/ /*!
3 @Title Resource Handle Manager
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Provide resource handle management
6 @License Dual MIT/GPLv2
8 The contents of this file are subject to the MIT license as set out below.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
32 This License is also included in this distribution in the file called
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /***************************************************************************/
44 /* See handle.h for a description of the handle API. */
47 * The implmentation supports movable handle structures, allowing the address
48 * of a handle structure to change without having to fix up pointers in
49 * any of the handle structures. For example, the linked list mechanism
50 * used to link subhandles together uses handle array indices rather than
51 * pointers to the structures themselves.
57 #include "handle_impl.h"
59 #include "pvr_debug.h"
60 #include "connection_server.h"
62 #define HANDLE_HASH_TAB_INIT_SIZE 32
64 #define SET_FLAG(v, f) ((void)((v) |= (f)))
65 #define CLEAR_FLAG(v, f) ((void)((v) &= (IMG_UINT)~(f)))
66 #define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
68 #define TEST_ALLOC_FLAG(psHandleData, f) TEST_FLAG((psHandleData)->eFlag, f)
70 #if !defined(ARRAY_SIZE)
71 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
75 /* Linked list structure. Used for both the list head and list items */
76 typedef struct _HANDLE_LIST_
83 typedef struct _HANDLE_DATA_
85 /* The handle that represents this structure */
89 PVRSRV_HANDLE_TYPE eType;
91 /* Flags specified when the handle was allocated */
92 PVRSRV_HANDLE_ALLOC_FLAG eFlag;
94 /* Pointer to the data that the handle represents */
98 * Callback specified at handle allocation time to
99 * release/destroy/free the data represented by the
100 * handle when it's reference count reaches 0. This
101 * should always be NULL for subhandles.
103 PFN_HANDLE_RELEASE pfnReleaseData;
105 /* List head for subhandles of this handle */
106 HANDLE_LIST sChildren;
108 /* List entry for sibling subhandles */
109 HANDLE_LIST sSiblings;
111 /* Reference count. The pfnReleaseData callback gets called when the
112 * reference count hits zero
114 IMG_UINT32 ui32RefCount;
119 /* Pointer to a handle implementations base structure */
120 HANDLE_IMPL_BASE *psImplBase;
123 * Pointer to handle hash table.
124 * The hash table is used to do reverse lookups, converting data
125 * pointers to handles.
127 HASH_TABLE *psHashTab;
129 /* Can be connection, process, global */
130 PVRSRV_HANDLE_BASE_TYPE eType;
134 * The key for the handle hash table is an array of three elements, the
135 * pointer to the resource, the resource type and the parent handle (or
136 * NULL if there is no parent). The eHandKey enumeration gives the
137 * array indices of the elements making up the key.
144 HAND_KEY_LEN /* Must be last item in list */
147 /* HAND_KEY is the type of the hash table key */
148 typedef uintptr_t HAND_KEY[HAND_KEY_LEN];
150 /* Stores a pointer to the function table of the handle back-end in use */
151 static HANDLE_IMPL_FUNCTAB const *gpsHandleFuncs = NULL;
154 * Global lock added to avoid to call the handling functions
155 * only in a single threaded context.
157 static POS_LOCK gHandleLock;
158 static IMG_BOOL gbLockInitialised = IMG_FALSE;
160 void LockHandle(void)
162 OSLockAcquire(gHandleLock);
165 void UnlockHandle(void)
167 OSLockRelease(gHandleLock);
171 * Kernel handle base structure. This is used for handles that are not
172 * allocated on behalf of a particular process.
174 PVRSRV_HANDLE_BASE *gpsKernelHandleBase = NULL;
176 /* Increase the reference count on the given handle.
177 * The handle lock must already be acquired.
178 * Returns: the reference count after the increment
180 static inline IMG_UINT32 _HandleRef(HANDLE_DATA *psHandleData)
182 #if defined PVRSRV_DEBUG_HANDLE_LOCK
183 if(!OSLockIsLocked(gHandleLock))
185 PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
189 psHandleData->ui32RefCount++;
190 return psHandleData->ui32RefCount;
193 /* Decrease the reference count on the given handle.
194 * The handle lock must already be acquired.
195 * Returns: the reference count after the decrement
197 static inline IMG_UINT32 _HandleUnref(HANDLE_DATA *psHandleData)
199 #if defined PVRSRV_DEBUG_HANDLE_LOCK
200 if(!OSLockIsLocked(gHandleLock))
202 PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
206 PVR_ASSERT(psHandleData->ui32RefCount > 0);
207 psHandleData->ui32RefCount--;
209 return psHandleData->ui32RefCount;
213 ******************************************************************************
215 @Function GetHandleData
217 @Description Get the handle data structure for a given handle
219 @Input psBase - pointer to handle base structure
220 ppsHandleData - location to return pointer to handle data structure
221 hHandle - handle from client
222 eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the
223 handle type is not to be checked.
225 @Output ppsHandleData - points to a pointer to the handle data structure
227 @Return Error code or PVRSRV_OK
229 ******************************************************************************/
230 #ifdef INLINE_IS_PRAGMA
231 #pragma inline(GetHandleData)
234 PVRSRV_ERROR GetHandleData(PVRSRV_HANDLE_BASE *psBase,
235 HANDLE_DATA **ppsHandleData,
237 PVRSRV_HANDLE_TYPE eType)
239 HANDLE_DATA *psHandleData;
242 eError = gpsHandleFuncs->pfnGetHandleData(psBase->psImplBase,
244 (void **)&psHandleData);
245 if (eError != PVRSRV_OK)
251 * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function,
252 * check handle is of the correct type.
254 if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandleData->eType)
256 PVR_DPF((PVR_DBG_ERROR,
257 "GetHandleData: Handle type mismatch (%d != %d)",
258 eType, psHandleData->eType));
259 return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
262 /* Return the handle structure */
263 *ppsHandleData = psHandleData;
269 ******************************************************************************
271 @Function HandleListInit
273 @Description Initialise a linked list structure embedded in a handle
276 @Input hHandle - handle containing the linked list structure
277 psList - pointer to linked list structure
278 hParent - parent handle or NULL
280 ******************************************************************************/
281 #ifdef INLINE_IS_PRAGMA
282 #pragma inline(HandleListInit)
285 void HandleListInit(IMG_HANDLE hHandle, HANDLE_LIST *psList, IMG_HANDLE hParent)
287 psList->hPrev = hHandle;
288 psList->hNext = hHandle;
289 psList->hParent = hParent;
293 ******************************************************************************
295 @Function InitParentList
297 @Description Initialise the children list head in a handle structure.
298 The children are the subhandles of this handle.
300 @Input psHandleData - pointer to handle data structure
302 ******************************************************************************/
303 #ifdef INLINE_IS_PRAGMA
304 #pragma inline(InitParentList)
307 void InitParentList(HANDLE_DATA *psHandleData)
309 IMG_HANDLE hParent = psHandleData->hHandle;
311 HandleListInit(hParent, &psHandleData->sChildren, hParent);
315 ******************************************************************************
317 @Function InitChildEntry
319 @Description Initialise the child list entry in a handle structure.
320 The list entry is used to link together subhandles of
323 @Input psHandleData - pointer to handle data structure
325 ******************************************************************************/
326 #ifdef INLINE_IS_PRAGMA
327 #pragma inline(InitChildEntry)
330 void InitChildEntry(HANDLE_DATA *psHandleData)
332 HandleListInit(psHandleData->hHandle, &psHandleData->sSiblings, NULL);
336 ******************************************************************************
338 @Function HandleListIsEmpty
340 @Description Determine whether a given linked list is empty.
342 @Input hHandle - handle containing the list head
343 psList - pointer to the list head
345 @Return IMG_TRUE if the list is empty, IMG_FALSE if it isn't.
347 ******************************************************************************/
348 #ifdef INLINE_IS_PRAGMA
349 #pragma inline(HandleListIsEmpty)
352 IMG_BOOL HandleListIsEmpty(IMG_HANDLE hHandle, HANDLE_LIST *psList) /* Instead of passing in the handle can we not just do (psList->hPrev == psList->hNext) ? IMG_TRUE : IMG_FALSE ??? */
356 bIsEmpty = (IMG_BOOL)(psList->hNext == hHandle);
362 bIsEmpty2 = (IMG_BOOL)(psList->hPrev == hHandle);
363 PVR_ASSERT(bIsEmpty == bIsEmpty2);
372 ******************************************************************************
376 @Description Determine whether a handle has any subhandles
378 @Input psHandleData - pointer to handle data structure
380 @Return IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does.
382 ******************************************************************************/
383 #ifdef INLINE_IS_PRAGMA
384 #pragma inline(NoChildren)
387 IMG_BOOL NoChildren(HANDLE_DATA *psHandleData)
389 PVR_ASSERT(psHandleData->sChildren.hParent == psHandleData->hHandle);
391 return HandleListIsEmpty(psHandleData->hHandle, &psHandleData->sChildren);
395 ******************************************************************************
399 @Description Determine whether a handle is a subhandle
401 @Input psHandleData - pointer to handle data structure
403 @Return IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is.
405 ******************************************************************************/
406 #ifdef INLINE_IS_PRAGMA
407 #pragma inline(NoParent)
410 IMG_BOOL NoParent(HANDLE_DATA *psHandleData)
412 if (HandleListIsEmpty(psHandleData->hHandle, &psHandleData->sSiblings))
414 PVR_ASSERT(psHandleData->sSiblings.hParent == NULL);
420 PVR_ASSERT(psHandleData->sSiblings.hParent != NULL);
427 ******************************************************************************
429 @Function ParentHandle
431 @Description Determine the parent of a handle
433 @Input psHandleData - pointer to handle data structure
435 @Return Parent handle, or NULL if the handle is not a subhandle.
437 ******************************************************************************/
438 #ifdef INLINE_IS_PRAGMA
439 #pragma inline(ParentHandle)
442 IMG_HANDLE ParentHandle(HANDLE_DATA *psHandleData)
444 return psHandleData->sSiblings.hParent;
448 * GetHandleListFromHandleAndOffset is used to generate either a
449 * pointer to the subhandle list head, or a pointer to the linked list
450 * structure of an item on a subhandle list.
451 * The list head is itself on the list, but is at a different offset
452 * in the handle structure to the linked list structure for items on
453 * the list. The two linked list structures are differentiated by
454 * the third parameter, containing the parent handle. The parent field
455 * in the list head structure references the handle structure that contains
456 * it. For items on the list, the parent field in the linked list structure
457 * references the parent handle, which will be different from the handle
458 * containing the linked list structure.
460 #ifdef INLINE_IS_PRAGMA
461 #pragma inline(GetHandleListFromHandleAndOffset)
464 HANDLE_LIST *GetHandleListFromHandleAndOffset(PVRSRV_HANDLE_BASE *psBase,
467 size_t uiParentOffset,
468 size_t uiEntryOffset)
470 HANDLE_DATA *psHandleData = NULL;
473 PVR_ASSERT(psBase != NULL);
475 eError = GetHandleData(psBase,
478 PVRSRV_HANDLE_TYPE_NONE);
479 if (eError != PVRSRV_OK)
484 if (hEntry == hParent)
486 return (HANDLE_LIST *)((IMG_CHAR *)psHandleData + uiParentOffset);
490 return (HANDLE_LIST *)((IMG_CHAR *)psHandleData + uiEntryOffset);
495 ******************************************************************************
497 @Function HandleListInsertBefore
499 @Description Insert a handle before a handle currently on the list.
501 @Input hEntry - handle to be inserted after
502 psEntry - pointer to handle structure to be inserted after
503 uiParentOffset - offset to list head struct in handle structure
504 hNewEntry - handle to be inserted
505 psNewEntry - pointer to handle structure of item to be inserted
506 uiEntryOffset - offset of list item struct in handle structure
507 hParent - parent handle of hNewEntry
509 @Return Error code or PVRSRV_OK
511 ******************************************************************************/
512 #ifdef INLINE_IS_PRAGMA
513 #pragma inline(HandleListInsertBefore)
516 PVRSRV_ERROR HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase,
518 HANDLE_LIST *psEntry,
519 size_t uiParentOffset,
520 IMG_HANDLE hNewEntry,
521 HANDLE_LIST *psNewEntry,
522 size_t uiEntryOffset,
525 HANDLE_LIST *psPrevEntry;
527 if (psBase == NULL || psEntry == NULL || psNewEntry == NULL)
529 return PVRSRV_ERROR_INVALID_PARAMS;
532 psPrevEntry = GetHandleListFromHandleAndOffset(psBase,
537 if (psPrevEntry == NULL)
539 return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
542 PVR_ASSERT(psNewEntry->hParent == NULL);
543 PVR_ASSERT(hEntry == psPrevEntry->hNext);
547 HANDLE_LIST *psParentList;
549 psParentList = GetHandleListFromHandleAndOffset(psBase,
554 PVR_ASSERT(psParentList && psParentList->hParent == hParent);
556 #endif /* defined(DEBUG) */
558 psNewEntry->hPrev = psEntry->hPrev;
559 psEntry->hPrev = hNewEntry;
561 psNewEntry->hNext = hEntry;
562 psPrevEntry->hNext = hNewEntry;
564 psNewEntry->hParent = hParent;
570 ******************************************************************************
574 @Description Assign a subhandle to a handle
576 @Input psParentData - pointer to handle structure of parent handle
577 psChildData - pointer to handle structure of child subhandle
579 @Return Error code or PVRSRV_OK
581 ******************************************************************************/
582 #ifdef INLINE_IS_PRAGMA
583 #pragma inline(AdoptChild)
586 PVRSRV_ERROR AdoptChild(PVRSRV_HANDLE_BASE *psBase,
587 HANDLE_DATA *psParentData,
588 HANDLE_DATA *psChildData)
590 IMG_HANDLE hParent = psParentData->sChildren.hParent;
592 PVR_ASSERT(hParent == psParentData->hHandle);
594 return HandleListInsertBefore(psBase,
596 &psParentData->sChildren,
597 offsetof(HANDLE_DATA, sChildren),
598 psChildData->hHandle,
599 &psChildData->sSiblings,
600 offsetof(HANDLE_DATA, sSiblings),
605 ******************************************************************************
607 @Function HandleListRemove
609 @Description Remove a handle from a list
611 @Input hEntry - handle to be removed
612 psEntry - pointer to handle structure of item to be removed
613 uiEntryOffset - offset of list item struct in handle structure
614 uiParentOffset - offset to list head struct in handle structure
616 @Return Error code or PVRSRV_OK
618 ******************************************************************************/
619 #ifdef INLINE_IS_PRAGMA
620 #pragma inline(HandleListRemove)
623 PVRSRV_ERROR HandleListRemove(PVRSRV_HANDLE_BASE *psBase,
625 HANDLE_LIST *psEntry,
626 size_t uiEntryOffset,
627 size_t uiParentOffset)
629 if (psBase == NULL || psEntry == NULL)
631 return PVRSRV_ERROR_INVALID_PARAMS;
634 if (!HandleListIsEmpty(hEntry, psEntry))
639 psPrev = GetHandleListFromHandleAndOffset(psBase,
646 return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
649 psNext = GetHandleListFromHandleAndOffset(psBase,
656 return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
660 * The list head is on the list, and we don't want to
663 PVR_ASSERT(psEntry->hParent != NULL);
665 psPrev->hNext = psEntry->hNext;
666 psNext->hPrev = psEntry->hPrev;
668 HandleListInit(hEntry, psEntry, NULL);
675 ******************************************************************************
677 @Function UnlinkFromParent
679 @Description Remove a subhandle from its parents list
681 @Input psHandleData - pointer to handle data structure of child subhandle
683 @Return Error code or PVRSRV_OK
685 ******************************************************************************/
686 #ifdef INLINE_IS_PRAGMA
687 #pragma inline(UnlinkFromParent)
690 PVRSRV_ERROR UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase,
691 HANDLE_DATA *psHandleData)
693 return HandleListRemove(psBase,
694 psHandleData->hHandle,
695 &psHandleData->sSiblings,
696 offsetof(HANDLE_DATA, sSiblings),
697 offsetof(HANDLE_DATA, sChildren));
701 ******************************************************************************
703 @Function HandleListIterate
705 @Description Iterate over the items in a list
707 @Input psHead - pointer to list head
708 uiParentOffset - offset to list head struct in handle structure
709 uiEntryOffset - offset of list item struct in handle structure
710 pfnIterFunc - function to be called for each handle in the list
712 @Return Error code or PVRSRV_OK
714 ******************************************************************************/
715 #ifdef INLINE_IS_PRAGMA
716 #pragma inline(HandleListIterate)
719 PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase,
721 size_t uiParentOffset,
722 size_t uiEntryOffset,
723 PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, IMG_HANDLE))
725 IMG_HANDLE hHandle = psHead->hNext;
726 IMG_HANDLE hParent = psHead->hParent;
729 PVR_ASSERT(psHead->hParent != NULL);
732 * Follow the next chain from the list head until we reach
733 * the list head again, which signifies the end of the list.
735 while (hHandle != hParent)
737 HANDLE_LIST *psEntry;
740 psEntry = GetHandleListFromHandleAndOffset(psBase,
747 return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
750 PVR_ASSERT(psEntry->hParent == psHead->hParent);
753 * Get the next index now, in case the list item is
754 * modified by the iteration function.
756 hNext = psEntry->hNext;
758 eError = (*pfnIterFunc)(psBase, hHandle);
759 if (eError != PVRSRV_OK)
771 ******************************************************************************
773 @Function IterateOverChildren
775 @Description Iterate over the subhandles of a parent handle
777 @Input psParentData - pointer to parent handle structure
778 pfnIterFunc - function to be called for each subhandle
780 @Return Error code or PVRSRV_OK
782 ******************************************************************************/
783 #ifdef INLINE_IS_PRAGMA
784 #pragma inline(IterateOverChildren)
787 PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase,
788 HANDLE_DATA *psParentData,
789 PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, IMG_HANDLE))
791 return HandleListIterate(psBase,
792 &psParentData->sChildren,
793 offsetof(HANDLE_DATA, sChildren),
794 offsetof(HANDLE_DATA, sSiblings),
799 ******************************************************************************
801 @Function ParentIfPrivate
803 @Description Return the parent handle if the handle was allocated
804 with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return
807 @Input psHandleData - pointer to handle data structure
809 @Return Parent handle, or NULL
811 ******************************************************************************/
812 #ifdef INLINE_IS_PRAGMA
813 #pragma inline(ParentIfPrivate)
816 IMG_HANDLE ParentIfPrivate(HANDLE_DATA *psHandleData)
818 return TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
819 ParentHandle(psHandleData) : NULL;
823 ******************************************************************************
827 @Description Initialise a hash table key for the current process
829 @Input psBase - pointer to handle base structure
830 aKey - pointer to key
831 pvData - pointer to the resource the handle represents
832 eType - type of resource
834 ******************************************************************************/
835 #ifdef INLINE_IS_PRAGMA
836 #pragma inline(InitKey)
839 void InitKey(HAND_KEY aKey,
840 PVRSRV_HANDLE_BASE *psBase,
842 PVRSRV_HANDLE_TYPE eType,
845 PVR_UNREFERENCED_PARAMETER(psBase);
847 aKey[HAND_KEY_DATA] = (uintptr_t)pvData;
848 aKey[HAND_KEY_TYPE] = (uintptr_t)eType;
849 aKey[HAND_KEY_PARENT] = (uintptr_t)hParent;
852 static PVRSRV_ERROR FreeHandleWrapper(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle);
855 ******************************************************************************
859 @Description Free a handle data structure.
861 @Input psBase - Pointer to handle base structure
862 hHandle - Handle to be freed
863 eType - Type of the handle to be freed
864 ppvData - Location for data associated with the freed handle
866 @Output ppvData - Points to data that was associated with the freed handle
868 @Return PVRSRV_OK or PVRSRV_ERROR
870 ******************************************************************************/
871 static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase,
873 PVRSRV_HANDLE_TYPE eType,
876 HANDLE_DATA *psHandleData = NULL;
877 HANDLE_DATA *psReleasedHandleData;
880 eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
881 if (eError != PVRSRV_OK)
886 if(_HandleUnref(psHandleData) > 0)
888 /* this handle still has references so do not destroy it
889 * or the underlying object yet
894 /* Call the release data callback for each reference on the handle */
895 if (psHandleData->pfnReleaseData != NULL)
897 eError = psHandleData->pfnReleaseData(psHandleData->pvData);
898 if (eError == PVRSRV_ERROR_RETRY)
900 PVR_DPF((PVR_DBG_MESSAGE,
902 "Got retry while calling release data callback for %p (type = %d)",
904 (IMG_UINT32)psHandleData->eType));
906 /* the caller should retry, so retain a reference on the handle */
907 _HandleRef(psHandleData);
911 else if (eError != PVRSRV_OK)
917 if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
920 IMG_HANDLE hRemovedHandle;
922 InitKey(aKey, psBase, psHandleData->pvData, psHandleData->eType, ParentIfPrivate(psHandleData));
924 hRemovedHandle = (IMG_HANDLE)HASH_Remove_Extended(psBase->psHashTab, aKey);
926 PVR_ASSERT(hRemovedHandle != NULL);
927 PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
928 PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
931 eError = UnlinkFromParent(psBase, psHandleData);
932 if (eError != PVRSRV_OK)
934 PVR_DPF((PVR_DBG_ERROR,
935 "FreeHandle: Error whilst unlinking from parent handle (%s)",
936 PVRSRVGetErrorStringKM(eError)));
941 eError = IterateOverChildren(psBase, psHandleData, FreeHandleWrapper);
942 if (eError != PVRSRV_OK)
944 PVR_DPF((PVR_DBG_ERROR,
945 "FreeHandle: Error whilst freeing subhandles (%s)",
946 PVRSRVGetErrorStringKM(eError)));
950 eError = gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase,
951 psHandleData->hHandle,
952 (void **)&psReleasedHandleData);
953 if (eError == PVRSRV_OK)
955 PVR_ASSERT(psReleasedHandleData == psHandleData);
960 *ppvData = psHandleData->pvData;
963 OSFreeMem(psHandleData);
968 static PVRSRV_ERROR FreeHandleWrapper(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle)
970 return FreeHandle(psBase, hHandle, PVRSRV_HANDLE_TYPE_NONE, NULL);
974 ******************************************************************************
978 @Description Find handle corresponding to a resource pointer
980 @Input psBase - pointer to handle base structure
981 pvData - pointer to resource to be associated with the handle
982 eType - the type of resource
984 @Return the handle, or NULL if not found
986 ******************************************************************************/
987 #ifdef INLINE_IS_PRAGMA
988 #pragma inline(FindHandle)
991 IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase,
993 PVRSRV_HANDLE_TYPE eType,
998 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1000 InitKey(aKey, psBase, pvData, eType, hParent);
1002 return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
1006 ******************************************************************************
1008 @Function AllocHandle
1010 @Description Allocate a new handle
1012 @Input phHandle - location for new handle
1013 pvData - pointer to resource to be associated with the handle
1014 eType - the type of resource
1015 hParent - parent handle or NULL
1016 pfnReleaseData - Function to release resource at handle release
1019 @Output phHandle - points to new handle
1021 @Return Error code or PVRSRV_OK
1023 ******************************************************************************/
1024 static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase,
1025 IMG_HANDLE *phHandle,
1027 PVRSRV_HANDLE_TYPE eType,
1028 PVRSRV_HANDLE_ALLOC_FLAG eFlag,
1030 PFN_HANDLE_RELEASE pfnReleaseData)
1032 HANDLE_DATA *psNewHandleData;
1034 PVRSRV_ERROR eError;
1036 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1037 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1038 PVR_ASSERT(psBase != NULL && psBase->psHashTab != NULL);
1039 PVR_ASSERT(gpsHandleFuncs);
1041 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1043 /* Handle must not already exist */
1044 PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == NULL);
1047 psNewHandleData = OSAllocZMem(sizeof(*psNewHandleData));
1048 if (psNewHandleData == NULL)
1050 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't allocate handle data"));
1051 return PVRSRV_ERROR_OUT_OF_MEMORY;
1054 eError = gpsHandleFuncs->pfnAcquireHandle(psBase->psImplBase, &hHandle, psNewHandleData);
1055 if (eError != PVRSRV_OK)
1057 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Failed to acquire a handle"));
1058 goto ErrorFreeHandleData;
1062 * If a data pointer can be associated with multiple handles, we
1063 * don't put the handle in the hash table, as the data pointer
1064 * may not map to a unique handle
1066 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
1070 /* Initialise hash key */
1071 InitKey(aKey, psBase, pvData, eType, hParent);
1073 /* Put the new handle in the hash table */
1074 if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (uintptr_t)hHandle))
1076 PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
1077 eError = PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
1078 goto ErrorReleaseHandle;
1082 psNewHandleData->hHandle = hHandle;
1083 psNewHandleData->eType = eType;
1084 psNewHandleData->eFlag = eFlag;
1085 psNewHandleData->pvData = pvData;
1086 psNewHandleData->pfnReleaseData = pfnReleaseData;
1087 psNewHandleData->ui32RefCount = 1;
1089 InitParentList(psNewHandleData);
1091 PVR_ASSERT(NoChildren(psNewHandleData));
1094 InitChildEntry(psNewHandleData);
1096 PVR_ASSERT(NoParent(psNewHandleData));
1099 /* Return the new handle to the client */
1100 *phHandle = psNewHandleData->hHandle;
1105 (void)gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, hHandle, NULL);
1107 ErrorFreeHandleData:
1108 OSFreeMem(psNewHandleData);
1114 ******************************************************************************
1116 @Function PVRSRVAllocHandle
1118 @Description Allocate a handle
1120 @Input phHandle - location for new handle
1121 pvData - pointer to resource to be associated with the handle
1122 eType - the type of resource
1123 pfnReleaseData - Function to release resource at handle release
1126 @Output phHandle - points to new handle
1128 @Return Error code or PVRSRV_OK
1130 ******************************************************************************/
1131 PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
1132 IMG_HANDLE *phHandle,
1134 PVRSRV_HANDLE_TYPE eType,
1135 PVRSRV_HANDLE_ALLOC_FLAG eFlag,
1136 PFN_HANDLE_RELEASE pfnReleaseData)
1138 PVRSRV_ERROR eError;
1141 eError = PVRSRVAllocHandleUnlocked(psBase, phHandle, pvData, eType, eFlag, pfnReleaseData);
1148 ******************************************************************************
1150 @Function PVRSRVAllocHandleUnlocked
1152 @Description Allocate a handle without acquiring/releasing the handle
1153 lock. The function assumes you hold the lock when called.
1155 @Input phHandle - location for new handle
1156 pvData - pointer to resource to be associated with the handle
1157 eType - the type of resource
1158 pfnReleaseData - Function to release resource at handle release
1161 @Output phHandle - points to new handle
1163 @Return Error code or PVRSRV_OK
1165 ******************************************************************************/
1166 PVRSRV_ERROR PVRSRVAllocHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
1167 IMG_HANDLE *phHandle,
1169 PVRSRV_HANDLE_TYPE eType,
1170 PVRSRV_HANDLE_ALLOC_FLAG eFlag,
1171 PFN_HANDLE_RELEASE pfnReleaseData)
1173 PVRSRV_ERROR eError;
1177 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1178 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1179 PVR_ASSERT(gpsHandleFuncs);
1183 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing handle base"));
1184 eError = PVRSRV_ERROR_INVALID_PARAMS;
1188 if (pfnReleaseData == NULL)
1190 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing release function"));
1191 eError = PVRSRV_ERROR_INVALID_PARAMS;
1195 eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, NULL, pfnReleaseData);
1202 ******************************************************************************
1204 @Function PVRSRVAllocSubHandle
1206 @Description Allocate a subhandle
1208 @Input phHandle - location for new subhandle
1209 pvData - pointer to resource to be associated with the subhandle
1210 eType - the type of resource
1211 hParent - parent handle
1213 @Output phHandle - points to new subhandle
1215 @Return Error code or PVRSRV_OK
1217 ******************************************************************************/
1218 PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase,
1219 IMG_HANDLE *phHandle,
1221 PVRSRV_HANDLE_TYPE eType,
1222 PVRSRV_HANDLE_ALLOC_FLAG eFlag,
1225 PVRSRV_ERROR eError;
1228 eError = PVRSRVAllocSubHandleUnlocked(psBase, phHandle, pvData, eType, eFlag, hParent);
1235 ******************************************************************************
1237 @Function PVRSRVAllocSubHandleUnlocked
1239 @Description Allocate a subhandle without acquiring/releasing the
1240 handle lock. The function assumes you hold the lock when called.
1242 @Input phHandle - location for new subhandle
1243 pvData - pointer to resource to be associated with the subhandle
1244 eType - the type of resource
1245 hParent - parent handle
1247 @Output phHandle - points to new subhandle
1249 @Return Error code or PVRSRV_OK
1251 ******************************************************************************/
1252 PVRSRV_ERROR PVRSRVAllocSubHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
1253 IMG_HANDLE *phHandle,
1255 PVRSRV_HANDLE_TYPE eType,
1256 PVRSRV_HANDLE_ALLOC_FLAG eFlag,
1259 HANDLE_DATA *psPHandleData = NULL;
1260 HANDLE_DATA *psCHandleData = NULL;
1261 IMG_HANDLE hParentKey;
1263 PVRSRV_ERROR eError;
1267 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1268 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1269 PVR_ASSERT(gpsHandleFuncs);
1273 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Missing handle base"));
1274 eError = PVRSRV_ERROR_INVALID_PARAMS;
1278 hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ? hParent : NULL;
1280 /* Lookup the parent handle */
1281 eError = GetHandleData(psBase, &psPHandleData, hParent, PVRSRV_HANDLE_TYPE_NONE);
1282 if (eError != PVRSRV_OK)
1284 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
1288 eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey, NULL);
1289 if (eError != PVRSRV_OK)
1294 eError = GetHandleData(psBase, &psCHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
1295 if (eError != PVRSRV_OK)
1297 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
1299 /* If we were able to allocate the handle then there should be no reason why we
1300 can't also get it's handle structure. Otherwise something has gone badly wrong. */
1301 PVR_ASSERT(eError == PVRSRV_OK);
1307 * Get the parent handle structure again, in case the handle
1308 * structure has moved (depending on the implementation
1311 eError = GetHandleData(psBase, &psPHandleData, hParent, PVRSRV_HANDLE_TYPE_NONE);
1312 if (eError != PVRSRV_OK)
1314 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Failed to get parent handle structure"));
1316 (void)FreeHandle(psBase, hHandle, eType, NULL);
1320 eError = AdoptChild(psBase, psPHandleData, psCHandleData);
1321 if (eError != PVRSRV_OK)
1323 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Parent handle failed to adopt subhandle"));
1325 (void)FreeHandle(psBase, hHandle, eType, NULL);
1329 *phHandle = hHandle;
1338 ******************************************************************************
1340 @Function PVRSRVFindHandle
1342 @Description Find handle corresponding to a resource pointer
1344 @Input phHandle - location for returned handle
1345 pvData - pointer to resource to be associated with the handle
1346 eType - the type of resource
1348 @Output phHandle - points to handle
1350 @Return Error code or PVRSRV_OK
1352 ******************************************************************************/
1353 PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
1354 IMG_HANDLE *phHandle,
1356 PVRSRV_HANDLE_TYPE eType)
1358 PVRSRV_ERROR eError;
1361 eError = PVRSRVFindHandleUnlocked(psBase, phHandle, pvData, eType);
1368 ******************************************************************************
1370 @Function PVRSRVFindHandleUnlocked
1372 @Description Find handle corresponding to a resource pointer without
1373 acquiring/releasing the handle lock. The function assumes you hold
1374 the lock when called.
1376 @Input phHandle - location for returned handle
1377 pvData - pointer to resource to be associated with the handle
1378 eType - the type of resource
1380 @Output phHandle - points to handle
1382 @Return Error code or PVRSRV_OK
1384 ******************************************************************************/
1385 PVRSRV_ERROR PVRSRVFindHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
1386 IMG_HANDLE *phHandle,
1388 PVRSRV_HANDLE_TYPE eType)
1391 PVRSRV_ERROR eError;
1393 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1394 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1395 PVR_ASSERT(gpsHandleFuncs);
1399 PVR_DPF((PVR_DBG_ERROR, "PVRSRVFindHandle: Missing handle base"));
1400 eError = PVRSRV_ERROR_INVALID_PARAMS;
1404 /* See if there is a handle for this data pointer */
1405 hHandle = FindHandle(psBase, pvData, eType, NULL);
1406 if (hHandle == NULL)
1408 PVR_DPF((PVR_DBG_ERROR,
1409 "PVRSRVFindHandle: Error finding handle. Type %u",
1412 eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
1416 *phHandle = hHandle;
1426 ******************************************************************************
1428 @Function PVRSRVLookupHandle
1430 @Description Lookup the data pointer corresponding to a handle
1432 @Input ppvData - location to return data pointer
1433 hHandle - handle from client
1435 bRef - If TRUE, a reference will be added on the handle if the
1436 lookup is successful.
1438 @Output ppvData - points to the data pointer
1440 @Return Error code or PVRSRV_OK
1442 ******************************************************************************/
1443 PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
1446 PVRSRV_HANDLE_TYPE eType,
1449 PVRSRV_ERROR eError;
1452 eError = PVRSRVLookupHandleUnlocked(psBase, ppvData, hHandle, eType, bRef);
1459 ******************************************************************************
1461 @Function PVRSRVLookupHandleUnlocked
1463 @Description Lookup the data pointer corresponding to a handle without
1464 acquiring/releasing the handle lock. The function assumes you
1465 hold the lock when called.
1467 @Input ppvData - location to return data pointer
1468 hHandle - handle from client
1470 bRef - If TRUE, a reference will be added on the handle if the
1471 lookup is successful.
1473 @Output ppvData - points to the data pointer
1475 @Return Error code or PVRSRV_OK
1477 ******************************************************************************/
1478 PVRSRV_ERROR PVRSRVLookupHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
1481 PVRSRV_HANDLE_TYPE eType,
1484 HANDLE_DATA *psHandleData = NULL;
1485 PVRSRV_ERROR eError;
1487 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1488 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1489 PVR_ASSERT(gpsHandleFuncs);
1493 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Missing handle base"));
1494 eError = PVRSRV_ERROR_INVALID_PARAMS;
1498 eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
1499 if (eError != PVRSRV_OK)
1501 PVR_DPF((PVR_DBG_ERROR,
1502 "PVRSRVLookupHandle: Error looking up handle (%s). Handle %p, type %u",
1503 PVRSRVGetErrorStringKM(eError),
1506 #if defined(DEBUG) || defined(PVRSRV_NEED_PVR_DPF)
1514 _HandleRef(psHandleData);
1517 *ppvData = psHandleData->pvData;
1527 ******************************************************************************
1529 @Function PVRSRVLookupSubHandle
1531 @Description Lookup the data pointer corresponding to a subhandle
1533 @Input ppvData - location to return data pointer
1534 hHandle - handle from client
1536 hAncestor - ancestor handle
1538 @Output ppvData - points to the data pointer
1540 @Return Error code or PVRSRV_OK
1542 ******************************************************************************/
1543 PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase,
1546 PVRSRV_HANDLE_TYPE eType,
1547 IMG_HANDLE hAncestor)
1549 HANDLE_DATA *psPHandleData = NULL;
1550 HANDLE_DATA *psCHandleData = NULL;
1551 PVRSRV_ERROR eError;
1553 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1554 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1555 PVR_ASSERT(gpsHandleFuncs);
1561 PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Missing handle base"));
1562 eError = PVRSRV_ERROR_INVALID_PARAMS;
1566 eError = GetHandleData(psBase, &psCHandleData, hHandle, eType);
1567 if (eError != PVRSRV_OK)
1569 PVR_DPF((PVR_DBG_ERROR,
1570 "PVRSRVLookupSubHandle: Error looking up subhandle (%s). Handle %p, type %u",
1571 PVRSRVGetErrorStringKM(eError),
1578 /* Look for hAncestor among the handle's ancestors */
1579 for (psPHandleData = psCHandleData; ParentHandle(psPHandleData) != hAncestor; )
1581 eError = GetHandleData(psBase, &psPHandleData, ParentHandle(psPHandleData), PVRSRV_HANDLE_TYPE_NONE);
1582 if (eError != PVRSRV_OK)
1584 PVR_DPF((PVR_DBG_ERROR,"PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
1585 eError = PVRSRV_ERROR_INVALID_SUBHANDLE;
1590 *ppvData = psCHandleData->pvData;
1601 ******************************************************************************
1603 @Function PVRSRVGetParentHandle
1605 @Description Lookup the parent of a handle
1607 @Input phParent - location for returning parent handle
1608 hHandle - handle for which the parent handle is required
1610 hParent - parent handle
1612 @Output *phParent - parent handle, or NULL if there is no parent
1614 @Return Error code or PVRSRV_OK. Note that not having a parent is
1615 not regarded as an error.
1617 ******************************************************************************/
1618 PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
1619 IMG_HANDLE *phParent,
1621 PVRSRV_HANDLE_TYPE eType)
1623 HANDLE_DATA *psHandleData = NULL;
1624 PVRSRV_ERROR eError;
1626 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1627 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1628 PVR_ASSERT(gpsHandleFuncs);
1634 PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Missing handle base"));
1635 eError = PVRSRV_ERROR_INVALID_PARAMS;
1639 eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
1640 if (eError != PVRSRV_OK)
1642 PVR_DPF((PVR_DBG_ERROR,
1643 "PVRSRVGetParentHandle: Error looking up subhandle (%s). Type %u",
1644 PVRSRVGetErrorStringKM(eError),
1650 *phParent = ParentHandle(psHandleData);
1661 ******************************************************************************
1663 @Function PVRSRVReleaseHandle
1665 @Description Release a handle that is no longer needed
1667 @Input hHandle - handle from client
1670 @Return Error code or PVRSRV_OK
1672 ******************************************************************************/
1673 PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
1675 PVRSRV_HANDLE_TYPE eType)
1677 PVRSRV_ERROR eError;
1680 eError = PVRSRVReleaseHandleUnlocked(psBase, hHandle, eType);
1688 ******************************************************************************
1690 @Function PVRSRVReleaseHandleUnlocked
1692 @Description Release a handle that is no longer needed without
1693 acquiring/releasing the handle lock. The function assumes you
1694 hold the lock when called.
1696 @Input hHandle - handle from client
1699 @Return Error code or PVRSRV_OK
1701 ******************************************************************************/
1702 PVRSRV_ERROR PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
1704 PVRSRV_HANDLE_TYPE eType)
1706 PVRSRV_ERROR eError;
1708 /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
1709 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1710 PVR_ASSERT(gpsHandleFuncs);
1714 PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Missing handle base"));
1715 eError = PVRSRV_ERROR_INVALID_PARAMS;
1719 eError = FreeHandle(psBase, hHandle, eType, NULL);
1727 ******************************************************************************
1729 @Function PVRSRVPurgeHandles
1731 @Description Purge handles for a given handle base
1733 @Input psBase - pointer to handle base structure
1735 @Return Error code or PVRSRV_OK
1737 ******************************************************************************/
1738 PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
1740 PVRSRV_ERROR eError;
1742 PVR_ASSERT(gpsHandleFuncs);
1748 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Missing handle base"));
1749 eError = PVRSRV_ERROR_INVALID_PARAMS;
1753 eError = gpsHandleFuncs->pfnPurgeHandles(psBase->psImplBase);
1762 ******************************************************************************
1764 @Function PVRSRVAllocHandleBase
1766 @Description Allocate a handle base structure for a process
1768 @Input ppsBase - pointer to handle base structure pointer
1770 @Output ppsBase - points to handle base structure pointer
1772 @Return Error code or PVRSRV_OK
1774 ******************************************************************************/
1775 PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase,
1776 PVRSRV_HANDLE_BASE_TYPE eType)
1778 PVRSRV_HANDLE_BASE *psBase;
1779 PVRSRV_ERROR eError;
1781 if (gpsHandleFuncs == NULL)
1783 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Handle management not initialised"));
1784 return PVRSRV_ERROR_NOT_READY;
1789 if (ppsBase == NULL)
1791 eError = PVRSRV_ERROR_INVALID_PARAMS;
1795 psBase = OSAllocZMem(sizeof(*psBase));
1798 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base"));
1799 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1803 psBase->eType = eType;
1805 eError = gpsHandleFuncs->pfnCreateHandleBase(&psBase->psImplBase);
1806 if (eError != PVRSRV_OK)
1808 goto ErrorFreeHandleBase;
1811 psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE,
1814 HASH_Key_Comp_Default);
1815 if (psBase->psHashTab == NULL)
1817 PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table"));
1818 eError = PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
1819 goto ErrorDestroyHandleBase;
1828 ErrorDestroyHandleBase:
1829 (void)gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase);
1831 ErrorFreeHandleBase:
1841 typedef struct _COUNT_HANDLE_DATA_
1843 PVRSRV_HANDLE_BASE *psBase;
1844 IMG_UINT32 uiHandleDataCount;
1845 } COUNT_HANDLE_DATA;
1847 /* Used to count the number of handles that have data associated with them */
1848 static PVRSRV_ERROR CountHandleDataWrapper(IMG_HANDLE hHandle, void *pvData)
1850 COUNT_HANDLE_DATA *psData = (COUNT_HANDLE_DATA *)pvData;
1851 HANDLE_DATA *psHandleData = NULL;
1852 PVRSRV_ERROR eError;
1854 PVR_ASSERT(gpsHandleFuncs);
1856 if (psData == NULL ||
1857 psData->psBase == NULL)
1859 PVR_DPF((PVR_DBG_ERROR, "CountHandleDataWrapper: Missing free data"));
1860 return PVRSRV_ERROR_INVALID_PARAMS;
1863 eError = GetHandleData(psData->psBase,
1866 PVRSRV_HANDLE_TYPE_NONE);
1867 if (eError != PVRSRV_OK)
1869 PVR_DPF((PVR_DBG_ERROR, "CountHandleDataWrapper: Couldn't get handle data for handle"));
1873 if (psHandleData != NULL)
1875 psData->uiHandleDataCount++;
1881 /* Print a handle in the handle base. Used with the iterator callback. */
1882 static PVRSRV_ERROR ListHandlesInBase(IMG_HANDLE hHandle, void *pvData)
1884 PVRSRV_HANDLE_BASE *psBase = (PVRSRV_HANDLE_BASE*) pvData;
1885 HANDLE_DATA *psHandleData = NULL;
1886 PVRSRV_ERROR eError;
1888 PVR_ASSERT(gpsHandleFuncs);
1892 PVR_DPF((PVR_DBG_ERROR, "%s: Missing base", __func__));
1893 return PVRSRV_ERROR_INVALID_PARAMS;
1896 eError = GetHandleData(psBase,
1899 PVRSRV_HANDLE_TYPE_NONE);
1900 if (eError != PVRSRV_OK)
1902 PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get handle data for handle", __func__));
1906 if (psHandleData != NULL)
1908 PVR_DPF((PVR_DBG_WARNING, " Handle: %6u, Type: %3u, Refs: %3u",
1909 (IMG_UINT32) (uintptr_t) psHandleData->hHandle,
1910 psHandleData->eType,
1911 psHandleData->ui32RefCount));
1920 #endif /* defined(DEBUG) */
1922 typedef struct FREE_HANDLE_DATA_TAG
1924 PVRSRV_HANDLE_BASE *psBase;
1925 PVRSRV_HANDLE_TYPE eHandleFreeType;
1926 /* timing data (ns) to release bridge lock upon the deadline */
1927 IMG_UINT64 ui64TimeStart;
1928 IMG_UINT64 ui64MaxBridgeTime;
1931 static INLINE IMG_BOOL _CheckIfMaxTimeExpired(IMG_UINT64 ui64TimeStart, IMG_UINT64 ui64MaxBridgeTime)
1933 IMG_UINT64 ui64Diff;
1934 IMG_UINT64 ui64Now = OSClockns64();
1936 if(ui64Now >= ui64TimeStart)
1938 ui64Diff = ui64Now - ui64TimeStart;
1942 /* time has wrapped around */
1943 ui64Diff = (0xFFFFFFFFFFFFFFFF - ui64TimeStart) + ui64Now;
1946 return ui64Diff >= ui64MaxBridgeTime;
1949 static PVRSRV_ERROR FreeHandleDataWrapper(IMG_HANDLE hHandle, void *pvData)
1951 FREE_HANDLE_DATA *psData = (FREE_HANDLE_DATA *)pvData;
1952 HANDLE_DATA *psHandleData = NULL;
1953 PVRSRV_ERROR eError;
1955 PVR_ASSERT(gpsHandleFuncs);
1957 if (psData == NULL ||
1958 psData->psBase == NULL ||
1959 psData->eHandleFreeType == PVRSRV_HANDLE_TYPE_NONE)
1961 PVR_DPF((PVR_DBG_ERROR, "FreeHandleDataWrapper: Missing free data"));
1962 return PVRSRV_ERROR_INVALID_PARAMS;
1965 eError = GetHandleData(psData->psBase,
1968 PVRSRV_HANDLE_TYPE_NONE);
1969 if (eError != PVRSRV_OK)
1971 PVR_DPF((PVR_DBG_ERROR, "FreeHandleDataWrapper: Couldn't get handle data for handle"));
1975 if (psHandleData == NULL || psHandleData->eType != psData->eHandleFreeType)
1980 PVR_ASSERT(psHandleData->ui32RefCount > 0);
1982 while (psHandleData->ui32RefCount != 0)
1984 if (psHandleData->pfnReleaseData != NULL)
1986 eError = psHandleData->pfnReleaseData(psHandleData->pvData);
1987 if (eError == PVRSRV_ERROR_RETRY)
1989 PVR_DPF((PVR_DBG_MESSAGE,
1990 "FreeHandleDataWrapper: "
1991 "Got retry while calling release data callback for %p (type = %d)",
1993 (IMG_UINT32)psHandleData->eType));
1997 else if (eError != PVRSRV_OK)
2003 _HandleUnref(psHandleData);
2006 if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
2009 IMG_HANDLE hRemovedHandle;
2013 psHandleData->pvData,
2014 psHandleData->eType,
2015 ParentIfPrivate(psHandleData));
2017 hRemovedHandle = (IMG_HANDLE)HASH_Remove_Extended(psData->psBase->psHashTab, aKey);
2019 PVR_ASSERT(hRemovedHandle != NULL);
2020 PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
2021 PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
2024 eError = gpsHandleFuncs->pfnSetHandleData(psData->psBase->psImplBase, hHandle, NULL);
2025 if (eError != PVRSRV_OK)
2030 OSFreeMem(psHandleData);
2032 /* If we reach the end of the time slice release we can release the global
2033 * lock, invoke the scheduler and reacquire the lock */
2034 if((psData->ui64MaxBridgeTime != 0) && _CheckIfMaxTimeExpired(psData->ui64TimeStart, psData->ui64MaxBridgeTime))
2036 PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByCriteria: Lock timeout (timeout: %llu)",
2037 psData->ui64MaxBridgeTime));
2039 OSReleaseBridgeLock();
2040 /* Invoke the scheduler to check if other processes are waiting for the lock */
2041 OSReleaseThreadQuanta();
2042 OSAcquireBridgeLock();
2044 /* Set again lock timeout and reset the counter */
2045 psData->ui64TimeStart = OSClockns64();
2046 PVR_DPF((PVR_DBG_MESSAGE, "FreeResourceByCriteria: Lock acquired again"));
2052 static PVRSRV_HANDLE_TYPE g_aeOrderedFreeList[] =
2054 PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
2055 PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
2056 PVRSRV_HANDLE_TYPE_RGX_FW_MEMDESC,
2057 PVRSRV_HANDLE_TYPE_RGX_RTDATA_CLEANUP,
2058 PVRSRV_HANDLE_TYPE_RGX_FREELIST,
2059 PVRSRV_HANDLE_TYPE_RGX_RPM_FREELIST,
2060 PVRSRV_HANDLE_TYPE_RGX_SERVER_RPM_CONTEXT,
2061 PVRSRV_HANDLE_TYPE_RGX_MEMORY_BLOCK,
2062 PVRSRV_HANDLE_TYPE_RGX_POPULATION,
2063 PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER,
2064 PVRSRV_HANDLE_TYPE_RGX_FWIF_RENDERTARGET,
2065 PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT,
2066 PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT,
2067 PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT,
2068 PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
2069 PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
2070 PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
2071 PVRSRV_HANDLE_TYPE_RI_HANDLE,
2072 PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
2073 PVRSRV_HANDLE_TYPE_SERVER_OP_COOKIE,
2074 PVRSRV_HANDLE_TYPE_SERVER_SYNC_PRIMITIVE,
2075 PVRSRV_HANDLE_TYPE_SERVER_SYNC_EXPORT,
2076 PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
2077 PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING,
2078 PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION,
2079 PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP,
2080 PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT,
2081 PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA,
2082 PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX,
2083 PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_PAGELIST,
2084 PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_SECURE_EXPORT,
2085 PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT,
2086 PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
2087 PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT,
2088 PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE,
2089 PVRSRV_HANDLE_TYPE_DC_PIN_HANDLE,
2090 PVRSRV_HANDLE_TYPE_DC_BUFFER,
2091 PVRSRV_HANDLE_TYPE_DC_DISPLAY_CONTEXT,
2092 PVRSRV_HANDLE_TYPE_DC_DEVICE,
2093 PVRSRV_HANDLE_TYPE_PVR_TL_SD,
2094 PVRSRV_HANDLE_TYPE_MM_PLAT_CLEANUP
2098 ******************************************************************************
2100 @Function PVRSRVFreeHandleBase
2102 @Description Free a handle base structure
2104 @Input psBase - pointer to handle base structure
2106 @Return Error code or PVRSRV_OK
2108 ******************************************************************************/
2109 PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase, IMG_UINT64 ui64MaxBridgeTime)
2112 COUNT_HANDLE_DATA sCountData = { 0 };
2114 FREE_HANDLE_DATA sHandleData = { 0 };
2116 PVRSRV_ERROR eError;
2118 PVR_ASSERT(gpsHandleFuncs);
2122 sHandleData.psBase = psBase;
2123 sHandleData.ui64TimeStart = OSClockns64();
2124 sHandleData.ui64MaxBridgeTime = ui64MaxBridgeTime;
2129 sCountData.psBase = psBase;
2131 eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
2132 &CountHandleDataWrapper,
2133 (void *)&sCountData);
2134 if (eError != PVRSRV_OK)
2136 PVR_DPF((PVR_DBG_ERROR,
2137 "PVRSRVFreeHandleBase: Failed to perform handle count (%s)",
2138 PVRSRVGetErrorStringKM(eError)));
2142 if (sCountData.uiHandleDataCount != 0)
2144 IMG_BOOL bList = sCountData.uiHandleDataCount < HANDLE_DEBUG_LISTING_MAX_NUM;
2146 PVR_DPF((PVR_DBG_WARNING,
2147 "%s: %u remaining handles in handle base 0x%p "
2148 "(PVRSRV_HANDLE_BASE_TYPE %u). %s",
2150 sCountData.uiHandleDataCount,
2153 bList ? "Check handle.h for a type reference":
2154 "Skipping details, too many items..."));
2158 PVR_DPF((PVR_DBG_WARNING, "-------- Listing Handles --------"));
2159 eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
2162 PVR_DPF((PVR_DBG_WARNING, "-------- Done Listing --------"));
2166 #endif /* defined(DEBUG) */
2169 * As we're freeing handles based on type, make sure all
2170 * handles have actually had their data freed to avoid
2171 * resources being leaked
2173 for (i = 0; i < ARRAY_SIZE(g_aeOrderedFreeList); i++)
2175 sHandleData.eHandleFreeType = g_aeOrderedFreeList[i];
2177 /* Make sure all handles have been freed before destroying the handle base */
2178 eError = gpsHandleFuncs->pfnIterateOverHandles(psBase->psImplBase,
2179 &FreeHandleDataWrapper,
2180 (void *)&sHandleData);
2181 if (eError != PVRSRV_OK)
2188 if (psBase->psHashTab != NULL)
2190 HASH_Delete(psBase->psHashTab);
2193 eError = gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase);
2194 if (eError != PVRSRV_OK)
2210 ******************************************************************************
2212 @Function PVRSRVHandleInit
2214 @Description Initialise handle management
2216 @Return Error code or PVRSRV_OK
2218 ******************************************************************************/
2219 PVRSRV_ERROR PVRSRVHandleInit(void)
2221 PVRSRV_ERROR eError;
2223 PVR_ASSERT(gpsKernelHandleBase == NULL);
2224 PVR_ASSERT(gpsHandleFuncs == NULL);
2225 PVR_ASSERT(!gbLockInitialised);
2227 eError = OSLockCreate(&gHandleLock, LOCK_TYPE_PASSIVE);
2228 if (eError != PVRSRV_OK)
2230 PVR_DPF((PVR_DBG_ERROR,
2231 "PVRSRVHandleInit: Creation of handle global lock failed (%s)",
2232 PVRSRVGetErrorStringKM(eError)));
2235 gbLockInitialised = IMG_TRUE;
2237 eError = PVRSRVHandleGetFuncTable(&gpsHandleFuncs);
2238 if (eError != PVRSRV_OK)
2240 PVR_DPF((PVR_DBG_ERROR,
2241 "PVRSRVHandleInit: PVRSRVHandleGetFuncTable failed (%s)",
2242 PVRSRVGetErrorStringKM(eError)));
2243 goto ErrorHandleDeinit;
2246 eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase,
2247 PVRSRV_HANDLE_BASE_TYPE_GLOBAL);
2248 if (eError != PVRSRV_OK)
2250 PVR_DPF((PVR_DBG_ERROR,
2251 "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%s)",
2252 PVRSRVGetErrorStringKM(eError)));
2253 goto ErrorHandleDeinit;
2256 eError = gpsHandleFuncs->pfnEnableHandlePurging(gpsKernelHandleBase->psImplBase);
2257 if (eError != PVRSRV_OK)
2259 PVR_DPF((PVR_DBG_ERROR,
2260 "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%s)",
2261 PVRSRVGetErrorStringKM(eError)));
2262 goto ErrorHandleDeinit;
2268 (void) PVRSRVHandleDeInit();
2274 ******************************************************************************
2276 @Function PVRSRVHandleDeInit
2278 @Description De-initialise handle management
2280 @Return Error code or PVRSRV_OK
2282 ******************************************************************************/
2283 PVRSRV_ERROR PVRSRVHandleDeInit(void)
2285 PVRSRV_ERROR eError = PVRSRV_OK;
2287 if (gpsHandleFuncs != NULL)
2289 if (gpsKernelHandleBase != NULL)
2291 eError = PVRSRVFreeHandleBase(gpsKernelHandleBase, 0 /* do not release bridge lock */);
2292 if (eError == PVRSRV_OK)
2294 gpsKernelHandleBase = NULL;
2298 PVR_DPF((PVR_DBG_ERROR,
2299 "PVRSRVHandleDeInit: FreeHandleBase failed (%s)",
2300 PVRSRVGetErrorStringKM(eError)));
2304 if (eError == PVRSRV_OK)
2306 gpsHandleFuncs = NULL;
2311 /* If we don't have a handle function table we shouldn't have a handle base either */
2312 PVR_ASSERT(gpsKernelHandleBase == NULL);
2315 if (gbLockInitialised)
2317 OSLockDestroy(gHandleLock);
2318 gbLockInitialised = IMG_FALSE;