Пример #1
0
void crVBoxServerRemoveClient(uint32_t u32ClientID)
{
    CRClient *pClient=NULL;
    int32_t i;

    crDebug("crServer: RemoveClient u32ClientID=%d", u32ClientID);

    for (i = 0; i < cr_server.numClients; i++)
    {
        if (cr_server.clients[i] && cr_server.clients[i]->conn
            && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
        {
            pClient = cr_server.clients[i];
            break;
        }
    }
    //if (!pClient) return VERR_INVALID_PARAMETER;
    if (!pClient)
    {
        crWarning("Invalid client id %u passed to crVBoxServerRemoveClient", u32ClientID);
        return;
    }

    /* Disconnect the client */
    pClient->conn->Disconnect(pClient->conn);

    /* Let server clear client from the queue */
    crServerDeleteClient(pClient);
}
Пример #2
0
/**
 * Process incoming/pending message for the given client (queue entry).
 * \return CLIENT_GONE if this client has gone away/exited,
 *         CLIENT_NEXT if we can advance to the next client
 *         CLIENT_MORE if we have to process more messages for this client. 
 */
static ClientStatus
crServerServiceClient(const RunQueue *qEntry)
{
    CRMessage *msg;
    CRConnection *conn;

    /* set current client pointer */
    cr_server.curClient = qEntry->client;

    conn = cr_server.run_queue->client->conn;

    /* service current client as long as we can */
    while (conn && conn->type != CR_NO_CONNECTION &&
                 crNetNumMessages(conn) > 0) {
        unsigned int len;

        /*
        crDebug("%d messages on %p",
                        crNetNumMessages(conn), (void *) conn);
        */

        /* Don't use GetMessage, because we want to do our own crNetRecv() calls
         * here ourself.
         * Note that crNetPeekMessage() DOES remove the message from the queue
         * if there is one.
         */
        len = crNetPeekMessage( conn, &msg );
        CRASSERT(len > 0);
        if (msg->header.type != CR_MESSAGE_OPCODES
            && msg->header.type != CR_MESSAGE_REDIR_PTR) {
            crError( "SPU %d sent me CRAP (type=0x%x)",
                             cr_server.curClient->spu_id, msg->header.type );
        }

        /* Do the context switch here.  No sense in switching before we
         * really have any work to process.  This is a no-op if we're
         * not really switching contexts.
         *
         * XXX This isn't entirely sound.  The crStateMakeCurrent() call
         * will compute the state difference and dispatch it using
         * the head SPU's dispatch table.
         *
         * This is a problem if this is the first buffer coming in,
         * and the head SPU hasn't had a chance to do a MakeCurrent()
         * yet (likely because the MakeCurrent() command is in the
         * buffer itself).
         *
         * At best, in this case, the functions are no-ops, and
         * are essentially ignored by the SPU.  In the typical
         * case, things aren't too bad; if the SPU just calls
         * crState*() functions to update local state, everything
         * will work just fine.
         *
         * In the worst (but unusual) case where a nontrivial
         * SPU is at the head of a crserver's SPU chain (say,
         * in a multiple-tiered "tilesort" arrangement, as
         * seen in the "multitilesort.conf" configuration), the
         * SPU may rely on state set during the MakeCurrent() that
         * may not be present yet, because no MakeCurrent() has
         * yet been dispatched.
         *
         * This headache will have to be revisited in the future;
         * for now, SPUs that could head a crserver's SPU chain
         * will have to detect the case that their functions are
         * being called outside of a MakeCurrent(), and will have
         * to handle the situation gracefully.  (This is currently
         * the case with the "tilesort" SPU.)
         */

#if 0
        crStateMakeCurrent( cr_server.curClient->currentCtx );
#else
        /* Check if the current window is the one that the client wants to
         * draw into.  If not, dispatch a MakeCurrent to activate the proper
         * window.
         */
        if (cr_server.curClient) {
             int clientWindow = cr_server.curClient->currentWindow;
             int clientContext = cr_server.curClient->currentContextNumber;
             CRContextInfo *clientCtxInfo = cr_server.curClient->currentCtxInfo;
             if (clientCtxInfo != cr_server.currentCtxInfo
                     || clientWindow != cr_server.currentWindow
                     || cr_server.bForceMakeCurrentOnClientSwitch) {
                 crServerDispatchMakeCurrent(clientWindow, 0, clientContext);
                 /*
                 CRASSERT(cr_server.currentWindow == clientWindow);
                 */
             }
        }
#endif

        /* Force scissor, viewport and projection matrix update in
         * crServerSetOutputBounds().
         */
        cr_server.currentSerialNo = 0;

        /* Commands get dispatched here */
        crServerDispatchMessage( conn, msg );

        crNetFree( conn, msg );

        if (qEntry->blocked) {
            /* Note/assert: we should not be inside a glBegin/End or glNewList/
             * glEndList pair at this time!
             */
            CRASSERT(0);
            return CLIENT_NEXT;
        }

    } /* while */

    /*
     * Check if client/connection is gone
     */
    if (!conn || conn->type == CR_NO_CONNECTION) {
        crDebug("Delete client %p at %d", cr_server.run_queue->client, __LINE__);
        crServerDeleteClient( cr_server.run_queue->client );
        return CLIENT_GONE;
    }

    /*
     * Determine if we can advance to next client.
     * If we're currently inside a glBegin/End primitive or building a display
     * list we can't service another client until we're done with the
     * primitive/list.
     */
    if (crServerClientInBeginEnd(cr_server.curClient)) {
        /* The next message has to come from the current client's connection. */
        CRASSERT(!qEntry->blocked);
        return CLIENT_MORE;
    }
    else {
        /* get next client */
        return CLIENT_NEXT;
    }
}
Пример #3
0
/**
 * Find the next client in the run queue that's not blocked and has a
 * waiting message.
 * Check if all clients are blocked (on barriers, semaphores), if so we've
 * deadlocked!
 * If no clients have a waiting message, call crNetRecv to get something
 * if 'block' is true, else return NULL if 'block' if false.
 */
static RunQueue *
getNextClient(GLboolean block)
{
    while (1)
    {
        if (cr_server.run_queue) 
        {
            GLboolean all_blocked = GL_TRUE;
            GLboolean done_something = GL_FALSE;
            RunQueue *start = cr_server.run_queue;

            /* check if this client's connection has gone away */
            if (!cr_server.run_queue->client->conn
                || (cr_server.run_queue->client->conn->type == CR_NO_CONNECTION
                    && crNetNumMessages(cr_server.run_queue->client->conn) == 0)) 
            {
                crServerDeleteClient( cr_server.run_queue->client );
                start = cr_server.run_queue;
            }
 
            if (cr_server.run_queue == NULL) {
                /* empty queue */
                return NULL;
            }

            if (crServerClientInBeginEnd(cr_server.run_queue->client)) {
                /* We _must_ service this client and no other.
                 * If we've got a message waiting on this client's connection we'll
                 * service it.  Else, return NULL.
                 */
                if (crNetNumMessages(cr_server.run_queue->client->conn) > 0)
                    return cr_server.run_queue;
                else
                    return NULL;
            }

            /* loop over entries in run queue, looking for next one that's ready */
            while (!done_something || cr_server.run_queue != start)
            {
                done_something = GL_TRUE;
                if (!cr_server.run_queue->blocked)
                {
                    all_blocked = GL_FALSE;
                }
                if (!cr_server.run_queue->blocked
                        && cr_server.run_queue->client->conn
                        && crNetNumMessages(cr_server.run_queue->client->conn) > 0)
                {
                    /* OK, this client isn't blocked and has a queued message */
                    return cr_server.run_queue;
                }
                cr_server.run_queue = cr_server.run_queue->next;
            }

            if (all_blocked)
            {
                 /* XXX crError is fatal?  Should this be an info/warning msg? */
                crError( "crserver: DEADLOCK! (numClients=%d, all blocked)",
                                 cr_server.numClients );
                if (cr_server.numClients < (int) cr_server.maxBarrierCount) {
                    crError("Waiting for more clients!!!");
                    while (cr_server.numClients < (int) cr_server.maxBarrierCount) {
                        crNetRecv();
                    }
                }
            }
        }

        if (!block)
             return NULL;

        /* no one had any work, get some! */
        crNetRecv();

    } /* while */

    /* UNREACHED */
    /* return NULL; */
}