diff options
Diffstat (limited to 'sgx/services4/srvkm/common/handle.c')
-rw-r--r-- | sgx/services4/srvkm/common/handle.c | 1232 |
1 files changed, 1025 insertions, 207 deletions
diff --git a/sgx/services4/srvkm/common/handle.c b/sgx/services4/srvkm/common/handle.c index 80f6d97..f71e67b 100644 --- a/sgx/services4/srvkm/common/handle.c +++ b/sgx/services4/srvkm/common/handle.c @@ -1,30 +1,61 @@ -/********************************************************************** - * - * Copyright (C) Imagination Technologies Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful but, except - * as otherwise stated in writing, without any warranty; without even the - * implied warranty of merchantability or fitness for a particular purpose. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Imagination Technologies Ltd. <gpl-support@imgtec.com> - * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK - * - ******************************************************************************/ +/*************************************************************************/ /*! +@Title Resource Handle Manager +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved +@Description Provide resource handle management +@License Dual MIT/GPLv2 + +The contents of this file are subject to the MIT license as set out below. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Alternatively, the contents of this file may be used under the terms of +the GNU General Public License Version 2 ("GPL") in which case the provisions +of GPL are applicable instead of those above. + +If you wish to allow use of your version of this file only under the terms of +GPL, and not to allow others to use your version of this file under the terms +of the MIT license, indicate your decision by deleting the provisions above +and replace them with the notice and other provisions required by GPL as set +out in the file called "GPL-COPYING" included in this distribution. If you do +not delete the provisions above, a recipient may use your version of this file +under the terms of either the MIT license or GPL. + +This License is also included in this distribution in the file called +"MIT-COPYING". + +EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS +PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ /**************************************************************************/ #if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE) +/* See handle.h for a description of the handle API. */ + +/* + * There is no locking here. It is assumed the code is used in a single + * threaded environment. In particular, it is assumed that the code will + * never be called from an interrupt handler. + * + * The implmentation supports movable handle structures, allowing the address + * of a handle structure to change without having to fix up pointers in + * any of the handle structures. For example, the linked list mechanism + * used to link subhandles together uses handle array indices rather than + * pointers to the structures themselves. + */ + #include <stddef.h> #include "services_headers.h" @@ -47,6 +78,7 @@ #define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount) +/* Valid handles are never NULL, but handle array indices are based from 0 */ #if defined (SUPPORT_SID_INTERFACE) #define INDEX_TO_HANDLE(i) ((IMG_SID)((i) + 1)) #define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1) @@ -110,6 +142,11 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) +/* + * Linked list structure. Used for both the list head and list items. + * Array indices, rather than pointers, are used to point to the next and + * previous items on the list. + */ struct sHandleList { IMG_UINT32 ui32Prev; @@ -128,101 +165,162 @@ enum ePVRSRVInternalHandleFlag INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02, }; +/* Handle structure */ struct sHandle { - + /* Handle type */ PVRSRV_HANDLE_TYPE eType; - + /* Pointer to the data that the handle represents */ IMG_VOID *pvData; - + /* + * When handles are on the free list, the value of the "next index + * plus one field" has the following meaning: + * zero - next handle is the one that follows this one, + * nonzero - the index of the next handle is the value minus one. + * This scheme means handle space can be initialised to all zeros. + * + * When this field is used to link together handles on a list + * other than the free list, zero indicates the end of the + * list, with nonzero the same as above. + */ IMG_UINT32 ui32NextIndexPlusOne; - + /* Internal flags */ enum ePVRSRVInternalHandleFlag eInternalFlag; - + /* Flags specified when the handle was allocated */ PVRSRV_HANDLE_ALLOC_FLAG eFlag; - + /* Index of this handle in the handle array */ IMG_UINT32 ui32Index; - + /* List head for subhandles of this handle */ struct sHandleList sChildren; - + /* List entry for sibling subhandles */ struct sHandleList sSiblings; }; +/* Handle array index structure. + * The handle array is an array of index structures, reallocated as the number of + * handles increases. + * NOTE: There is one index structure per block of handles. + */ struct sHandleIndex { - + /* Pointer to first handle structure in the block */ struct sHandle *psHandle; - + /* Block allocation cookie returned from OSAllocMem for the block of handles */ IMG_HANDLE hBlockAlloc; - + /* Number of free handles in block */ IMG_UINT32 ui32FreeHandBlockCount; }; struct _PVRSRV_HANDLE_BASE_ { - + /* Handle returned from OSAllocMem for handle base allocation */ IMG_HANDLE hBaseBlockAlloc; - + /* Handle returned from OSAllocMem for handle array allocation */ IMG_HANDLE hArrayBlockAlloc; - + /* Pointer to array of pointers to handle structures */ struct sHandleIndex *psHandleArray; - + /* + * Pointer to handle hash table. + * The hash table is used to do reverse lookups, converting data + * pointers to handles. + */ HASH_TABLE *psHashTab; - + /* Number of free handles */ IMG_UINT32 ui32FreeHandCount; - + /* + * If purging is not enabled, this is the array index of first free + * handle. + * If purging is enabled, this is the index to start searching for + * a free handle from. In this case it is usually zero, unless + * the handle array size has been increased due to lack of + * handles. + */ IMG_UINT32 ui32FirstFreeIndex; - + /* Maximum handle index, plus one */ IMG_UINT32 ui32MaxIndexPlusOne; - + /* Total number of handles, free and allocated */ IMG_UINT32 ui32TotalHandCount; - + /* + * Index of the last free index, plus one. Not used if purging + * is enabled. + */ IMG_UINT32 ui32LastFreeIndexPlusOne; - + /* Size of current handle batch, or zero if batching not enabled */ IMG_UINT32 ui32HandBatchSize; - + /* Number of handles prior to start of current batch */ IMG_UINT32 ui32TotalHandCountPreBatch; - + /* Index of first handle in batch, plus one */ IMG_UINT32 ui32FirstBatchIndexPlusOne; - + /* Number of handle allocation failures in batch */ IMG_UINT32 ui32BatchHandAllocFailures; - + /* Purging enabled. + * If purging is enabled, the size of the table can be reduced + * by removing free space at the end of the table. To make + * purging more likely to succeed, handles are allocated as + * far to the front of the table as possible. The first free + * handle is found by a linear search from the start of the table, + * and so no free handle list management is done. + */ IMG_BOOL bPurgingEnabled; }; +/* + * The key for the handle hash table is an array of three elements, the + * pointer to the resource, the resource type, and the process ID. The + * eHandKey enumeration gives the array indices of the elements making + * up the key. + */ enum eHandKey { HAND_KEY_DATA = 0, HAND_KEY_TYPE, HAND_KEY_PARENT, - HAND_KEY_LEN + HAND_KEY_LEN /* Must be last item in list */ }; +/* + * Kernel handle base structure. For handles that are not allocated on + * behalf of a particular process + */ PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL; +/* HAND_KEY is the type of the hash table key */ typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN]; +/*! +****************************************************************************** + + @Function HandleListInit + + @Description Initialise a linked list structure embedded in a handle + structure. + + @Input ui32Index - index of handle in the handle array + psList - pointer to linked list structure + hParent - parent handle, or IMG_NULL + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(HandleListInit) #endif @@ -238,6 +336,17 @@ IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HA psList->hParent = hParent; } +/*! +****************************************************************************** + + @Function InitParentList + + @Description Initialise the children list head in a handle structure. + The children are the subhandles of this handle. + + @Input psHandle - pointer to handle structure + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(InitParentList) #endif @@ -249,6 +358,18 @@ IMG_VOID InitParentList(struct sHandle *psHandle) HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent)); } +/*! +****************************************************************************** + + @Function InitChildEntry + + @Description Initialise the child list entry in a handle structure. + The list entry is used to link together subhandles of + a given handle. + + @Input psHandle - pointer to handle structure + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(InitChildEntry) #endif @@ -258,6 +379,19 @@ IMG_VOID InitChildEntry(struct sHandle *psHandle) HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL); } +/*! +****************************************************************************** + + @Function HandleListIsEmpty + + @Description Determine whether a given linked list is empty. + + @Input ui32Index - index of the handle containing the list head + psList - pointer to the list head + + @Return IMG_TRUE if the list is empty, IMG_FALSE if it isn't. + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(HandleListIsEmpty) #endif @@ -273,7 +407,7 @@ IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList) IMG_BOOL bIsEmpty2; bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index); - PVR_ASSERT(bIsEmpty == bIsEmpty2) + PVR_ASSERT(bIsEmpty == bIsEmpty2); } #endif @@ -281,17 +415,41 @@ IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList) } #ifdef DEBUG +/*! +****************************************************************************** + + @Function NoChildren + + @Description Determine whether a handle has any subhandles + + @Input psHandle - pointer to handle structure + + @Return IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does. + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(NoChildren) #endif static INLINE IMG_BOOL NoChildren(struct sHandle *psHandle) { - PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle)) + PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle)); return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren); } +/*! +****************************************************************************** + + @Function NoParent + + @Description Determine whether a handle is a subhandle + + @Input psHandle - pointer to handle structure + + @Return IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is. + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(NoParent) #endif @@ -300,17 +458,29 @@ IMG_BOOL NoParent(struct sHandle *psHandle) { if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings)) { - PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL) + PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL); return IMG_TRUE; } else { - PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL) + PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL); } return IMG_FALSE; } -#endif +#endif /*DEBUG*/ +/*! +****************************************************************************** + + @Function ParentHandle + + @Description Determine the parent of a handle + + @Input psHandle - pointer to handle structure + + @Return Parent handle, or IMG_NULL if the handle is not a subhandle. + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(ParentHandle) #endif @@ -324,21 +494,49 @@ IMG_HANDLE ParentHandle(struct sHandle *psHandle) return psHandle->sSiblings.hParent; } +/* + * The LIST_PTR_FROM_INDEX_AND_OFFSET macro is used to generate either a + * pointer to the subhandle list head, or a pointer to the linked list + * structure of an item on a subhandle list. + * The list head is itself on the list, but is at a different offset + * in the handle structure to the linked list structure for items on + * the list. The two linked list structures are differentiated by + * the third parameter, containing the parent index. The parent field + * in the list head structure references the handle structure that contains + * it. For items on the list, the parent field in the linked list structure + * references the parent handle, which will be different from the handle + * containing the linked list structure. + */ #define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \ ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo)))) +/*! +****************************************************************************** + + @Function HandleListInsertBefore + + @Description Insert a handle before a handle currently on the list. + + @Input ui32InsIndex - index of handle to be inserted after + psIns - pointer to handle structure to be inserted after + uiParentOffset - offset to list head struct in handle structure + ui32EntryIndex - index of handle to be inserted + psEntry - pointer to handle structure of item to be inserted + uiEntryOffset - offset of list item struct in handle structure + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(HandleListInsertBefore) #endif static INLINE IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex) { - + /* PRQA S 3305 7 */ /*override stricter alignment warning */ struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset); - PVR_ASSERT(psEntry->hParent == IMG_NULL) - PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next) - PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex)) + PVR_ASSERT(psEntry->hParent == IMG_NULL); + PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next); + PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex)); psEntry->ui32Prev = psIns->ui32Prev; psIns->ui32Prev = ui32EntryIndex; @@ -348,6 +546,17 @@ IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIn psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex); } +/*! +****************************************************************************** + + @Function AdoptChild + + @Description Assign a subhandle to a handle + + @Input psParent - pointer to handle structure of parent handle + psChild - pointer to handle structure of child subhandle + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(AdoptChild) #endif @@ -356,12 +565,25 @@ IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct { IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent); - PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent)) + PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent)); HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent); } +/*! +****************************************************************************** + + @Function HandleListRemove + + @Description Remove a handle from a list + + @Input ui32EntryIndex - index of handle to be removed + psEntry - pointer to handle structure of item to be removed + uiEntryOffset - offset of list item struct in handle structure + uiParentOffset - offset to list head struct in handle structure + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(HandleListRemove) #endif @@ -370,12 +592,15 @@ IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, { if (!HandleListIsEmpty(ui32EntryIndex, psEntry)) { - + /* PRQA S 3305 3 */ /*override stricter alignment warning */ struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset); struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset); - - PVR_ASSERT(psEntry->hParent != IMG_NULL) + /* + * The list head is on the list, and we don't want to + * remove it. + */ + PVR_ASSERT(psEntry->hParent != IMG_NULL); psPrev->ui32Next = psEntry->ui32Next; psNext->ui32Prev = psEntry->ui32Prev; @@ -384,6 +609,16 @@ IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, } } +/*! +****************************************************************************** + + @Function UnlinkFromParent + + @Description Remove a subhandle from its parents list + + @Input psHandle - pointer to handle structure of child subhandle + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(UnlinkFromParent) #endif @@ -393,6 +628,19 @@ IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle) HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren)); } +/*! +****************************************************************************** + + @Function HandleListIterate + + @Description Iterate over the items in a list + + @Input psHead - pointer to list head + uiParentOffset - offset to list head struct in handle structure + uiEntryOffset - offset of list item struct in handle structure + pfnIterFunc - function to be called for each handle in the list + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(HandleListIterate) #endif @@ -402,18 +650,24 @@ PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *p IMG_UINT32 ui32Index; IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent); - PVR_ASSERT(psHead->hParent != IMG_NULL) + PVR_ASSERT(psHead->hParent != IMG_NULL); - + /* + * Follow the next chain from the list head until we reach + * the list head again, which signifies the end of the list. + */ for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; ) { struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index); - + /* PRQA S 3305 2 */ /*override stricter alignment warning */ struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset); PVRSRV_ERROR eError; - PVR_ASSERT(psEntry->hParent == psHead->hParent) - + PVR_ASSERT(psEntry->hParent == psHead->hParent); + /* + * Get the next index now, in case the list item is + * modified by the iteration function. + */ ui32Index = psEntry->ui32Next; eError = (*pfnIterFunc)(psBase, psHandle); @@ -426,6 +680,17 @@ PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *p return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function IterateOverChildren + + @Description Iterate over the subhandles of a parent handle + + @Input psParent - pointer to parent handle structure + pfnIterFunc - function to be called for each subhandle + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(IterateOverChildren) #endif @@ -435,6 +700,24 @@ PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psP return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc); } +/*! +****************************************************************************** + + @Function GetHandleStructure + + @Description Get the handle structure for a given handle + + @Input psBase - pointer to handle base structure + ppsHandle - location to return pointer to handle structure + hHandle - handle from client + eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the + handle type is not to be checked. + + @Output ppsHandle - points to a pointer to the handle structure + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(GetHandleStructure) #endif @@ -448,7 +731,7 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle); struct sHandle *psHandle; - + /* Check handle index is in range */ if (!INDEX_IS_VALID(psBase, ui32Index)) { PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount)); @@ -468,7 +751,10 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED; } - + /* + * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function, + * check handle is of the correct type. + */ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType) { PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType)); @@ -478,12 +764,26 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH; } - + /* Return the handle structure */ *ppsHandle = psHandle; return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function ParentIfPrivate + + @Description Return the parent handle if the handle was allocated + with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return + IMG_NULL + + @Input psHandle - pointer to handle + + @Return Parent handle, or IMG_NULL + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(ParentIfPrivate) #endif @@ -498,6 +798,19 @@ IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle) ParentHandle(psHandle) : IMG_NULL; } +/*! +****************************************************************************** + + @Function InitKey + + @Description Initialise a hash table key for the current process + + @Input psBase - pointer to handle base structure + aKey - pointer to key + pvData - pointer to the resource the handle represents + eType - type of resource + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(InitKey) #endif @@ -515,6 +828,21 @@ IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PV aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent; } +/*! +****************************************************************************** + + @Function ReallocHandleArray + + @Description Reallocate the handle array + + @Input psBase - handle base. + phBlockAlloc - pointer to block allocation handle. + ui32NewCount - new handle count + ui32OldCount - old handle count + + @Return Error code or PVRSRV_OK + +******************************************************************************/ static PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount) { @@ -541,15 +869,15 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) || ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0)) { - PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0) - PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0) + PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0); + PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0); return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32NewCount != 0) { - + /* Allocate new handle array */ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex), (IMG_VOID **)&psNewArray, @@ -568,7 +896,10 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo } } - + /* + * If the new handle array is smaller than the old one, free + * unused handle structures + */ for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE) { struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index); @@ -583,10 +914,13 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo } } - + /* + * If the new handle array is bigger than the old one, allocate + * new handle structures + */ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE) { - + /* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index); eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, @@ -624,7 +958,7 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo } #ifdef DEBUG_MAX_HANDLE_COUNT - + /* Force handle failure to test error exit code */ if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT) { PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT)); @@ -635,7 +969,7 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo if (psOldArray != IMG_NULL) { - + /* Free old handle array */ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex), psOldArray, @@ -652,16 +986,21 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo if (ui32NewCount > ui32OldCount) { - - PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount) + /* Check for wraparound */ + PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount); - + /* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */ psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount); - + /* + * If purging is enabled, there is no free handle list + * management, but as an optimization, when allocating + * new handles, we use ui32FirstFreeIndex to point to + * the first handle in a newly allocated block. + */ if (psBase->ui32FirstFreeIndex == 0) { - PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0) + PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0); psBase->ui32FirstFreeIndex = ui32OldCount; } @@ -669,8 +1008,8 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo { if (!psBase->bPurgingEnabled) { - PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0) - PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0) + PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0); + PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0); INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1; } @@ -683,11 +1022,11 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo } else { - PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled) - PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount) - PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount) + PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled); + PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount); + PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount); - + /* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */ psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount); if (ui32NewCount == 0) @@ -697,16 +1036,16 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo } } - PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount) + PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount); return PVRSRV_OK; error: - PVR_ASSERT(eReturn != PVRSRV_OK) + PVR_ASSERT(eReturn != PVRSRV_OK); if (psNewArray != IMG_NULL) { - + /* Free any new handle structures that were allocated */ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE) { struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index); @@ -723,7 +1062,7 @@ error: } } - + /* Free new handle array */ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex), psNewArray, @@ -737,18 +1076,52 @@ error: return eReturn; } +/*! +****************************************************************************** + + @Function FreeHandleArray + + @Description Frees the handle array. + The memory containing the array of handle structure + pointers is deallocated. + + @Input psBase - pointer to handle base structure + + @Return Error code or PVRSRV_OK + +******************************************************************************/ static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase) { return ReallocHandleArray(psBase, 0); } +/*! +****************************************************************************** + + @Function FreeHandle + + @Description Free a handle structure. + + @Input psBase - pointer to handle base structure + psHandle - pointer to handle structure + + @Return PVRSRV_OK or PVRSRV_ERROR + +******************************************************************************/ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle) { HAND_KEY aKey; IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle); PVRSRV_ERROR eError; - + /* + * If a handle allocated in batch mode is freed whilst still + * in batch mode, the type is set to PVRSRV_HANDLE_TYPE_NONE further + * down, to indicate the handle will not be used, but not actually + * freed. The Free is completed when this function is called a + * second time as part of the batch commit or release. + */ + InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle)); if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) @@ -762,15 +1135,15 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan #endif - PVR_ASSERT(hHandle != IMG_NULL) - PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index)) + PVR_ASSERT(hHandle != IMG_NULL); + PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index)); PVR_UNREFERENCED_PARAMETER(hHandle); } - + /* Unlink handle from parent */ UnlinkFromParent(psBase, psHandle); - + /* Free children */ eError = IterateOverChildren(psBase, psHandle, FreeHandle); if (eError != PVRSRV_OK) { @@ -778,45 +1151,54 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan return eError; } - + /* + * Clear the type here, so that a handle can no longer be looked + * up if it is only partially freed. + */ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE; if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) { - + /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */ SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle); - + /* + * If the handle was allocated in batch mode, delay the free + * until the batch commit or release. + */ return PVRSRV_OK; } - + /* No free list management if purging is enabled */ if (!psBase->bPurgingEnabled) { if (psBase->ui32FreeHandCount == 0) { - PVR_ASSERT(psBase->ui32FirstFreeIndex == 0) - PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0) + PVR_ASSERT(psBase->ui32FirstFreeIndex == 0); + PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0); psBase->ui32FirstFreeIndex = ui32Index; } else { - - PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0) - PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0) + /* + * Put the handle pointer on the end of the the free + * handle pointer linked list. + */ + PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0); + PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0); INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1; } - PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0) + PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0); - + /* Update the end of the free handle linked list */ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1; } psBase->ui32FreeHandCount++; INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++; - PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE) + PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE); #ifdef DEBUG { @@ -828,13 +1210,25 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex); } - PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount) + PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount); } #endif return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function FreeAllHandles + + @Description Free all handles for a given handle base + + @Input psBase - pointer to handle base structure + + @Return PVRSRV_OK or PVRSRV_ERROR + +******************************************************************************/ static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase) { IMG_UINT32 i; @@ -860,7 +1254,7 @@ static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase) break; } - + /* Break out of loop if all the handles free */ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount) { break; @@ -871,6 +1265,18 @@ static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase) return eError; } +/*! +****************************************************************************** + + @Function FreeHandleBase + + @Description Free a handle base. + + @Input psHandleBase - pointer to handle base + + @Return Error code or PVRSRV_OK + +******************************************************************************/ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase) { PVRSRV_ERROR eError; @@ -881,7 +1287,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase) PVRSRVReleaseHandleBatch(psBase); } - + /* Free the handle array */ eError = FreeAllHandles(psBase); if (eError != PVRSRV_OK) { @@ -889,7 +1295,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase) return eError; } - + /* Free the handle array */ eError = FreeHandleArray(psBase); if (eError != PVRSRV_OK) { @@ -899,7 +1305,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase) if (psBase->psHashTab != IMG_NULL) { - + /* Free the hash table */ HASH_Delete(psBase->psHashTab); } @@ -916,6 +1322,20 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase) return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function FindHandle + + @Description Find handle corresponding to a resource pointer + + @Input psBase - pointer to handle base structure + pvData - pointer to resource to be associated with the handle + eType - the type of resource + + @Return the handle, or IMG_NULL if not found + +******************************************************************************/ #ifdef INLINE_IS_PRAGMA #pragma inline(FindHandle) #endif @@ -928,7 +1348,7 @@ IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDL { HAND_KEY aKey; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); InitKey(aKey, psBase, pvData, eType, hParent); @@ -939,16 +1359,30 @@ IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDL #endif } +/*! +****************************************************************************** + + @Function IncreaseHandleArraySize + + @Description Allocate some more free handles + + @Input psBase - pointer to handle base structure + ui32Delta - number of new handles required + + @Return Error code or PVRSRV_OK + +******************************************************************************/ static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta) { PVRSRV_ERROR eError; IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta); IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted; -; - PVR_ASSERT(ui32Delta != 0) + PVR_ASSERT(ui32Delta != 0); - + /* + * Check new count against max handle index, and check for wrap around. + */ if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount) { ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne; @@ -962,9 +1396,9 @@ static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT } } - PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta) + PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta); - + /* Realloc handle pointer array */ eError = ReallocHandleArray(psBase, ui32NewTotalHandCount); if (eError != PVRSRV_OK) { @@ -975,6 +1409,19 @@ static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function EnsureFreeHandles + + @Description Ensure there are enough free handles + + @Input psBase - pointer to handle base structure + ui32Free - number of free handles required + + @Return Error code or PVRSRV_OK + +******************************************************************************/ static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free) { PVRSRV_ERROR eError; @@ -994,6 +1441,23 @@ static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui3 return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function AllocHandle + + @Description Allocate a new handle + + @Input phHandle - location for new handle + pvData - pointer to resource to be associated with the handle + eType - the type of resource + hParent - parent handle or IMG_NULL + + @Output phHandle - points to new handle + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent) #else @@ -1010,15 +1474,15 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle HAND_KEY aKey; PVRSRV_ERROR eError; - - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) - PVR_ASSERT(psBase != IMG_NULL) - PVR_ASSERT(psBase->psHashTab != IMG_NULL) + /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); + PVR_ASSERT(psBase != IMG_NULL); + PVR_ASSERT(psBase->psHashTab != IMG_NULL); if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { - - PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL) + /* Handle must not already exist */ + PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL); } if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase)) @@ -1026,30 +1490,41 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize)); } - + /* Ensure there is a free handle */ eError = EnsureFreeHandles(psBase, 1); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError)); return eError; } - PVR_ASSERT(psBase->ui32FreeHandCount != 0) + PVR_ASSERT(psBase->ui32FreeHandCount != 0); if (!psBase->bPurgingEnabled) { - + /* Array index of first free handle */ ui32NewIndex = psBase->ui32FirstFreeIndex; - + /* Get handle array entry */ psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex); } else { IMG_UINT32 ui32BlockedIndex; - - - PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0) + /* + * If purging is enabled, we always try to allocate handles + * at the front of the array, to increase the chances that + * the size of the handle array can be reduced by a purge. + * No linked list of free handles is kept; we search for + * free handles as required. + */ + + /* + * ui32FirstFreeIndex should only be set when a new batch of + * handle structures is allocated, and should always be a + * multiple of the block size. + */ + PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0); for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE) { @@ -1070,20 +1545,24 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle } } psBase->ui32FirstFreeIndex = 0; - PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount) + PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount); } - PVR_ASSERT(psNewHandle != IMG_NULL) + PVR_ASSERT(psNewHandle != IMG_NULL); - + /* Handle to be returned to client */ hHandle = INDEX_TO_HANDLE(ui32NewIndex); - + /* + * If a data pointer can be associated with multiple handles, we + * don't put the handle in the hash table, as the data pointer + * may not map to a unique handle + */ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { - + /* Initialise hash key */ InitKey(aKey, psBase, pvData, eType, hParent); - + /* Put the new handle in the hash table */ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle)) { PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table")); @@ -1094,36 +1573,44 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle psBase->ui32FreeHandCount--; - PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE) - PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0) + PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE); + PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0); INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--; - + /* No free list management if purging is enabled */ if (!psBase->bPurgingEnabled) { - + /* Check whether the last free handle has been allocated */ if (psBase->ui32FreeHandCount == 0) { - PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex) - PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1)) + PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex); + PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1)); psBase->ui32LastFreeIndexPlusOne = 0; psBase->ui32FirstFreeIndex = 0; } else { - + /* + * Update the first free handle index. + * If the "next free index plus one" field in the new + * handle structure is zero, the next free index is + * the index of the new handle plus one. This + * convention has been adopted to simplify the + * initialisation of freshly allocated handle + * space. + */ psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ? ui32NewIndex + 1 : psNewHandle->ui32NextIndexPlusOne - 1; } } - - PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex) + /* Initialise the newly allocated handle */ + PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex); - + /* PRQA S 0505 1 */ /* psNewHandle is never NULL, see assert earlier */ psNewHandle->eType = eType; psNewHandle->pvData = pvData; psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE; @@ -1131,22 +1618,22 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle InitParentList(psNewHandle); #if defined(DEBUG) - PVR_ASSERT(NoChildren(psNewHandle)) + PVR_ASSERT(NoChildren(psNewHandle)); #endif InitChildEntry(psNewHandle); #if defined(DEBUG) - PVR_ASSERT(NoParent(psNewHandle)) + PVR_ASSERT(NoParent(psNewHandle)); #endif if (HANDLES_BATCHED(psBase)) { - + /* Add handle to batch list */ psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne; psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1; - + /* PRQA S 1474 1 */ /* ignore warnings about enum types being modified */ SET_BATCHED_HANDLE(psNewHandle); } else @@ -1154,12 +1641,28 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle psNewHandle->ui32NextIndexPlusOne = 0; } - + /* Return the new handle to the client */ *phHandle = hHandle; return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVAllocHandle + + @Description Allocate a handle + + @Input phHandle - location for new handle + pvData - pointer to resource to be associated with the handle + eType - the type of resource + + @Output phHandle - points to new handle + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag) #else @@ -1181,16 +1684,19 @@ PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, if (HANDLES_BATCHED(psBase)) { - + /* + * Increment the counter in case of failure. It will be + * decremented on success. + */ psBase->ui32BatchHandAllocFailures++; } - - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { - + /* See if there is already a handle for this data pointer */ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL); #if defined (SUPPORT_SID_INTERFACE) if (hHandle != 0) @@ -1207,7 +1713,11 @@ PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, return eError; } - + /* + * If the client is willing to share a handle, and the + * existing handle is marked as shareable, return the + * existing handle. + */ if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED)) { *phHandle = hHandle; @@ -1233,6 +1743,23 @@ exit_ok: return eError; } +/*! +****************************************************************************** + + @Function PVRSRVAllocSubHandle + + @Description Allocate a subhandle + + @Input phHandle - location for new subhandle + pvData - pointer to resource to be associated with the subhandle + eType - the type of resource + hParent - parent handle + + @Output phHandle - points to new subhandle + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent) #else @@ -1256,17 +1783,20 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand if (HANDLES_BATCHED(psBase)) { - + /* + * Increment the counter in case of failure. It will be + * decremented on success. + */ psBase->ui32BatchHandAllocFailures++; } - - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ? hParent : IMG_NULL; - + /* Lookup the parent handle */ eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE); if (eError != PVRSRV_OK) { @@ -1275,7 +1805,7 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { - + /* See if there is already a handle for this data pointer */ hHandle = FindHandle(psBase, pvData, eType, hParentKey); #if defined (SUPPORT_SID_INTERFACE) if (hHandle != 0) @@ -1293,9 +1823,14 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand return eErr; } - PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent) + PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent); - + /* + * If the client is willing to share a handle, the + * existing handle is marked as shareable, and the + * existing handle has the same parent, return the + * existing handle. + */ if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent) { *phHandle = hHandle; @@ -1314,7 +1849,11 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand return eError; } - + /* + * Get the parent handle structure again, in case the handle + * structure has moved (depending on the implementation + * of AllocHandle). + */ psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent); psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle); @@ -1332,6 +1871,22 @@ exit_ok: return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVFindHandle + + @Description Find handle corresponding to a resource pointer + + @Input phHandle - location for returned handle + pvData - pointer to resource to be associated with the handle + eType - the type of resource + + @Output phHandle - points to handle + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType) #else @@ -1344,9 +1899,9 @@ PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_HANDLE hHandle; #endif - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); - + /* See if there is a handle for this data pointer */ #if defined (SUPPORT_SID_INTERFACE) hHandle = (IMG_SID) FindHandle(psBase, pvData, eType, IMG_NULL); #else @@ -1362,6 +1917,23 @@ PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVLookupHandleAnyType + + @Description Lookup the data pointer and type corresponding to a handle + + @Input ppvData - location to return data pointer + peType - location to return handle type + hHandle - handle from client + + @Output ppvData - points to the data pointer + peType - points to handle type + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle) #else @@ -1387,6 +1959,22 @@ PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *pp return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVLookupHandle + + @Description Lookup the data pointer corresponding to a handle + + @Input ppvData - location to return data pointer + hHandle - handle from client + eType - handle type + + @Output ppvData - points to the data pointer + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType) #else @@ -1396,9 +1984,9 @@ PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, struct sHandle *psHandle; PVRSRV_ERROR eError; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); #if defined (SUPPORT_SID_INTERFACE) - PVR_ASSERT(hHandle != 0) + PVR_ASSERT(hHandle != 0); #endif eError = GetHandleStructure(psBase, &psHandle, hHandle, eType); @@ -1416,6 +2004,23 @@ PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVLookupSubHandle + + @Description Lookup the data pointer corresponding to a subhandle + + @Input ppvData - location to return data pointer + hHandle - handle from client + eType - handle type + hAncestor - ancestor handle + + @Output ppvData - points to the data pointer + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor) #else @@ -1426,9 +2031,9 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat struct sHandle *psCHand; PVRSRV_ERROR eError; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); #if defined (SUPPORT_SID_INTERFACE) - PVR_ASSERT(hHandle != 0) + PVR_ASSERT(hHandle != 0); #endif eError = GetHandleStructure(psBase, &psCHand, hHandle, eType); @@ -1438,7 +2043,7 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat return eError; } - + /* Look for hAncestor among the handle's ancestors */ for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; ) { eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE); @@ -1454,6 +2059,24 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVGetParentHandle + + @Description Lookup the parent of a handle + + @Input phParent - location for returning parent handle + hHandle - handle for which the parent handle is required + eType - handle type + hParent - parent handle + + @Output *phParent - parent handle, or IMG_NULL if there is no parent + + @Return Error code or PVRSRV_OK. Note that not having a parent is + not regarded as an error. + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType) #else @@ -1463,7 +2086,7 @@ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phPare struct sHandle *psHandle; PVRSRV_ERROR eError; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); eError = GetHandleStructure(psBase, &psHandle, hHandle, eType); if (eError != PVRSRV_OK) @@ -1477,6 +2100,23 @@ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phPare return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVLookupAndReleaseHandle + + @Description Lookup the data pointer corresponding to a handle + + @Input ppvData - location to return data pointer + hHandle - handle from client + eType - handle type + eFlag - lookup flags + + @Output ppvData - points to the data pointer + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType) #else @@ -1486,7 +2126,7 @@ PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID struct sHandle *psHandle; PVRSRV_ERROR eError; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); eError = GetHandleStructure(psBase, &psHandle, hHandle, eType); if (eError != PVRSRV_OK) @@ -1505,6 +2145,19 @@ PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID return eError; } +/*! +****************************************************************************** + + @Function PVRSRVReleaseHandle + + @Description Release a handle that is no longer needed + + @Input hHandle - handle from client + eType - handle type + + @Return Error code or PVRSRV_OK + +******************************************************************************/ #if defined (SUPPORT_SID_INTERFACE) PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType) #else @@ -1514,7 +2167,7 @@ PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, struct sHandle *psHandle; PVRSRV_ERROR eError; - PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE) + PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); eError = GetHandleStructure(psBase, &psHandle, hHandle, eType); if (eError != PVRSRV_OK) @@ -1528,6 +2181,19 @@ PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, return eError; } +/*! +****************************************************************************** + + @Function PVRSRVNewHandleBatch + + @Description Start a new handle batch + + @Input psBase - handle base + @Input ui32BatchSize - handle batch size + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize) { PVRSRV_ERROR eError; @@ -1553,18 +2219,31 @@ PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Bat psBase->ui32HandBatchSize = ui32BatchSize; - + /* Record current number of handles */ psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount; - PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0) + PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0); - PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0) + PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0); - PVR_ASSERT(HANDLES_BATCHED(psBase)) + PVR_ASSERT(HANDLES_BATCHED(psBase)); return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVHandleBatchCommitOrRelease + + @Description Release a handle batch + + @Input psBase - handle base + bCommit - commit handles + + @Return none + +******************************************************************************/ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit) { @@ -1587,24 +2266,32 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, } bCommitBatch = IMG_FALSE; } - - PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit) + /* + * The whole point of batched handles is to avoid handle allocation + * failures. + */ + PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit); ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne; while(ui32IndexPlusOne != 0) { struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1); IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne; - PVR_ASSERT(BATCHED_HANDLE(psHandle)) + PVR_ASSERT(BATCHED_HANDLE(psHandle)); psHandle->ui32NextIndexPlusOne = 0; if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) { + /* + * We need a complete free here. If the handle + * is not partially free, set the handle as + * unbatched to avoid a partial free. + */ if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) { - - SET_UNBATCHED_HANDLE(psHandle); + /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */ + SET_UNBATCHED_HANDLE(psHandle); /* PRQA S 4130 */ /* mis-use of enums FIXME*/ } eError = FreeHandle(psBase, psHandle); @@ -1612,11 +2299,11 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, { PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError)); } - PVR_ASSERT(eError == PVRSRV_OK) + PVR_ASSERT(eError == PVRSRV_OK); } else { - + /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */ SET_UNBATCHED_HANDLE(psHandle); } @@ -1628,7 +2315,7 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, { IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch; - PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch) + PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch); PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta)); @@ -1639,7 +2326,7 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, if (psBase->ui32BatchHandAllocFailures != 0 && bCommit) { - PVR_ASSERT(!bCommitBatch) + PVR_ASSERT(!bCommitBatch); eError = PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE; } @@ -1652,16 +2339,53 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, return eError; } +/*! +****************************************************************************** + + @Function PVRSRVCommitHandleBatch + + @Description Commit a handle batch + + @Input psBase - handle base + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase) { return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE); } +/*! +****************************************************************************** + + @Function PVRSRReleaseHandleBatch + + @Description Release a handle batch + + @Input psBase - handle base + + @Return none + +******************************************************************************/ IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase) { (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE); } +/*! +****************************************************************************** + + @Function PVRSRVSetMaxHandle + + @Description Set maximum handle number for given handle base + + @Input psBase - pointer to handle base structure + ui32MaxHandle - Maximum handle number + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle) { IMG_UINT32 ui32MaxHandleRounded; @@ -1672,7 +2396,7 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa return PVRSRV_ERROR_INVALID_PARAMS; } - + /* Validate the limit */ if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE)); @@ -1680,7 +2404,7 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa return PVRSRV_ERROR_INVALID_PARAMS; } - + /* The limit can only be set if no handles have been allocated */ if (psBase->ui32TotalHandCount != 0) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated")); @@ -1690,24 +2414,54 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle); - + /* + * Allow the maximum number of handles to be reduced, but never to + * zero. + */ if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne) { psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded; } - PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0) - PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE) - PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0) + PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0); + PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE); + PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0); return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVGetMaxHandle + + @Description Get maximum handle number for given handle base + + @Input psBase - pointer to handle base structure + + @Output Maximum handle number, or 0 if handle limits not + supported. + + @Return Error code or PVRSRV_OK + +******************************************************************************/ IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase) { return psBase->ui32MaxIndexPlusOne; } +/*! +****************************************************************************** + + @Function PVRSRVEnableHandlePurging + + @Description Enable purging for a given handle base + + @Input psBase - pointer to handle base structure + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase) { if (psBase->bPurgingEnabled) @@ -1716,7 +2470,7 @@ PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase) return PVRSRV_OK; } - + /* Purging can only be enabled if no handles have been allocated */ if (psBase->ui32TotalHandCount != 0) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated")); @@ -1728,6 +2482,18 @@ PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase) return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVPurgeHandles + + @Description Purge handles for a given handle base + + @Input psBase - pointer to handle base structure + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase) { IMG_UINT32 ui32BlockIndex; @@ -1745,7 +2511,7 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase) return PVRSRV_ERROR_INVALID_PARAMS; } - PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0) + PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0); for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--) { @@ -1756,12 +2522,14 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase) } ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex); - + /* + * Check for a suitable decrease in the handle count. + */ if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2)) { PVRSRV_ERROR eError; - + // PVR_TRACE((" PVRSRVPurgeHandles: reducing number of handles from %u to %u", psBase->ui32TotalHandCount, ui32NewHandCount)); eError = ReallocHandleArray(psBase, ui32NewHandCount); if (eError != PVRSRV_OK) @@ -1773,6 +2541,20 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase) return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVAllocHandleBase + + @Description Allocate a handle base structure for a process + + @Input ppsBase - pointer to handle base structure pointer + + @Output ppsBase - points to handle base structure pointer + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase) { PVRSRV_HANDLE_BASE *psBase; @@ -1791,7 +2573,7 @@ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase) } OSMemSet(psBase, 0, sizeof(*psBase)); - + /* Create hash table */ psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default); if (psBase->psHashTab == IMG_NULL) { @@ -1809,11 +2591,23 @@ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase) return PVRSRV_OK; } +/*! +****************************************************************************** + + @Function PVRSRVFreeHandleBase + + @Description Free a handle base structure + + @Input psBase - pointer to handle base structure + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase) { PVRSRV_ERROR eError; - PVR_ASSERT(psBase != gpsKernelHandleBase) + PVR_ASSERT(psBase != gpsKernelHandleBase); eError = FreeHandleBase(psBase); if (eError != PVRSRV_OK) @@ -1824,11 +2618,21 @@ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase) return eError; } +/*! +****************************************************************************** + + @Function PVRSRVHandleInit + + @Description Initialise handle management + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID) { PVRSRV_ERROR eError; - PVR_ASSERT(gpsKernelHandleBase == IMG_NULL) + PVR_ASSERT(gpsKernelHandleBase == IMG_NULL); eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase); if (eError != PVRSRV_OK) @@ -1850,6 +2654,16 @@ error: return eError; } +/*! +****************************************************************************** + + @Function PVRSRVHandleDeInit + + @Description De-initialise handle management + + @Return Error code or PVRSRV_OK + +******************************************************************************/ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID) { PVRSRV_ERROR eError = PVRSRV_OK; @@ -1870,4 +2684,8 @@ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID) return eError; } #else -#endif +/* disable warning about empty module */ +#endif /* #if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE) */ +/****************************************************************************** + End of file (handle.c) +******************************************************************************/ |