/** * Creates MidpSession for the specified XRPC client id. Invoked on the XRPC * thread under synchronization. */ STATIC MidpSession* GWENG_MidpCreateSession(EcmtGateway* gw, int xrpcSid) { MidpSession* ses = MEM_New(MidpSession); if (ses) { LUID luid; /* Just in case if AllocateLocallyUniqueId fails... */ luid.LowPart = (DWORD)ses; AllocateLocallyUniqueId(&luid); memset(ses, 0, sizeof(*ses)); ses->key.xrpcSid = xrpcSid; ses->key.xrpcSession = XRPC_GetCurrentSession(gw->xrpc); ses->sid = luid.LowPart; ASSERT(!HASH_Contains(&gw->ecmtSessionMap,(HashKey)ses->sid)); ASSERT(!HASH_Contains(&gw->midpSessionMap,&ses->key)); if (HASH_Init(&ses->connMap, 1, NULL, NULL, hashFreeValueProc)) { /* Create context for the control connection (number zero) */ MidpConnection* conn = MEM_New(MidpConnection); if (conn) { memset(conn, 0, sizeof(*conn)); if (HASH_Put(&ses->connMap, (HashKey)0, conn)) { if (HASH_Put(&gw->ecmtSessionMap,(HashKey)ses->sid,ses)) { if (HASH_Put(&gw->midpSessionMap, &ses->key, ses)) { if (MUTEX_Init(&ses->xrpcMutex)) { ses->xrpcWorkThread = WKQ_Create(); if (ses->xrpcWorkThread) { ses->xrpcWorkItem = WKI_Create( ses->xrpcWorkThread, GWENG_AsyncXRpc, ses); if (ses->xrpcWorkItem) { QUEUE_Init(&ses->xrpcQueue); TRACE3("GW: new session %08x for " "%08x.%08x\n", ses->sid, ses->key.xrpcSession, ses->key.xrpcSid); return ses; } WKQ_Delete(ses->xrpcWorkThread); } MUTEX_Destroy(&ses->xrpcMutex); } HASH_Remove(&gw->midpSessionMap, &ses->key); } HASH_Remove(&gw->ecmtSessionMap, (HashKey)ses->sid); } } else { MEM_Free(conn); } } HASH_Destroy(&ses->connMap); } MEM_Free(ses); } return NULL; }
void RA_Free(struct RA_ARENA *pArena, u32 base, IMG_BOOL bFreeBackingStore) { struct BT *pBT; PVR_ASSERT(pArena != NULL); if (pArena == NULL) { PVR_DPF(PVR_DBG_ERROR, "RA_Free: invalid parameter - pArena"); return; } PVR_DPF(PVR_DBG_MESSAGE, "RA_Free: name='%s', base=0x%x", pArena->name, base); pBT = (struct BT *)HASH_Remove(pArena->pSegmentHash, base); PVR_ASSERT(pBT != NULL); if (pBT) { PVR_ASSERT(pBT->base == base); #ifdef RA_STATS pArena->sStatistics.uCumulativeFrees++; #endif _FreeBT(pArena, pBT, bFreeBackingStore); } }
IMG_VOID BM_Free (BM_HANDLE hBuf, IMG_UINT32 ui32Flags) { BM_BUF *pBuf = (BM_BUF *)hBuf; SYS_DATA *psSysData; IMG_SYS_PHYADDR sHashAddr; PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%x)", (IMG_UINTPTR_T)hBuf)); PVR_ASSERT (pBuf!=IMG_NULL); if (pBuf == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter")); return; } SysAcquireData(&psSysData); pBuf->ui32RefCount--; if(pBuf->ui32RefCount == 0) { if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) { sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr); HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddr.uiAddr); } FreeBuf (pBuf, ui32Flags, IMG_TRUE); } }
void BM_Free(void *hBuf, u32 ui32Flags) { struct BM_BUF *pBuf = (struct BM_BUF *)hBuf; struct SYS_DATA *psSysData; struct IMG_SYS_PHYADDR sHashAddr; PVR_DPF(PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf); PVR_ASSERT(pBuf != NULL); if (pBuf == NULL) { PVR_DPF(PVR_DBG_ERROR, "BM_Free: invalid parameter"); return; } if (SysAcquireData(&psSysData) != PVRSRV_OK) return; pBuf->ui32RefCount--; if (pBuf->ui32RefCount == 0) { struct BM_MAPPING *map = pBuf->pMapping; struct BM_CONTEXT *ctx = map->pBMHeap->pBMContext; if (map->eCpuMemoryOrigin == hm_wrapped || map->eCpuMemoryOrigin == hm_wrapped_virtaddr) { sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr); HASH_Remove(ctx->pBufferHash, (u32)sHashAddr.uiAddr); } FreeBuf(pBuf, ui32Flags); pvr_put_ctx(ctx); } }
/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferDestroy @Description Destroy a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID) { #if !defined(TTRACE_KEEP_BUFFER_ON_EXIT) sTimeTraceBuffer *psBuffer; #if defined(DUMP_TTRACE_BUFFERS_ON_EXIT) PVRSRVDumpTimeTraceBuffers(); #endif LinuxLockMutex(&g_sTTraceMutex); psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); if (psBuffer) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE, psBuffer, NULL); HASH_Remove(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); LinuxUnLockMutex(&g_sTTraceMutex); return PVRSRV_OK; } PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferDestroy: Can't find trace buffer in hash table")); LinuxUnLockMutex(&g_sTTraceMutex); return PVRSRV_ERROR_INVALID_PARAMS; #else return PVRSRV_OK; #endif }
IMG_VOID RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore) { BT *pBT; PVR_ASSERT (pArena != IMG_NULL); if (pArena == IMG_NULL) { PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena")); return; } #ifdef USE_BM_FREESPACE_CHECK CheckBMFreespace(); #endif PVR_DPF ((PVR_DBG_MESSAGE, "RA_Free: name='%s', base=0x%x", pArena->name, base)); pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base); PVR_ASSERT (pBT != IMG_NULL); if (pBT) { PVR_ASSERT (pBT->base == base); #ifdef RA_STATS pArena->sStatistics.uCumulativeFrees++; #endif #ifdef USE_BM_FREESPACE_CHECK { IMG_BYTE* p; IMG_BYTE* endp; p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(); endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize)); while ((IMG_UINT32)p & 3) { *p++ = 0xAA; } while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc)) { *(IMG_UINT32*)p = 0xAAAAAAAA; p += sizeof(IMG_UINT32); } while (p < endp) { *p++ = 0xAA; } PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize)); } #endif _FreeBT (pArena, pBT, bFreeBackingStore); } }
/** * Deallocates the MIDP session context. */ STATIC void GWENG_MidpFree(EcmtGateway* gw, MidpSession* midp) { if (midp) { QEntry* e; VERIFY(HASH_Remove(&gw->midpSessionMap, &midp->key)); HASH_Remove(&gw->ecmtSessionMap, (HashKey)midp->sid); HASH_Destroy(&midp->connMap); WKI_Cancel(midp->xrpcWorkItem); WKI_Detach(midp->xrpcWorkItem); WKQ_Delete(midp->xrpcWorkThread); MUTEX_Destroy(&midp->xrpcMutex); while ((e = QUEUE_RemoveHead(&midp->xrpcQueue)) != NULL) { AsyncXRpcEntry* a = QCAST(e,AsyncXRpcEntry,entry); XRPC_FreeContainer(a->params); MEM_Free(a); } MEM_Free(midp); } }
static inline void put_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo) { struct PVRSRV_DEVICE_NODE *dev = syncinfo->dev_cookie; syncinfo->refcount--; if (!syncinfo->refcount) { HASH_Remove(dev->sync_table, syncinfo->phys_addr.uiAddr); PVRSRVFreeSyncInfoKM(syncinfo); } }
static enum PVRSRV_ERROR FreePerProcessData( struct PVRSRV_PER_PROCESS_DATA *psPerProc) { enum PVRSRV_ERROR eError; u32 uiPerProc; PVR_ASSERT(psPerProc != NULL); uiPerProc = HASH_Remove(psHashTab, (u32)psPerProc->ui32PID); if (uiPerProc == 0) { PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: " "Couldn't find process in per-process data hash table"); PVR_ASSERT(psPerProc->ui32PID == 0); } else { PVR_ASSERT((struct PVRSRV_PER_PROCESS_DATA *) uiPerProc == psPerProc); PVR_ASSERT(((struct PVRSRV_PER_PROCESS_DATA *)uiPerProc)-> ui32PID == psPerProc->ui32PID); } if (psPerProc->psHandleBase != NULL) { eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: " "Couldn't free handle base for process (%d)", eError); return eError; } } if (psPerProc->hPerProcData != NULL) { eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "FreePerProcessData: " "Couldn't release per-process data handle (%d)", eError); return eError; } } OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), psPerProc, psPerProc->hBlockAlloc); return PVRSRV_OK; }
/** * Sends "reset" event to both XRPC and ECMT clients and deallocates the * connection context. Caller must hold the mutex. */ STATIC void GWENG_MidpResetConn(EcmtGateway* gw, MidpSession* midp, I32u cid, Bool resetEcmt, Bool resetXrpc) { TRACE1("GW: resetting connection %u\n",cid); HASH_Remove(&midp->connMap, (HashKey)cid); if (resetEcmt) { char pkt[ECMT_MIDP_DEBUG_RESET_SIZE]; GWENG_MidpFillHeader(pkt, midp->sid, ECMT_MIDP_DEBUG_OPCODE_RESET); *((I32u*)(pkt+ECMT_MIDP_DEBUG_RESET_CID_OFFSET)) = htonl(cid); GWENG_QueueAdd(gw->handsetQueue, KECMT_MIDP_DEBUG_PLUGIN_UID, pkt, ECMT_MIDP_DEBUG_RESET_SIZE); } if (resetXrpc) { GWENG_SubmitAsyncCall(midp, ECMTGW_SEI_RESET_METHOD, GWENG_CreateXRpcParams(midp, ECMTGW_SEI_RESET_SID_PARAM, ECMTGW_SEI_RESET_CID_PARAM, cid)); } }
/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferDestroy @Description Destroy a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID) { sTimeTraceBuffer *psBuffer; #if defined(DUMP_TTRACE_BUFFERS_ON_EXIT) PVRSRVDumpTimeTraceBuffers(); #endif psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); if (psBuffer) { if (psBuffer->pui8Data) OSFreeMem(PVRSRV_PAGEABLE_SELECT, TIME_TRACE_BUFFER_SIZE, psBuffer->pui8Data, NULL); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer), psBuffer, NULL); HASH_Remove(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); return PVRSRV_OK; } PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferDestroy: Can't find trace buffer in hash table")); return PVRSRV_ERROR_INVALID_PARAMS; }
/*! ****************************************************************************** @Function FreePerProcData @Description Free a per-process data area @Input psPerProc - pointer to per-process data area @Return Error code, or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc) { PVRSRV_ERROR eError; IMG_UINTPTR_T uiPerProc; PVR_ASSERT(psPerProc != IMG_NULL); if (psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter")); return PVRSRV_ERROR_INVALID_PARAMS; } uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID); if (uiPerProc == 0) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table")); /* * We must have failed early in the per-process data area * creation, before the process ID was set. */ PVR_ASSERT(psPerProc->ui32PID == 0); } else { PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc); PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID); } /* Free handle base for this process */ if (psPerProc->psHandleBase != IMG_NULL) { eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError)); return eError; } } /* Release handle for per-process data area */ if (psPerProc->hPerProcData != IMG_NULL) { eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError)); return eError; } } /* Call environment specific per process deinit function */ eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError)); return eError; } eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), psPerProc, psPerProc->hBlockAlloc); /*not nulling pointer, copy on stack*/ if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError)); return eError; } return PVRSRV_OK; }
static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc) { PVRSRV_ERROR eError; IMG_UINTPTR_T uiPerProc; PVR_ASSERT(psPerProc != IMG_NULL); if (psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter")); return PVRSRV_ERROR_INVALID_PARAMS; } uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID); if (uiPerProc == 0) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table")); PVR_ASSERT(psPerProc->ui32PID == 0); } else { PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc); PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID); } if (psPerProc->psHandleBase != IMG_NULL) { eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError)); return eError; } } if (psPerProc->hPerProcData != IMG_NULL) { eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError)); return eError; } } eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError)); return eError; } eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), psPerProc, psPerProc->hBlockAlloc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError)); return eError; } return PVRSRV_OK; }
/** * @brief Unit test function. */ bool HASH_test () { // return value bool result = true; /* test 1: create the hash table, delete the hash table */ hashTable_s* table = HASH_NewTable(true, true, true); HASH_DeleteTable (&table); /* check table pointer is correctly set to nil */ result = result && (table == NULL); if (!result) return false; /* check alloc total */ result = result && (_num_allocs == 0); if (!result) return false; /* test 2: create the hash table, insert 3 values, delete the hash table */ table = HASH_NewTable(true, true, true); HASH_Insert (table, "AAA", 4, "AAA", 4); HASH_Insert (table, "BBB", 4, "BBB", 4); HASH_Insert (table, "CCC", 4, "CCC", 4); if (HASH_Count(table) != 3) return false; HASH_Clear (table); if (HASH_Count(table) != 0) return false; HASH_DeleteTable (&table); /* check table pointer is correctly set to nil */ result = result && (table == NULL); if (!result) return false; /* check alloc total */ result = result && (_num_allocs == 0); if (!result) return false; /* test 3: create the hash table, insert/remove 3 values, delete the hash table */ table = HASH_NewTable(true, true, true); HASH_Insert (table, "AAA", 4, "AAA", 4); HASH_Remove (table, "AAA", 4); HASH_Insert (table, "BBB", 4, "BBB", 4); HASH_Remove (table, "BBB", 4); HASH_Insert (table, "CCC", 4, "CCC", 4); HASH_Remove (table, "CCC", 4); HASH_DeleteTable (&table); /* check table pointer is correctly set to nil */ result = result && (table == NULL); if (!result) return false; /* check alloc total */ result = result && (_num_allocs == 0); if (!result) return false; /* test 4: create the hash table, insert/count/search/delete 3 values, delete the hash table */ table = HASH_NewTable(true, true, true); HASH_Insert (table, "AAA", 4, "AAA", 4); HASH_Insert (table, "BBB", 4, "BBB", 4); HASH_Insert (table, "CCC", 4, "CCC", 4); /* check count items */ if (HASH_Count(table) != 3) return false; char* aaa = (char*)HASH_Get(table, "AAA", 4); if (strncmp (aaa, "AAA", 4) != 0) return false; char* bbb = (char*)HASH_Get(table, "BBB", 4); if (strncmp (bbb, "BBB", 4) != 0) return false; char* ccc = (char*)HASH_Get(table, "CCC", 4); if (strncmp (ccc, "CCC", 4) != 0) return false; HASH_Remove (table, "AAA", 4); HASH_Remove (table, "BBB", 4); HASH_Remove (table, "CCC", 4); if (HASH_Count(table) != 0) return false; HASH_DeleteTable (&table); /* check table pointer is correctly set to nil */ result = result && (table == NULL); if (!result) return false; /* check alloc total */ result = result && (_num_allocs == 0); if (!result) return false; /* test 5: hash function test */ const char AZ[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; char buffer[26]; /* compute the averag of the hash index of 400 random keys */ int total = 0; srand(time(NULL)); for(int i=0; i < 4000; i++) { /* create random key of random length between 4..23 charachters */ int len = 4 + (rand() % 20); memset (buffer, 0, sizeof(buffer)); for (int j=0; j < len; j++) { int v = rand() % sizeof(AZ); buffer[j]=AZ[v]; } /* compute the hash index */ int idx = default_hash (buffer, len); /* sum index */ total += idx; } /* now compute the average of the indices */ int avg = (total / 4000); /* the average idx should be somewhere halfway, allow a %10 error margin */ int idx_low = (HASH_TABLE_SIZE/2) - (HASH_TABLE_SIZE/10); int idx_high = (HASH_TABLE_SIZE/2) + (HASH_TABLE_SIZE/10); if ( !((idx_low <= avg) && (idx_high >= avg)) ) return false; /* test 6: hash table without ownership test */ table = HASH_NewTable(true, false, true); char item1[] = "AAA"; char item2[] = "BBB"; char item3[] = "CCC"; HASH_Insert (table, item1, 4, item1, 4); HASH_Insert (table, item2, 4, item2, 4); HASH_Insert (table, item3, 4, item3, 4); /* check if we get the correct value pointers */ aaa = (char*)HASH_Get(table, "AAA", 4); if (aaa != item1) return false; bbb = (char*)HASH_Get(table, "BBB", 4); if (bbb != item2) return false; ccc = (char*)HASH_Get(table, "CCC", 4); if (ccc != item3) return false; HASH_DeleteTable (&table); /* check table pointer is correctly set to nil */ result = result && (table == NULL); if (!result) return false; /* check alloc total */ result = result && (_num_allocs == 0); if (!result) return false; /* end of unit test, everything OK */ return true; }