summaryrefslogtreecommitdiff
path: root/sgx/services4/srvkm/common/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'sgx/services4/srvkm/common/handle.c')
-rw-r--r--sgx/services4/srvkm/common/handle.c1232
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)
+******************************************************************************/