void crVBoxHGSMITearDown(void) { int32_t i, cCons; Assert(0); if (!g_crvboxhgsmi.initialized) return; /* Connection count would be changed in calls to crNetDisconnect, so we have to store original value. * Walking array backwards is not a good idea as it could cause some issues if we'd disconnect clients not in the * order of their connection. */ cCons = g_crvboxhgsmi.num_conns; for (i=0; i<cCons; i++) { /* Note that [0] is intended, as the connections array would be shifted in each call to crNetDisconnect */ crNetDisconnect(g_crvboxhgsmi.conns[0]); } CRASSERT(0==g_crvboxhgsmi.num_conns); #ifdef CHROMIUM_THREADSAFE crFreeMutex(&g_crvboxhgsmi.mutex); crFreeMutex(&g_crvboxhgsmi.recvmutex); #endif if (g_crvboxhgsmi.mempool) crBufferPoolCallbackFree(g_crvboxhgsmi.mempool, _crVBoxHGSMISysMemFree); g_crvboxhgsmi.mempool = NULL; g_crvboxhgsmi.initialized = 0; crFree(g_crvboxhgsmi.conns); g_crvboxhgsmi.conns = NULL; }
BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { crInitMutex(&_PackMutex); break; } case DLL_PROCESS_DETACH: { crFreeMutex(&_PackMutex); crNetTearDown(); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: default: break; } return TRUE; }
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) } }
/** * Tear down a network connection (close the socket, etc). */ void crNetDisconnect( CRConnection *conn ) { conn->Disconnect( conn ); crFree( conn->hostname ); #ifdef CHROMIUM_THREADSAFE crFreeMutex( &conn->messageList.lock ); #endif crFree( conn ); }
static void crSDPDoDisconnect( CRConnection *conn ) { int num_conns = cr_sdp.num_conns; int none_left = 1; int i; /* If this connection has already been disconnected (e.g. * if the connection has been lost and disabled through * a call to __sdp_dead_connection(), which will then * call this routine), don't disconnect it again; if we * do, and if a new valid connection appears in the same * slot (conn->index), we'll effectively disable the * valid connection by mistake, leaving us unable to * receive inbound data on that connection. */ if (conn->type == CR_NO_CONNECTION) return; crCloseSocket( conn->sdp_socket ); conn->sdp_socket = 0; conn->type = CR_NO_CONNECTION; cr_sdp.conns[conn->index] = NULL; for (i = 0; i < num_conns; i++) { if ( cr_sdp.conns[i] && cr_sdp.conns[i]->type != CR_NO_CONNECTION ) none_left = 0; /* found a live connection */ } if (none_left && cr_sdp.server_sock != -1) { crDebug("Closing master socket (probably quitting)."); crCloseSocket( cr_sdp.server_sock ); #ifdef CHROMIUM_THREADSAFE crFreeMutex(&cr_sdp.mutex); crFreeMutex(&cr_sdp.recvmutex); #endif crBufferPoolFree( cr_sdp.bufpool ); cr_sdp.bufpool = NULL; last_port = 0; cr_sdp.initialized = 0; } }
void crFreeHashtable( CRHashTable *hash, CRHashtableCallback deleteFunc ) { int i; CRHashNode *entry, *next; if ( !hash) return; #ifdef CHROMIUM_THREADSAFE crLockMutex(&hash->mutex); #endif for ( i = 0; i < CR_NUM_BUCKETS; i++ ) { entry = hash->buckets[i]; while (entry) { next = entry->next; /* Clear the key in case crHashtableDelete() is called * from this callback. */ entry->key = 0; if (deleteFunc && entry->data) { (*deleteFunc)(entry->data); } crFree(entry); entry = next; } } crFreeHashIdPool( hash->idPool ); #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&hash->mutex); crFreeMutex(&hash->mutex); #endif crFree( hash ); }
BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { crInitMutex(&_PackMutex); break; } case DLL_PROCESS_DETACH: { crFreeMutex(&_PackMutex); crNetTearDown(); break; } case DLL_THREAD_ATTACH: { packspu_VBoxPackAttachThread(); crStateOnThreadAttachDetach(GL_TRUE); break; } case DLL_THREAD_DETACH: { packspu_VBoxPackDetachThread(); crStateOnThreadAttachDetach(GL_FALSE); break; } default: break; } return TRUE; }
/* Free up stuff */ void crNetTearDown() { CRNetReceiveFuncList *rfl; CRNetCloseFuncList *cfl; void *tmp; if (!cr_net.initialized) return; #ifdef CHROMIUM_THREADSAFE crLockMutex(&cr_net.mutex); #endif /* Note, other protocols used by chromium should free up stuff too, * but VBox doesn't use them, so no other checks. */ if (cr_net.use_hgcm) crVBoxHGCMTearDown(); for (rfl = cr_net.recv_list ; rfl ; rfl = (CRNetReceiveFuncList *) tmp ) { tmp = rfl->next; crFree(rfl); } for (cfl = cr_net.close_list ; cfl ; cfl = (CRNetCloseFuncList *) tmp ) { tmp = cfl->next; crFree(cfl); } cr_net.initialized = 0; #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&cr_net.mutex); crFreeMutex(&cr_net.mutex); #endif }
static void stubSPUSafeTearDown(void) { #ifdef CHROMIUM_THREADSAFE CRmutex *mutex; #endif if (!stub_initialized) return; stub_initialized = 0; #ifdef CHROMIUM_THREADSAFE mutex = &stub.mutex; crLockMutex(mutex); #endif crDebug("stubSPUSafeTearDown"); #ifdef WINDOWS # ifndef CR_NEWWINTRACK stubUninstallWindowMessageHook(); # endif #endif #if defined(CR_NEWWINTRACK) crUnlockMutex(mutex); # if defined(WINDOWS) if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED) { HANDLE hNative; DWORD ec=0; hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE, false, RTThreadGetNative(stub.hSyncThread)); if (!hNative) { crWarning("Failed to get handle for sync thread(%#x)", GetLastError()); } else { crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread)); } ASMAtomicWriteBool(&stub.bShutdownSyncThread, true); if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0)) { RTThreadWait(stub.hSyncThread, 1000, NULL); /*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads * to issues as our dll goes to be unloaded. *@todo *We usually call this function from DllMain which seems to be holding some lock and thus we have to * kill thread via TerminateThread. */ if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT) { crDebug("Wait failed, terminating"); if (!TerminateThread(hNative, 1)) { crDebug("TerminateThread failed"); } } if (GetExitCodeThread(hNative, &ec)) { crDebug("Thread %p exited with ec=%i", hNative, ec); } else { crDebug("GetExitCodeThread failed(%#x)", GetLastError()); } } else { crDebug("Sync thread killed before DLL_PROCESS_DETACH"); } if (hNative) { CloseHandle(hNative); } } #else if (stub.hSyncThread!=NIL_RTTHREAD) { ASMAtomicWriteBool(&stub.bShutdownSyncThread, true); { /*RTThreadWait might return too early, which cause our code being unloaded while RT thread wrapper is still running*/ int rc = pthread_join(RTThreadGetNative(stub.hSyncThread), NULL); if (!rc) { crDebug("pthread_join failed %i", rc); } } } #endif crLockMutex(mutex); #endif #ifndef WINDOWS crNetTearDown(); #endif #ifdef CHROMIUM_THREADSAFE crUnlockMutex(mutex); crFreeMutex(mutex); #endif crMemset(&stub, 0, sizeof(stub)); }
/** * Establish a connection with a server. * \param server the server to connect to, in the form * "protocol://servername:port" where the port specifier * is optional and if the protocol is missing it is assumed * to be "tcpip". * \param default_port the port to connect to, if port not specified in the * server URL string. * \param mtu desired maximum transmission unit size (in bytes) * \param broker either 1 or 0 to indicate if connection is brokered through * the mothership */ CRConnection * crNetConnectToServer( const char *server, unsigned short default_port, int mtu, int broker #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , struct VBOXUHGSMI *pHgsmi #endif ) { char hostname[4096], protocol[4096]; unsigned short port; CRConnection *conn; crDebug( "In crNetConnectToServer( \"%s\", port=%d, mtu=%d, broker=%d )", server, default_port, mtu, broker ); CRASSERT( cr_net.initialized ); if (mtu < CR_MINIMUM_MTU) { crError( "You tried to connect to server \"%s\" with an mtu of %d, " "but the minimum MTU is %d", server, mtu, CR_MINIMUM_MTU ); } /* Tear the URL apart into relevant portions. */ if ( !crParseURL( server, protocol, hostname, &port, default_port ) ) { crError( "Malformed URL: \"%s\"", server ); } /* If the host name is "localhost" replace it with the _real_ name * of the localhost. If we don't do this, there seems to be * confusion in the mothership as to whether or not "localhost" and * "foo.bar.com" are the same machine. */ if (crStrcmp(hostname, "localhost") == 0) { int rv = crGetHostname(hostname, 4096); CRASSERT(rv == 0); (void) rv; } /* XXX why is this here??? I think it could be moved into the * crTeacConnection() function with no problem. I.e. change the * connection's port, teac_rank and tcscomm_rank there. (BrianP) */ if ( !crStrcmp( protocol, "quadrics" ) || !crStrcmp( protocol, "quadrics-tcscomm" ) ) { /* For Quadrics protocols, treat "port" as "rank" */ if ( port > CR_QUADRICS_HIGHEST_RANK ) { crWarning( "Invalid crserver rank, %d, defaulting to %d\n", port, CR_QUADRICS_LOWEST_RANK ); port = CR_QUADRICS_LOWEST_RANK; } } crDebug( "Connecting to %s on port %d, with protocol %s", hostname, port, protocol ); #ifdef SDP_SUPPORT /* This makes me ill, but we need to "fix" the hostname for sdp. MCH */ if (!crStrcmp(protocol, "sdp")) { char* temp; temp = strtok(hostname, "."); crStrcat(temp, crGetSDPHostnameSuffix()); crStrcpy(hostname, temp); crDebug("SDP rename hostname: %s", hostname); } #endif conn = (CRConnection *) crCalloc( sizeof(*conn) ); if (!conn) return NULL; /* init the non-zero fields */ conn->type = CR_NO_CONNECTION; /* we don't know yet */ conn->recv_credits = CR_INITIAL_RECV_CREDITS; conn->hostname = crStrdup( hostname ); conn->port = port; conn->mtu = mtu; conn->buffer_size = mtu; conn->broker = broker; conn->endianness = crDetermineEndianness(); /* XXX why are these here??? Move them into the crTeacConnection() * and crTcscommConnection() functions. */ conn->teac_id = -1; conn->teac_rank = port; conn->tcscomm_id = -1; conn->tcscomm_rank = port; crInitMessageList(&conn->messageList); /* now, just dispatch to the appropriate protocol's initialization functions. */ InitConnection(conn, protocol, mtu #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , pHgsmi #endif ); if (!crNetConnect( conn )) { crDebug("crNetConnectToServer() failed, freeing the connection"); #ifdef CHROMIUM_THREADSAFE crFreeMutex( &conn->messageList.lock ); #endif conn->Disconnect(conn); crFree( conn ); return NULL; } crDebug( "Done connecting to %s (swapping=%d)", server, conn->swap ); return conn; }
void crPackDeleteContext(CRPackContext *pc) { crFreeMutex(&pc->mutex); crFree(pc); }