summaryrefslogtreecommitdiffstats
path: root/pvr-source/services4/srvkm/common/resman.c
diff options
context:
space:
mode:
Diffstat (limited to 'pvr-source/services4/srvkm/common/resman.c')
-rw-r--r--pvr-source/services4/srvkm/common/resman.c985
1 files changed, 985 insertions, 0 deletions
diff --git a/pvr-source/services4/srvkm/common/resman.c b/pvr-source/services4/srvkm/common/resman.c
new file mode 100644
index 0000000..aef102f
--- /dev/null
+++ b/pvr-source/services4/srvkm/common/resman.c
@@ -0,0 +1,985 @@
+/*************************************************************************/ /*!
+@Title Resource Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource 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.
+*/ /**************************************************************************/
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+#include <linux/mutex.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+static DEFINE_MUTEX(lock);
+#define DOWN(m) mutex_lock(m)
+#define UP(m) mutex_unlock(m)
+#else
+static DECLARE_MUTEX(lock);
+#define DOWN(m) down(m)
+#define UP(m) up(m)
+#endif
+
+#define ACQUIRE_SYNC_OBJ do { \
+ if (in_interrupt()) { \
+ printk("ISR cannot take RESMAN mutex\n"); \
+ BUG(); \
+ } \
+ else DOWN(&lock); \
+} while (0)
+#define RELEASE_SYNC_OBJ UP(&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+/******************************************************************************
+ * resman structures
+ *****************************************************************************/
+
+/* resman item structure */
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_ITEM_ **ppsThis; /*!< list navigation */
+ struct _RESMAN_ITEM_ *psNext; /*!< list navigation */
+
+ IMG_UINT32 ui32Flags; /*!< flags */
+ IMG_UINT32 ui32ResType;/*!< res type */
+
+ IMG_PVOID pvParam; /*!< param1 for callback */
+ IMG_UINT32 ui32Param; /*!< param2 for callback */
+
+ RESMAN_FREE_FN pfnFreeResource;/*!< resman item free callback */
+} RESMAN_ITEM;
+
+
+/* resman context structure */
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_CONTEXT_ **ppsThis;/*!< list navigation */
+ struct _RESMAN_CONTEXT_ *psNext;/*!< list navigation */
+
+ PVRSRV_PER_PROCESS_DATA *psPerProc; /* owner of resources */
+
+ RESMAN_ITEM *psResItemList;/*!< res item list for context */
+
+} RESMAN_CONTEXT;
+
+
+/* resman list structure */
+typedef struct
+{
+ RESMAN_CONTEXT *psContextList; /*!< resman context list */
+
+} RESMAN_LIST, *PRESMAN_LIST; /* PRQA S 3205 */
+
+
+PRESMAN_LIST gpsResList = IMG_NULL;
+
+#include "lists.h" /* PRQA S 5087 */ /* include lists.h required here */
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+static IMPLEMENT_LIST_REVERSE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+/******************************************************** Forword references */
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback, IMG_BOOL bForceCleanup);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback);
+
+
+#ifdef DEBUG
+ static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+ #define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+ #define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+/*!
+******************************************************************************
+
+ @Function ResManInit
+
+ @Description initialises the resman
+
+ @Return none
+
+******************************************************************************/
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+ if (gpsResList == IMG_NULL)
+ {
+ /* If not already initialised */
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*gpsResList),
+ (IMG_VOID **)&gpsResList, IMG_NULL,
+ "Resource Manager List") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Init list, the linked list has dummy entries at both ends */
+ gpsResList->psContextList = IMG_NULL;
+
+ /* Check resource list */
+ VALIDATERESLIST();
+ }
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function ResManDeInit
+
+ @Description de-initialises the resman
+
+ @Return none
+
+******************************************************************************/
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+ if (gpsResList != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+ gpsResList = IMG_NULL;
+ }
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManConnect
+
+ @Description Opens a connection to the Resource Manager
+
+ @input hPerProc - Per-process data (if applicable)
+ @output phResManContext - Resman context
+
+ @Return error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext)
+{
+ PVRSRV_ERROR eError;
+ PRESMAN_CONTEXT psResManContext;
+
+ /*Acquire resource list sync object*/
+ ACQUIRE_SYNC_OBJ;
+
+ /*Check resource list*/
+ VALIDATERESLIST();
+
+ /* Allocate memory for the new context. */
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+ (IMG_VOID **)&psResManContext, IMG_NULL,
+ "Resource Manager Context");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+ }
+
+#ifdef DEBUG
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif /* DEBUG */
+ psResManContext->psResItemList = IMG_NULL;
+ psResManContext->psPerProc = hPerProc;
+
+ /* Insert new context struct after the dummy first entry */
+ List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManDisconnect
+
+ @Description Closes a Resource Manager connection and frees all resources
+
+ @input hResManContext - Resman context
+ @input bKernelContext - IMG_TRUE for kernel contexts
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+ IMG_BOOL bKernelContext)
+{
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Print and validate resource list */
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+ /* Free all auto-freed resources in order */
+
+ if (!bKernelContext)
+ {
+ /* OS specific User-mode Mappings: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+ /* VGX types: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, 0, 0, IMG_TRUE);
+
+ /* Event Object */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+ /* syncobject state (Read/Write Complete values) */
+ /* Must be FIFO, so we reverse the list, twice */
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList); // (could survive without this - all following items would be cleared up "fifo" too)
+
+ /* SGX types: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+ /* COMMON types: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
+#if defined(SUPPORT_ION)
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ION, 0, 0, IMG_TRUE);
+#endif
+ /* DISPLAY CLASS types: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+ /* BUFFER CLASS types: */
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+ }
+
+ /* Ensure that there are no resources left */
+ PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+ /* Remove the context struct from the list */
+ List_RESMAN_CONTEXT_Remove(psResManContext);
+
+ /* Free the context struct */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+ /*not nulling pointer, copy on stack*/
+
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Print and validate resource list */
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManRegisterRes
+
+ @Description : Inform the resource manager that the given resource has
+ been alloacted and freeing of it will be the responsibility
+ of the resource manager
+
+ @input psResManContext - resman context
+ @input ui32ResType - identify what kind of resource it is
+ @input pvParam - address of resource
+ @input ui32Param - size of resource
+ @input pfnFreeResource - pointer to function that frees this resource
+
+ @Return On success a pointer to an opaque data structure that represents
+ the allocated resource, else NULL
+
+**************************************************************************/
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource)
+{
+ PRESMAN_ITEM psNewResItem;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+ return (PRESMAN_ITEM) IMG_NULL;
+ }
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+ "FreeFunc %08X",
+ (IMG_UINTPTR_T)psResManContext,
+ ui32ResType,
+ (IMG_UINTPTR_T)pvParam,
+ ui32Param,
+ (IMG_UINTPTR_T)pfnFreeResource));
+
+ /* Allocate memory for the new resource structure */
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+ IMG_NULL,
+ "Resource Manager Item") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item"));
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return((PRESMAN_ITEM)IMG_NULL);
+ }
+
+ /* Fill in details about this resource */
+#ifdef DEBUG
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+#endif /* DEBUG */
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->ui32Param = ui32Param;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+ psNewResItem->ui32Flags = 0;
+
+ /* Insert new structure after dummy first entry */
+ List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return(psNewResItem);
+}
+
+/*!
+******************************************************************************
+ @Function ResManFreeResByPtr
+
+ @Description frees a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item to free
+ bForceCleanup - ignored uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
+ (IMG_UINTPTR_T)psResItem));
+
+ /*Acquire resource list sync object*/
+ ACQUIRE_SYNC_OBJ;
+
+ /*Check resource list*/
+ VALIDATERESLIST();
+
+ /*Free resource*/
+ eError = FreeResourceByPtr(psResItem, IMG_TRUE, bForceCleanup);
+
+ /*Check resource list*/
+ VALIDATERESLIST();
+
+ /*Release resource list sync object*/
+ RELEASE_SYNC_OBJ;
+
+ return(eError);
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManFreeResByCriteria
+
+ @Description frees a resource by matching on criteria
+
+ @inputs hResManContext - handle for resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be
+ used in search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+ "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+ (IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
+ (IMG_UINTPTR_T)pvParam, ui32Param));
+
+ /* Free resources by criteria for this context */
+ eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+ ui32ResType, pvParam, ui32Param,
+ IMG_TRUE);
+
+ /* Check resource list */
+ VALIDATERESLIST();
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManDissociateRes
+
+ @Description Moves a resource from one context to another.
+
+ @inputs psResItem - pointer to resource item to dissociate
+ @inputs psNewResManContext - new resman context for the resource
+
+ @Return IMG_VOID
+**************************************************************************/
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
+ PRESMAN_CONTEXT psNewResManContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG /* QAC fix */
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ if (psNewResManContext != IMG_NULL)
+ {
+ /* Remove this item from its old resource list */
+ List_RESMAN_ITEM_Remove(psResItem);
+
+ /* Re-insert into new list */
+ List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+ }
+ else
+ {
+ eError = FreeResourceByPtr(psResItem, IMG_FALSE, CLEANUP_WITH_POLL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+ return eError;
+ }
+ }
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr_AnyVaCb
+
+ @Description
+ Compares the resman item with a given pointer.
+
+ @inputs psCurItem - theThe item to check
+ @inputs va - Variable argument list with:
+ psItem - pointer to resource item to find
+
+ @Return IMG_BOOL
+**************************************************************************/
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ RESMAN_ITEM *psItem;
+
+ psItem = va_arg(va, RESMAN_ITEM*);
+
+ return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr
+
+ @Description
+ Attempts to find a resource in the list for this context
+
+ @inputs hResManContext - handle for resman context
+ @inputs psItem - pointer to resource item to find
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
+ RESMAN_ITEM *psItem)
+{
+/* RESMAN_ITEM *psCurItem;*/
+
+ PVRSRV_ERROR eResult;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG /* QAC fix */
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ (IMG_UINTPTR_T)psResManContext,
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam,
+ psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource,
+ psItem->ui32Flags));
+
+ /* Search resource items starting at after the first dummy item */
+ if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+ &ResManFindResourceByPtr_AnyVaCb,
+ psItem))
+ {
+ eResult = PVRSRV_OK;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_NOT_OWNER;
+ }
+
+ /* Release resource list sync object */
+ RELEASE_SYNC_OBJ;
+
+/* return PVRSRV_ERROR_NOT_OWNER;*/
+ return eResult;
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByPtr
+
+ @Description
+ Frees a resource and move it from the list
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psItem - pointer to resource item to free
+ bExecuteCallback - execute callback?
+ bForceCleanup - skips uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if (psItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG /* QAC fix */
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
+
+ /* Release resource list sync object just in case the free routine calls the resource manager */
+ RELEASE_SYNC_OBJ;
+
+ /* Call the freeing routine */
+ if (bExecuteCallback)
+ {
+ eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param, bForceCleanup);
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+ }
+ }
+
+ /* Acquire resource list sync object */
+ ACQUIRE_SYNC_OBJ;
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Remove this item from the resource list */
+ List_RESMAN_ITEM_Remove(psItem);
+
+ /* Free memory for the resource item */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ }
+
+ return(eError);
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria_AnyVaCb
+
+ @Description
+ Matches a resource manager item with a given criteria.
+
+ @inputs psCuItem - the item to be matched
+ @inputs va - a variable argument list with:.
+ ui32SearchCriteria - indicates which parameters should be used
+ search for resources to free
+ ui32ResType - identify what kind of resource to free
+ pvParam - address of resource to be free
+ ui32Param - size of resource to be free
+
+
+ @Return psCurItem if matched, IMG_NULL otherwise.
+**************************************************************************/
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+ ui32Param = va_arg(va, IMG_UINT32);
+
+ /*check that for all conditions are either disabled or eval to true*/
+ if(
+ /* Check resource type */
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+ /* Check address */
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ &&
+ /* Check size */
+ (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+ (psCurItem->ui32Param == ui32Param))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria
+
+ @Description
+ Frees all resources that match the given criteria for the
+ context.
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psResManContext - pointer to resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be used
+ @inputs search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+ @inputs ui32AutoFreeLev - auto free level to free
+ @inputs bExecuteCallback - execute callback?
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ /* Search resource items starting at after the first dummy item */
+ /*while we get a match and not an error*/
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+ &FreeResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam,
+ ui32Param)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ do
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ RELEASE_SYNC_OBJ;
+ OSReleaseBridgeLock();
+ /* Give a chance for other threads to come in and SGX to do more work */
+ OSSleepms(MAX_CLEANUP_TIME_WAIT_US/1000);
+ OSReacquireBridgeLock();
+ ACQUIRE_SYNC_OBJ;
+ }
+ } while (eError == PVRSRV_ERROR_RETRY);
+ }
+
+ return eError;
+}
+
+
+#ifdef DEBUG
+/*!
+******************************************************************************
+ @Function ValidateResList
+
+ @Description
+ Walks the resource list check the pointers
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @Return none
+**************************************************************************/
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+ PRESMAN_ITEM psCurItem, *ppsThisItem;
+ PRESMAN_CONTEXT psCurContext, *ppsThisContext;
+
+ /* check we're initialised */
+ if (psResList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+ return;
+ }
+
+ psCurContext = psResList->psContextList;
+ ppsThisContext = &psResList->psContextList;
+
+ /* Walk the context list */
+ while(psCurContext != IMG_NULL)
+ {
+ /* Check current item */
+ PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurContext->ppsThis != ppsThisContext)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+ (IMG_UINTPTR_T)psCurContext,
+ (IMG_UINTPTR_T)psCurContext->ppsThis,
+ (IMG_UINTPTR_T)psCurContext->psNext,
+ (IMG_UINTPTR_T)ppsThisContext));
+ PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+ }
+
+ /* Walk the list for this context */
+ psCurItem = psCurContext->psResItemList;
+ ppsThisItem = &psCurContext->psResItemList;
+ while(psCurItem != IMG_NULL)
+ {
+ /* Check current item */
+ PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurItem->ppsThis != ppsThisItem)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+ (IMG_UINTPTR_T)psCurItem,
+ (IMG_UINTPTR_T)psCurItem->ppsThis,
+ (IMG_UINTPTR_T)psCurItem->psNext,
+ (IMG_UINTPTR_T)ppsThisItem));
+ PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+ }
+
+ /* Move to next item */
+ ppsThisItem = &psCurItem->psNext;
+ psCurItem = psCurItem->psNext;
+ }
+
+ /* Move to next context */
+ ppsThisContext = &psCurContext->psNext;
+ psCurContext = psCurContext->psNext;
+ }
+}
+#endif /* DEBUG */
+
+
+/******************************************************************************
+ End of file (resman.c)
+******************************************************************************/