This converts the dispatch loop into using a list of ready clients instead of an array. For now, that list is constructed from the array returned by WaitForSomething.
Signed-off-by: Keith Packard <kei...@keithp.com> --- dix/dispatch.c | 86 ++++++++++++++++++++++++++++++++++------------------- include/dixstruct.h | 8 +++++ 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/dix/dispatch.c b/dix/dispatch.c index 89c0a4e..f7ac931 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -241,23 +241,52 @@ long SmartLastPrint; void Dispatch(void); -static int -SmartScheduleClient(int *clientReady, int nready) +static struct xorg_list ready_clients; + +static void +init_client_ready(void) { - ClientPtr pClient; - int i; - int client; - int bestPrio, best = 0; + xorg_list_init(&ready_clients); +} + +static Bool +clients_are_ready(void) +{ + return !xorg_list_is_empty(&ready_clients); +} + +/* Client has requests queued or data on the network */ +void +mark_client_ready(ClientPtr client) +{ + if (xorg_list_is_empty(&client->ready)) + xorg_list_append(&client->ready, &ready_clients); +} + +/* Client has no requests queued and no data on network */ +void +mark_client_not_ready(ClientPtr client) +{ + xorg_list_del(&client->ready); +} + +static ClientPtr +SmartScheduleClient(void) +{ + ClientPtr pClient, best = NULL; + int bestPrio; int bestRobin, robin; long now = SmartScheduleTime; long idle; + int nready = 0; bestPrio = -0x7fffffff; bestRobin = 0; idle = 2 * SmartScheduleSlice; - for (i = 0; i < nready; i++) { - client = clientReady[i]; - pClient = clients[client]; + + xorg_list_for_each_entry(pClient, &ready_clients, ready) { + nready++; + /* Praise clients which haven't run in a while */ if ((now - pClient->smart_stop_tick) >= idle) { if (pClient->smart_priority < 0) @@ -273,27 +302,26 @@ SmartScheduleClient(int *clientReady, int nready) (pClient->smart_priority == bestPrio && robin > bestRobin)) { bestPrio = pClient->smart_priority; bestRobin = robin; - best = client; + best = pClient; } #ifdef SMART_DEBUG if ((now - SmartLastPrint) >= 5000) - fprintf(stderr, " %2d: %3d", client, pClient->smart_priority); + fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority); #endif } #ifdef SMART_DEBUG if ((now - SmartLastPrint) >= 5000) { - fprintf(stderr, " use %2d\n", best); + fprintf(stderr, " use %2d\n", best->index); SmartLastPrint = now; } #endif - pClient = clients[best]; - SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index; + SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = best->index; /* * Set current client pointer */ - if (SmartLastClient != pClient) { - pClient->smart_start_tick = now; - SmartLastClient = pClient; + if (SmartLastClient != best) { + best->smart_start_tick = now; + SmartLastClient = best; } /* * Adjust slice @@ -358,25 +386,22 @@ Dispatch(void) nready = WaitForSomething(clientReady); - if (nready) { - clientReady[0] = SmartScheduleClient(clientReady, nready); - nready = 1; - } + init_client_ready(); + for (result = 0; result < nready; result++) + mark_client_ready(clients[clientReady[result]]); + /***************** * Handle events in round robin fashion, doing input between * each round *****************/ - while (!dispatchException && (--nready >= 0)) { - client = clients[clientReady[nready]]; - if (!client) { - /* KillClient can cause this to happen */ - continue; - } + if (!dispatchException && clients_are_ready()) { + client = SmartScheduleClient(); + /* GrabServer activation can cause this to be true */ if (grabState == GrabKickout) { grabState = GrabActive; - break; + continue; } isItTimeToYield = FALSE; @@ -450,8 +475,7 @@ Dispatch(void) } } FlushAllOutput(); - client = clients[clientReady[nready]]; - if (client) + if (client == SmartLastClient) client->smart_stop_tick = SmartScheduleTime; } dispatchException &= ~DE_PRIORITYCHANGE; @@ -3370,6 +3394,7 @@ CloseDownClient(ClientPtr client) if (grabState != GrabNone && grabClient == client) { UngrabServer(client); } + mark_client_not_ready(client); BITCLEAR(grabWaiters, client->index); DeleteClientFromAnySelections(client); ReleaseActiveGrabs(client); @@ -3459,6 +3484,7 @@ void InitClient(ClientPtr client, int i, void *ospriv) { client->index = i; + xorg_list_init(&client->ready); client->clientAsMask = ((Mask) i) << CLIENTOFFSET; client->closeDownMode = i ? DestroyAll : RetainPermanent; client->requestVector = InitialVector; diff --git a/include/dixstruct.h b/include/dixstruct.h index 8e70ae1..ada45bd 100644 --- a/include/dixstruct.h +++ b/include/dixstruct.h @@ -76,6 +76,7 @@ typedef struct _saveSet { typedef struct _Client { void *requestBuffer; void *osPrivate; /* for OS layer, including scheduler */ + struct xorg_list ready; /* List of clients ready to run */ Mask clientAsMask; short index; unsigned char majorOp, minorOp; @@ -138,6 +139,13 @@ extern Bool SmartScheduleSignalEnable; extern void SmartScheduleStartTimer(void); extern void SmartScheduleStopTimer(void); +/* Client has requests queued or data on the network */ +void mark_client_ready(ClientPtr client); + +/* Client has no requests queued and no data on network */ +void mark_client_not_ready(ClientPtr client); + + #define SMART_MAX_PRIORITY (20) #define SMART_MIN_PRIORITY (-20) -- 2.8.0.rc3 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel