static int packSPUCleanup(void) { int i; #ifdef CHROMIUM_THREADSAFE crLockMutex(&_PackMutex); #endif for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && pack_spu.thread[i].packer) { crPackDeleteContext(pack_spu.thread[i].packer); } } crFreeTSD(&_PackerTSD); crFreeTSD(&_PackTSD); #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&_PackMutex); # ifndef WINDOWS crFreeMutex(&_PackMutex); # endif #endif return 1; }
/** * This routine is called when a context or thread is done with a DLM. * It maintains an internal count of users, and will only actually destroy * itself when no one is still using the DLM. */ void DLM_APIENTRY crDLMFreeDLM(CRDLM *dlm, SPUDispatchTable *dispatchTable) { /* We're about to change the displayLists hash; lock it first */ DLM_LOCK(dlm) /* Decrement the user count. If the user count has gone to * 0, then free the rest of the DLM. Otherwise, other * contexts or threads are still using this DLM; keep * it around. */ dlm->userCount--; if (dlm->userCount == 0) { crFreeHashtableEx(dlm->displayLists, crdlmFreeDisplayListResourcesCb, dispatchTable); dlm->displayLists = NULL; /* Must unlock before freeing the mutex */ DLM_UNLOCK(dlm) #ifdef CHROMIUM_THREADSAFE /* We release the mutex here; we really should delete the * thread data key, but there's no utility in Chromium to * do this. * * Note that, should one thread release the entire DLM * while other threads still believe they are using it, * any other threads that have current display lists (i.e. * have issued glNewList more recently than glEndList) * will be unable to reclaim their (likely very large) * content buffers, as there will be no way to reclaim * the thread-specific data. * * On the other hand, if one thread really does release * the DLM while other threads still believe they are * using it, unreclaimed memory is the least of the * application's problems... */ crFreeMutex(&(dlm->dlMutex)); /* We free the TSD key here as well. Note that this will * strand any threads that still have thread-specific data * tied to this key; but as stated above, if any threads * still do have thread-specific data attached to this DLM, * they're in big trouble anyway. */ crFreeTSD(&(dlm->tsdKey)); crFreeTSD(&CRDLMTSDKey); #endif /* Free the master record, and we're all done. */ crFree(dlm); } else { /* We're keeping the DLM around for other users. Unlock it, * but retain its memory and display lists. */ DLM_UNLOCK(dlm) } }
void crStateDestroy(void) { if (__currentBits) { crStateClientDestroyBits(&(__currentBits->client)); crStateLightingDestroyBits(&(__currentBits->lighting)); crFree(__currentBits); __currentBits = NULL; } #ifdef CHROMIUM_THREADSAFE crFreeTSD(&__contextTSD); #endif }
/* Windows crap */ BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { CRNetServer ns; #ifdef CHROMIUM_THREADSAFE crInitTSD(&g_stubCurrentContextTSD); #endif crInitMutex(&stub_init_mutex); #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerRegister(); #endif crNetInit(NULL, NULL); ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerUnregister(); #endif return FALSE; } else crNetFreeConnection(ns.conn); break; } case DLL_PROCESS_DETACH: { /* do exactly the same thing as for DLL_THREAD_DETACH since * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } stubSPUSafeTearDown(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&g_stubCurrentContextTSD); #endif #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerUnregister(); #endif break; } case DLL_THREAD_ATTACH: { if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxAttachThread(); } break; } case DLL_THREAD_DETACH: { stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } break; } default: break; } return TRUE; }
static int renderSPUCleanup(void) { renderspuVBoxCompositorClearAll(); if (render_spu.blitterTable) { crFreeHashtable(render_spu.blitterTable, DeleteBlitterCallback); render_spu.blitterTable = NULL; } else { crHashtableWalk(render_spu.windowTable, renderspuBlitterCleanupCB, NULL); crHashtableWalk(render_spu.dummyWindowTable, renderspuBlitterCleanupCB, NULL); } renderspuSetDefaultSharedContext(NULL); crFreeHashtable(render_spu.contextTable, DeleteContextCallback); render_spu.contextTable = NULL; crFreeHashtable(render_spu.windowTable, DeleteWindowCallback); render_spu.windowTable = NULL; crFreeHashtable(render_spu.dummyWindowTable, DeleteWindowCallback); render_spu.dummyWindowTable = NULL; crFreeHashtable(render_spu.barrierHash, crFree); render_spu.barrierHash = NULL; #ifdef RT_OS_DARWIN # ifndef VBOX_WITH_COCOA_QT render_spu.fInit = false; DisposeEventHandlerUPP(render_spu.hParentEventHandler); ReleaseWindowGroup(render_spu.pMasterGroup); ReleaseWindowGroup(render_spu.pParentGroup); if (render_spu.hRootVisibleRegion) { DisposeRgn(render_spu.hRootVisibleRegion); render_spu.hRootVisibleRegion = 0; } render_spu.currentBufferName = 1; render_spu.uiDockUpdateTS = 0; RTSemFastMutexDestroy(render_spu.syncMutex); # else /* VBOX_WITH_COCOA_QT */ # endif /* VBOX_WITH_COCOA_QT */ #endif /* RT_OS_DARWIN */ #ifdef RT_OS_WINDOWS if (render_spu.dwWinThreadId) { HANDLE hNative; hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE, false, render_spu.dwWinThreadId); if (!hNative) { crWarning("Failed to get handle for window thread(%#x)", GetLastError()); } if (PostThreadMessage(render_spu.dwWinThreadId, WM_QUIT, 0, 0)) { WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE); /*wait for os thread to actually finish*/ if (hNative && WaitForSingleObject(hNative, 3000)==WAIT_TIMEOUT) { crDebug("Wait failed, terminating"); if (!TerminateThread(hNative, 1)) { crWarning("TerminateThread failed"); } } } if (hNative) { CloseHandle(hNative); } } CloseHandle(render_spu.hWinThreadReadyEvent); render_spu.hWinThreadReadyEvent = NULL; #endif crUnloadOpenGL(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&_RenderTSD); #endif return 1; }
/* Windows crap */ BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { CRNetServer ns; const char * env; #if defined(DEBUG_misha) HMODULE hCrUtil; char aName[MAX_PATH]; GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName)); crDbgCmdSymLoadPrint(aName, hDLLInst); hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll"); Assert(hCrUtil); crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil); #endif #ifdef CHROMIUM_THREADSAFE crInitTSD(&g_stubCurrentContextTSD); #endif crInitMutex(&stub_init_mutex); #ifdef VDBG_VEHANDLER env = crGetenv("CR_DBG_VEH_ENABLE"); g_VBoxVehEnable = crStrParseI32(env, # ifdef DEBUG_misha 1 # else 0 # endif ); if (g_VBoxVehEnable) { char procName[1024]; size_t cProcName; size_t cChars; env = crGetenv("CR_DBG_VEH_FLAGS"); g_VBoxVehFlags = crStrParseI32(env, 0 # ifdef DEBUG_misha | VBOXVEH_F_BREAK # else | VBOXVEH_F_DUMP # endif ); env = crGetenv("CR_DBG_VEH_DUMP_DIR"); if (!env) env = VBOXMD_DUMP_DIR_DEFAULT; g_cVBoxMdFilePrefixLen = strlen(env); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR)) { g_cVBoxMdFilePrefixLen = 0; env = ""; } mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE); Assert(cChars == g_cVBoxMdFilePrefixLen + 1); g_cVBoxMdFilePrefixLen = cChars - 1; if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\') g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\'; memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)); g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR); crGetProcName(procName, RT_ELEMENTS(procName)); cProcName = strlen(procName); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26) { mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE); Assert(cChars == cProcName + 1); g_cVBoxMdFilePrefixLen += cChars - 1; g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_'; } /* sanity */ g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0'; env = crGetenv("CR_DBG_VEH_DUMP_TYPE"); g_enmVBoxMdDumpType = crStrParseI32(env, MiniDumpNormal | MiniDumpWithDataSegs | MiniDumpWithFullMemory | MiniDumpWithHandleData //// | MiniDumpFilterMemory //// | MiniDumpScanMemory // | MiniDumpWithUnloadedModules //// | MiniDumpWithIndirectlyReferencedMemory //// | MiniDumpFilterModulePaths // | MiniDumpWithProcessThreadData // | MiniDumpWithPrivateReadWriteMemory //// | MiniDumpWithoutOptionalData // | MiniDumpWithFullMemoryInfo // | MiniDumpWithThreadInfo // | MiniDumpWithCodeSegs // | MiniDumpWithFullAuxiliaryState // | MiniDumpWithPrivateWriteCopyMemory // | MiniDumpIgnoreInaccessibleMemory // | MiniDumpWithTokenInformation //// | MiniDumpWithModuleHeaders //// | MiniDumpFilterTriage ); vboxVDbgVEHandlerRegister(); } #endif crNetInit(NULL, NULL); ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif return FALSE; } else { crNetFreeConnection(ns.conn); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiInit(); #endif break; } case DLL_PROCESS_DETACH: { /* do exactly the same thing as for DLL_THREAD_DETACH since * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiTerm(); #endif stubSPUSafeTearDown(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&g_stubCurrentContextTSD); #endif #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif break; } case DLL_THREAD_ATTACH: { if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxAttachThread(); } break; } case DLL_THREAD_DETACH: { stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } break; } default: break; } return TRUE; }