[PATCH xserver 15/25] Modify ready_client list directly from WaitForSomething

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


This changes the WaitForSomething API so that it only notifies DIX
when a client becomes ready to read. This avoids walking over all
existing ready clients to compute the total set each time.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 dix/dispatch.c  | 45 +++++++++++++++++++++++++++++++++------------
 include/os.h    |  3 +--
 os/WaitFor.c    | 36 +++++++++++++++++-------------------
 os/connection.c |  5 ++++-
 4 files changed, 55 insertions(+), 34 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 76e392b..e3dc9b2 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -241,11 +241,13 @@ long SmartLastPrint;
 void Dispatch(void);
 
 static struct xorg_list ready_clients;
+static struct xorg_list saved_ready_clients;
 
 static void
 init_client_ready(void)
 {
     xorg_list_init(&ready_clients);
+    xorg_list_init(&saved_ready_clients);
 }
 
 static Bool
@@ -269,6 +271,30 @@ mark_client_not_ready(ClientPtr client)
     xorg_list_del(&client->ready);
 }
 
+static void
+mark_client_grab(ClientPtr grab)
+{
+    ClientPtr   client, tmp;
+
+    xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
+        if (client != grab) {
+            xorg_list_del(&client->ready);
+            xorg_list_append(&client->ready, &saved_ready_clients);
+        }
+    }
+}
+
+static void
+mark_client_ungrab(void)
+{
+    ClientPtr   client, tmp;
+
+    xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
+        xorg_list_del(&client->ready);
+        xorg_list_append(&client->ready, &ready_clients);
+    }
+}
+
 static ClientPtr
 SmartScheduleClient(void)
 {
@@ -365,32 +391,25 @@ DisableLimitedSchedulingLatency(void)
 void
 Dispatch(void)
 {
-    int *clientReady;           /* array of request ready clients */
     int result;
     ClientPtr client;
-    int nready;
     HWEventQueuePtr *icheck = checkForInput;
     long start_tick;
 
     nextFreeClientID = 1;
     nClients = 0;
 
-    clientReady = xallocarray(MaxClients, sizeof(int));
-    if (!clientReady)
-        return;
-
     SmartScheduleSlice = SmartScheduleInterval;
+    init_client_ready();
+
     while (!dispatchException) {
         if (*icheck[0] != *icheck[1]) {
             ProcessInputEvents();
             FlushIfCriticalOutputPending();
         }
 
-        nready = WaitForSomething(clientReady);
-
-        init_client_ready();
-        for (result = 0; result < nready; result++)
-            mark_client_ready(clients[clientReady[result]]);
+        if (!WaitForSomething(clients_are_ready()))
+            continue;
 
        /*****************
 	*  Handle events in round robin fashion, doing input between
@@ -419,6 +438,7 @@ Dispatch(void)
                 /* now, finally, deal with client requests */
                 result = ReadRequestFromClient(client);
                 if (result <= 0) {
+                    mark_client_not_ready(client);
                     if (result < 0)
                         CloseDownClient(client);
                     break;
@@ -481,7 +501,6 @@ Dispatch(void)
     ddxBeforeReset();
 #endif
     KillAllClients();
-    free(clientReady);
     dispatchException &= ~DE_RESET;
     SmartScheduleLatencyLimited = 0;
     ResetOsBuffers();
@@ -1081,6 +1100,7 @@ ProcGrabServer(ClientPtr client)
         return rc;
     grabState = GrabActive;
     grabClient = client;
+    mark_client_grab(client);
 
     if (ServerGrabCallback) {
         ServerGrabInfoRec grabinfo;
@@ -1100,6 +1120,7 @@ UngrabServer(ClientPtr client)
 
     grabState = GrabNone;
     ListenToAllClients();
+    mark_client_ungrab();
     for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
     if (i >= 0) {
         i <<= 5;
diff --git a/include/os.h b/include/os.h
index 1ede9b9..aeb1034 100644
--- a/include/os.h
+++ b/include/os.h
@@ -93,8 +93,7 @@ extern _X_EXPORT void (*OsVendorVErrorFProc) (const char *,
 _X_ATTRIBUTE_PRINTF(1, 0);
 #endif
 
-extern _X_EXPORT int WaitForSomething(int *     /*pClientsReady */
-    );
+extern _X_EXPORT Bool WaitForSomething(Bool clients_are_ready);
 
 extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
 
diff --git a/os/WaitFor.c b/os/WaitFor.c
index 26673e4..e78e358 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -142,8 +142,8 @@ static volatile OsTimerPtr timers = NULL;
  *     pClientsReady is an array to store ready client->index values into.
  *****************/
 
-int
-WaitForSomething(int *pClientsReady)
+Bool
+WaitForSomething(Bool clients_are_ready)
 {
     int i;
     struct timeval waittime, *wt;
@@ -154,7 +154,6 @@ WaitForSomething(int *pClientsReady)
     int selecterr;
     static int nready;
     CARD32 now = 0;
-    Bool someReady = FALSE;
     Bool someNotifyWriteReady = FALSE;
 
     FD_ZERO(&clientsReadable);
@@ -174,13 +173,11 @@ WaitForSomething(int *pClientsReady)
         /* deal with any blocked jobs */
         if (workQueue)
             ProcessWorkQueue();
-        if (XFD_ANYSET(&ClientsWithInput)) {
-            someReady = TRUE;
+
+        if (clients_are_ready) {
             waittime.tv_sec = 0;
             waittime.tv_usec = 0;
             wt = &waittime;
-        }
-        if (someReady) {
             XFD_COPYSET(&AllSockets, &LastSelectMask);
             XFD_UNSET(&LastSelectMask, &ClientsWithInput);
         }
@@ -225,12 +222,12 @@ WaitForSomething(int *pClientsReady)
         WakeupHandler(i);
         if (i <= 0) {           /* An error or timeout occurred */
             if (dispatchException)
-                return 0;
+                return FALSE;
             if (i < 0) {
                 if (selecterr == EBADF) {       /* Some client disconnected */
                     CheckConnections();
                     if (!XFD_ANYSET(&AllClients))
-                        return 0;
+                        return FALSE;
                 }
                 else if (selecterr == EINVAL) {
                     FatalError("WaitForSomething(): select: %s\n",
@@ -241,7 +238,7 @@ WaitForSomething(int *pClientsReady)
                            strerror(selecterr));
                 }
             }
-            else if (someReady) {
+            else if (clients_are_ready) {
                 /*
                  * If no-one else is home, bail quickly
                  */
@@ -250,7 +247,7 @@ WaitForSomething(int *pClientsReady)
                 break;
             }
             if (*checkForInput[0] != *checkForInput[1])
-                return 0;
+                return FALSE;
 
             if (timers) {
                 int expired = 0;
@@ -265,7 +262,7 @@ WaitForSomething(int *pClientsReady)
                         DoTimer(timers, now, &timers);
                     OsReleaseSignals();
 
-                    return 0;
+                    return FALSE;
                 }
             }
         }
@@ -286,12 +283,11 @@ WaitForSomething(int *pClientsReady)
                             DoTimer(timers, now, &timers);
                         OsReleaseSignals();
 
-                        return 0;
+                        return FALSE;
                     }
                 }
             }
-            if (someReady)
-                XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
+
             if (AnyWritesPending) {
                 XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
                 if (XFD_ANYSET(&clientsWritable)) {
@@ -314,11 +310,12 @@ WaitForSomething(int *pClientsReady)
             if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
                 HandleNotifyFds();
 
-            if (XFD_ANYSET(&clientsReadable))
+            if (clients_are_ready || XFD_ANYSET(&clientsReadable))
                 break;
+
             /* check here for DDXes that queue events during Block/Wakeup */
             if (*checkForInput[0] != *checkForInput[1])
-                return 0;
+                return FALSE;
         }
     }
 
@@ -343,7 +340,8 @@ WaitForSomething(int *pClientsReady)
             curclient = XFD_FD(&savedClientsReadable, i);
             client_index = GetConnectionTranslation(curclient);
 #endif
-            pClientsReady[nready++] = client_index;
+            nready++;
+            mark_client_ready(clients[client_index]);
 #ifndef WIN32
             clientsReadable.fds_bits[i] &= ~(((fd_mask) 1L) << curclient);
         }
@@ -356,7 +354,7 @@ WaitForSomething(int *pClientsReady)
     if (nready)
         SmartScheduleStartTimer();
 
-    return nready;
+    return TRUE;
 }
 
 /* If time has rewound, re-run every affected timer.
diff --git a/os/connection.c b/os/connection.c
index b300025..d3fda35 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -1246,6 +1246,7 @@ IgnoreClient(ClientPtr client)
         return;
 
     isItTimeToYield = TRUE;
+    mark_client_not_ready(client);
     if (!GrabInProgress || FD_ISSET(connection, &AllClients)) {
         if (FD_ISSET(connection, &ClientsWithInput))
             FD_SET(connection, &IgnoredClientsWithInput);
@@ -1287,8 +1288,10 @@ AttendClient(ClientPtr client)
         FD_SET(connection, &AllClients);
         FD_SET(connection, &AllSockets);
         FD_SET(connection, &LastSelectMask);
-        if (FD_ISSET(connection, &IgnoredClientsWithInput))
+        if (FD_ISSET(connection, &IgnoredClientsWithInput)) {
             FD_SET(connection, &ClientsWithInput);
+            mark_client_ready(client);
+        }
     }
     else {
         FD_SET(connection, &SavedAllClients);
-- 
2.8.0.rc3



More information about the xorg-devel mailing list