static void crServerTearDown( void ) { GLint i; /* avoid a race condition */ if (tearingdown) return; tearingdown = 1; crStateSetCurrent( NULL ); cr_server.curClient = NULL; cr_server.run_queue = NULL; crFree( cr_server.overlap_intens ); cr_server.overlap_intens = NULL; /* Deallocate all semaphores */ crFreeHashtable(cr_server.semaphores, crFree); cr_server.semaphores = NULL; /* Deallocate all barriers */ crFreeHashtable(cr_server.barriers, DeleteBarrierCallback); cr_server.barriers = NULL; /* Free all context info */ crFreeHashtable(cr_server.contextTable, deleteContextCallback); /* Free vertex programs */ crFreeHashtable(cr_server.programTable, crFree); for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i]) { CRConnection *conn = cr_server.clients[i]->conn; crNetFreeConnection(conn); crFree(cr_server.clients[i]); } } cr_server.numClients = 0; #if 1 /* disable these two lines if trying to get stack traces with valgrind */ crSPUUnloadChain(cr_server.head_spu); cr_server.head_spu = NULL; #endif crUnloadOpenGL(); }
static void glStubDeleteClient( CRClient *client ) { int i, j; crDebug("Deleting client %p (%d msgs left)", client, crNetNumMessages(client->conn)); #if 0 if (crNetNumMessages(client->conn) > 0) { crDebug("Delay destroying client: message still pending"); return; } #endif if (!FindClientInQueue(client)) { /* this should never happen */ crError("GLStub: client %p not found in the queue!", client); } /* remove from clients[] array */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] == client) { /* found it */ for (j = i; j < cr_server.numClients - 1; j++) cr_server.clients[j] = cr_server.clients[j + 1]; cr_server.numClients--; break; } } /* remove from the run queue */ if (cr_server.run_queue) { RunQueue *q = cr_server.run_queue; RunQueue *qStart = cr_server.run_queue; do { if (q->client == client) { /* this test seems a bit excessive */ if ((q->next == q->prev) && (q->next == q) && (cr_server.run_queue == q)) { /* We're removing/deleting the only client */ CRASSERT(cr_server.numClients == 0); crFree(q); cr_server.run_queue = NULL; cr_server.curClient = NULL; crDebug("Last client deleted - empty run queue."); } else { /* remove from doubly linked list and free the node */ if (cr_server.curClient == q->client) cr_server.curClient = NULL; if (cr_server.run_queue == q) cr_server.run_queue = q->next; q->prev->next = q->next; q->next->prev = q->prev; crFree(q); } break; } q = q->next; } while (q != qStart); } crNetFreeConnection(client->conn); crFree(client); }
/** * Do one-time initializations for the faker. * Returns TRUE on success, FALSE otherwise. */ static bool stubInitLocked(void) { /* Here is where we contact the mothership to find out what we're supposed * to be doing. Networking code in a DLL initializer. I sure hope this * works :) * * HOW can I pass the mothership address to this if I already know it? */ CRConnection *conn = NULL; char response[1024]; char **spuchain; int num_spus; int *spu_ids; char **spu_names; const char *app_id; int i; int disable_sync = 0; stubInitVars(); crGetProcName(response, 1024); crDebug("Stub launched for %s", response); #if defined(CR_NEWWINTRACK) && !defined(WINDOWS) /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread * as at the start compiz runs our code under XGrabServer. */ if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real") || !crStrcmp(response, "compiz-bin")) { disable_sync = 1; } #elif defined(WINDOWS) && defined(VBOX_WITH_WDDM) && defined(VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS) if (GetModuleHandle(VBOX_MODNAME_DISPD3D)) { disable_sync = 1; crDebug("running with " VBOX_MODNAME_DISPD3D); stub.trackWindowVisibleRgn = 0; stub.bRunningUnderWDDM = true; } #endif /* @todo check if it'd be of any use on other than guests, no use for windows */ app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" ); crNetInit( NULL, NULL ); #ifndef WINDOWS { CRNetServer ns; ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM."); return false; } else { crNetFreeConnection(ns.conn); } #if 0 && defined(CR_NEWWINTRACK) { Status st = XInitThreads(); if (st==0) { crWarning("XInitThreads returned %i", (int)st); } } #endif } #endif strcpy(response, "2 0 feedback 1 pack"); spuchain = crStrSplit( response, " " ); num_spus = crStrToInt( spuchain[0] ); spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) ); spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) ); for (i = 0 ; i < num_spus ; i++) { spu_ids[i] = crStrToInt( spuchain[2*i+1] ); spu_names[i] = crStrdup( spuchain[2*i+2] ); crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] ); } stubSetDefaultConfigurationOptions(); stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL ); crFree( spuchain ); crFree( spu_ids ); for (i = 0; i < num_spus; ++i) crFree(spu_names[i]); crFree( spu_names ); // spu chain load failed somewhere if (!stub.spu) { return false; } crSPUInitDispatchTable( &glim ); /* This is unlikely to change -- We still want to initialize our dispatch * table with the functions of the first SPU in the chain. */ stubInitSPUDispatch( stub.spu ); /* we need to plug one special stub function into the dispatch table */ glim.GetChromiumParametervCR = stub_GetChromiumParametervCR; #if !defined(VBOX_NO_NATIVEGL) /* Load pointers to native OpenGL functions into stub.nativeDispatch */ stubInitNativeDispatch(); #endif /*crDebug("stub init"); raise(SIGINT);*/ #ifdef WINDOWS # ifndef CR_NEWWINTRACK stubInstallWindowMessageHook(); # endif #endif #ifdef CR_NEWWINTRACK { int rc; RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); if (!disable_sync) { crDebug("Starting sync thread"); rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync"); if (RT_FAILURE(rc)) { crError("Failed to start sync thread! (%x)", rc); } RTThreadUserWait(stub.hSyncThread, 60 * 1000); RTThreadUserReset(stub.hSyncThread); crDebug("Going on"); } } #endif #ifdef GLX stub.xshmSI.shmid = -1; stub.bShmInitFailed = GL_FALSE; stub.pGLXPixmapsHash = crAllocHashtable(); stub.bXExtensionsChecked = GL_FALSE; stub.bHaveXComposite = GL_FALSE; stub.bHaveXFixes = GL_FALSE; #endif return true; }
/* 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; }
void PACKSPU_APIENTRY packspu_VBoxDetachThread() { int i; GET_THREAD(thread); if (thread) { crLockMutex(&_PackMutex); for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID() && thread->netServer.conn) { CRASSERT(pack_spu.numThreads>0); packspuFlush((void *) thread); if (pack_spu.thread[i].packer) { CR_LOCK_PACKER_CONTEXT(thread->packer); crPackSetContext(NULL); CR_UNLOCK_PACKER_CONTEXT(thread->packer); crPackDeleteContext(pack_spu.thread[i].packer); } crNetFreeConnection(pack_spu.thread[i].netServer.conn); pack_spu.numThreads--; /*note can't shift the array here, because other threads have TLS references to array elements*/ crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo)); crSetTSD(&_PackTSD, NULL); if (i==pack_spu.idxThreadInUse) { for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse) { pack_spu.idxThreadInUse=i; break; } } } break; } } for (i=0; i<CR_MAX_CONTEXTS; ++i) { ContextInfo *ctx = &pack_spu.context[i]; if (ctx->currentThread == thread) { CRASSERT(ctx->fAutoFlush); ctx->currentThread = NULL; } } crUnlockMutex(&_PackMutex); } crStateVBoxDetachThread(); }
void crServerDeleteClient( CRClient *client ) { int i, j; int cleanup=1; crDebug("Deleting client %p (%d msgs left)", client, crNetNumMessages(client->conn)); #if 0 if (crNetNumMessages(client->conn) > 0) { crDebug("Delay destroying client: message still pending"); return; } #endif if (!FindClientInQueue(client)) { /* this should never happen */ crError("CRServer: client %p not found in the queue!", client); } /* remove from clients[] array */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] == client) { /* found it */ for (j = i; j < cr_server.numClients - 1; j++) cr_server.clients[j] = cr_server.clients[j + 1]; cr_server.numClients--; break; } } /* check if there're any other guest threads in same process */ for (i=0; i < cr_server.numClients; i++) { if (cr_server.clients[i]->pid==client->pid) { cleanup=0; break; } } if (cleanup) { crServerCleanupClient(client); } /* remove from the run queue */ if (cr_server.run_queue) { RunQueue *q = cr_server.run_queue; RunQueue *qStart = cr_server.run_queue; do { if (q->client == client) { /* this test seems a bit excessive */ if ((q->next == q->prev) && (q->next == q) && (cr_server.run_queue == q)) { /* We're removing/deleting the only client */ CRASSERT(cr_server.numClients == 0); crFree(q); cr_server.run_queue = NULL; cr_server.curClient = NULL; crDebug("Last client deleted - empty run queue."); } else { /* remove from doubly linked list and free the node */ if (cr_server.curClient == q->client) cr_server.curClient = NULL; if (cr_server.run_queue == q) cr_server.run_queue = q->next; q->prev->next = q->next; q->next->prev = q->prev; crFree(q); } break; } q = q->next; } while (q != qStart); } crNetFreeConnection(client->conn); client->conn = NULL; if (cleanup) { crServerCleanupByPID(client->pid); crFree(client); } else { CRClientNode *pNode = (CRClientNode *)crAlloc(sizeof(CRClientNode)); if (!pNode) { crWarning("Not enough memory, forcing client cleanup"); crServerCleanupClient(client); crServerCleanupByPID(client->pid); crFree(client); return; } pNode->pClient = client; pNode->prev = NULL; pNode->next = cr_server.pCleanupClient; cr_server.pCleanupClient = pNode; } }
void crServerDeleteClient( CRClient *client ) { int i, j; int cleanup=1; crDebug("Deleting client %p (%d msgs left)", client, crNetNumMessages(client->conn)); #if 0 if (crNetNumMessages(client->conn) > 0) { crDebug("Delay destroying client: message still pending"); return; } #endif if (!FindClientInQueue(client)) { /* this should never happen */ crError("CRServer: client %p not found in the queue!", client); } /* remove from clients[] array */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] == client) { /* found it */ for (j = i; j < cr_server.numClients - 1; j++) cr_server.clients[j] = cr_server.clients[j + 1]; cr_server.numClients--; break; } } /* check if there're any other guest threads in same process */ for (i=0; i < cr_server.numClients; i++) { if (cr_server.clients[i]->pid==client->pid) { cleanup=0; break; } } if (cleanup) { crServerCleanupClient(client); } /* remove from the run queue */ if (cr_server.run_queue) { RunQueue *q = cr_server.run_queue; RunQueue *qStart = cr_server.run_queue; do { if (q->client == client) { /* this test seems a bit excessive */ if ((q->next == q->prev) && (q->next == q) && (cr_server.run_queue == q)) { /* We're removing/deleting the only client */ CRASSERT(cr_server.numClients == 0); crFree(q); cr_server.run_queue = NULL; cr_server.curClient = NULL; crDebug("Last client deleted - empty run queue."); } else { /* remove from doubly linked list and free the node */ if (cr_server.curClient == q->client) cr_server.curClient = NULL; if (cr_server.run_queue == q) cr_server.run_queue = q->next; q->prev->next = q->next; q->next->prev = q->prev; crFree(q); } break; } q = q->next; } while (q != qStart); } crNetFreeConnection(client->conn); client->conn = NULL; if (cleanup) { crServerCleanupByPID(client->pid); crFree(client); } else { CRClientNode *pNode = (CRClientNode *)crAlloc(sizeof(CRClientNode)); if (!pNode) { crWarning("Not enough memory, forcing client cleanup"); crServerCleanupClient(client); crServerCleanupByPID(client->pid); crFree(client); return; } pNode->pClient = client; pNode->prev = NULL; pNode->next = cr_server.pCleanupClient; cr_server.pCleanupClient = pNode; } if (!cr_server.numClients) { /* if no clients, the guest driver may be unloaded, * and thus the visible regions situation might not be under control anymore, * so cleanup the 3D framebuffer data here * @todo: what really should happen is that guest driver on unload * posts some request to host that would copy the current framebuffer 3D data to the 2D buffer * (i.e. to the memory used by the standard IFramebuffer API) */ HCR_FRAMEBUFFER hFb; for (hFb = CrPMgrFbGetFirstEnabled(); hFb; hFb = CrPMgrFbGetNextEnabled(hFb)) { int rc = CrFbUpdateBegin(hFb); if (RT_SUCCESS(rc)) { CrFbRegionsClear(hFb); CrFbUpdateEnd(hFb); } else WARN(("CrFbUpdateBegin failed %d", rc)); } } }
static void crServerTearDown( void ) { GLint i; CRClientNode *pNode, *pNext; /* avoid a race condition */ if (tearingdown) return; tearingdown = 1; crStateSetCurrent( NULL ); cr_server.curClient = NULL; cr_server.run_queue = NULL; crFree( cr_server.overlap_intens ); cr_server.overlap_intens = NULL; /* Deallocate all semaphores */ crFreeHashtable(cr_server.semaphores, crFree); cr_server.semaphores = NULL; /* Deallocate all barriers */ crFreeHashtable(cr_server.barriers, DeleteBarrierCallback); cr_server.barriers = NULL; /* Free all context info */ crFreeHashtable(cr_server.contextTable, deleteContextCallback); /* Free context/window creation info */ crFreeHashtable(cr_server.pContextCreateInfoTable, crServerCreateInfoDeleteCB); crFreeHashtable(cr_server.pWindowCreateInfoTable, crServerCreateInfoDeleteCB); /* Free vertex programs */ crFreeHashtable(cr_server.programTable, crFree); for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i]) { CRConnection *conn = cr_server.clients[i]->conn; crNetFreeConnection(conn); crFree(cr_server.clients[i]); } } cr_server.numClients = 0; pNode = cr_server.pCleanupClient; while (pNode) { pNext=pNode->next; crFree(pNode->pClient); crFree(pNode); pNode=pNext; } cr_server.pCleanupClient = NULL; #if 1 /* disable these two lines if trying to get stack traces with valgrind */ crSPUUnloadChain(cr_server.head_spu); cr_server.head_spu = NULL; #endif crStateDestroy(); crNetTearDown(); }
/* 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; }