static void crServerCleanupByPID(uint64_t pid) { CRClientNode *pNode=cr_server.pCleanupClient, *pNext; while (pNode) { if (pNode->pClient->pid==pid) { crServerCleanupClient(pNode->pClient); crFree(pNode->pClient); if (pNode->prev) { pNode->prev->next=pNode->next; } else { cr_server.pCleanupClient=pNode->next; } if (pNode->next) { pNode->next->prev = pNode->prev; } pNext=pNode->next; crFree(pNode); pNode=pNext; } else { pNode=pNode->next; } } }
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)); } } }