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;
    }
}
示例#3
0
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));
        }
    }
}