[PATCH xserver 12/25] dix: Use list for ready clients

Keith Packard keithp at keithp.com
Wed May 25 05:38:49 UTC 2016


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 <keithp at 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



More information about the xorg-devel mailing list