[PATCH xserver 19/23] os: Switch server to poll(2)

Keith Packard keithp at keithp.com
Thu May 26 23:59:54 UTC 2016


Eliminates all of the fd_set mangling in the server main thread

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 dix/dispatch.c      |   4 +
 include/dixstruct.h |  25 ++++
 os/WaitFor.c        | 157 +++++++------------------
 os/connection.c     | 333 ++++++++++++++++++++--------------------------------
 os/io.c             | 101 +++-------------
 os/osdep.h          |  29 ++---
 os/osinit.c         |   1 -
 os/xdmcp.c          |   1 -
 8 files changed, 223 insertions(+), 428 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index a61d7a4..51e586f 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -242,12 +242,14 @@ void Dispatch(void);
 
 static struct xorg_list ready_clients;
 static struct xorg_list saved_ready_clients;
+struct xorg_list output_pending_clients;
 
 static void
 init_client_ready(void)
 {
     xorg_list_init(&ready_clients);
     xorg_list_init(&saved_ready_clients);
+    xorg_list_init(&output_pending_clients);
 }
 
 Bool
@@ -3413,6 +3415,7 @@ CloseDownClient(ClientPtr client)
             UngrabServer(client);
         }
         mark_client_not_ready(client);
+        xorg_list_del(&client->output_pending);
         BITCLEAR(grabWaiters, client->index);
         DeleteClientFromAnySelections(client);
         ReleaseActiveGrabs(client);
@@ -3503,6 +3506,7 @@ InitClient(ClientPtr client, int i, void *ospriv)
 {
     client->index = i;
     xorg_list_init(&client->ready);
+    xorg_list_init(&client->output_pending);
     client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
     client->closeDownMode = i ? DestroyAll : RetainPermanent;
     client->requestVector = InitialVector;
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 1f38349..38c649a 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -77,6 +77,7 @@ typedef struct _Client {
     void *requestBuffer;
     void *osPrivate;             /* for OS layer, including scheduler */
     struct xorg_list ready;      /* List of clients ready to run */
+    struct xorg_list output_pending; /* List of clients with output queued */
     Mask clientAsMask;
     short index;
     unsigned char majorOp, minorOp;
@@ -153,6 +154,30 @@ static inline Bool client_is_ready(ClientPtr client)
 Bool
 clients_are_ready(void);
 
+extern struct xorg_list output_pending_clients;
+
+static inline void
+output_pending_mark(ClientPtr client)
+{
+    if (xorg_list_is_empty(&client->output_pending))
+        xorg_list_append(&client->output_pending, &output_pending_clients);
+}
+
+static inline void
+output_pending_clear(ClientPtr client)
+{
+    xorg_list_del(&client->output_pending);
+}
+
+static inline Bool any_output_pending(void) {
+    return !xorg_list_is_empty(&output_pending_clients);
+}
+
+static inline Bool client_output_pending(ClientPtr client)
+{
+    return !xorg_list_is_empty(&client->output_pending);
+}
+
 #define SMART_MAX_PRIORITY  (20)
 #define SMART_MIN_PRIORITY  (-20)
 
diff --git a/os/WaitFor.c b/os/WaitFor.c
index ef4ebb5..9fdc996 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -66,7 +66,6 @@ SOFTWARE.
 #include "misc.h"
 
 #include "osdep.h"
-#include <X11/Xpoll.h>
 #include "dixstruct.h"
 #include "opaque.h"
 #ifdef DPMSExtension
@@ -146,22 +145,20 @@ Bool
 WaitForSomething(Bool are_ready)
 {
     int i;
-    struct timeval waittime, *wt;
     int timeout;
-    fd_set clientsReadable;
-    fd_set clientsWritable;
-    int curclient;
-    int selecterr;
-    static int nready;
+    int pollerr;
+    static Bool were_ready;
+    Bool timer_is_running;
     CARD32 now = 0;
-    Bool someNotifyWriteReady = FALSE;
 
-    FD_ZERO(&clientsReadable);
-    FD_ZERO(&clientsWritable);
+    timer_is_running = were_ready;
 
-    if (nready)
+    if (were_ready && !are_ready) {
+        timer_is_running = FALSE;
         SmartScheduleStopTimer();
-    nready = 0;
+    }
+
+    were_ready = FALSE;
 
 #ifdef BUSFAULT
     busfault_check();
@@ -176,8 +173,6 @@ WaitForSomething(Bool are_ready)
 
         if (are_ready) {
             timeout = 0;
-            XFD_COPYSET(&AllSockets, &LastSelectMask);
-            XFD_UNSET(&LastSelectMask, &ClientsWithInput);
         }
         else {
             timeout = -1;
@@ -195,57 +190,39 @@ WaitForSomething(Bool are_ready)
                         timeout = 0;
                 }
             }
-            XFD_COPYSET(&AllSockets, &LastSelectMask);
         }
 
         BlockHandler(&timeout);
-        if (timeout < 0)
-            wt = NULL;
-        else {
-            waittime.tv_sec = timeout / MILLI_PER_SECOND;
-            waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
-                (1000000 / MILLI_PER_SECOND);
-            wt = &waittime;
-        }
         if (NewOutputPending)
             FlushAllOutput();
         /* keep this check close to select() call to minimize race */
         if (dispatchException)
             i = -1;
-        else if (AnyWritesPending) {
-            XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask);
-            XFD_ORSET(&LastSelectWriteMask, &NotifyWriteFds, &LastSelectWriteMask);
-            i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt);
-        }
-        else {
-            i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
-        }
-        selecterr = GetErrno();
+        else
+            i = ospoll_wait(server_poll, timeout);
+        pollerr = GetErrno();
         WakeupHandler(i);
         if (i <= 0) {           /* An error or timeout occurred */
             if (dispatchException)
                 return FALSE;
             if (i < 0) {
-                if (selecterr == EBADF) {       /* Some client disconnected */
+                if (pollerr == EBADF) {       /* Some client disconnected */
                     CheckConnections();
-                    if (!XFD_ANYSET(&AllClients))
-                        return FALSE;
+                    return FALSE;
                 }
-                else if (selecterr == EINVAL) {
-                    FatalError("WaitForSomething(): select: %s\n",
-                               strerror(selecterr));
+                else if (pollerr == EINVAL) {
+                    FatalError("WaitForSomething(): poll: %s\n",
+                               strerror(pollerr));
                 }
-                else if (selecterr != EINTR && selecterr != EAGAIN) {
-                    ErrorF("WaitForSomething(): select: %s\n",
-                           strerror(selecterr));
+                else if (pollerr != EINTR && pollerr != EAGAIN) {
+                    ErrorF("WaitForSomething(): poll: %s\n",
+                           strerror(pollerr));
                 }
             }
             else if (are_ready) {
                 /*
                  * If no-one else is home, bail quickly
                  */
-                XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
-                XFD_COPYSET(&ClientsWithInput, &clientsReadable);
                 break;
             }
             if (*checkForInput[0] != *checkForInput[1])
@@ -269,93 +246,39 @@ WaitForSomething(Bool are_ready)
             }
         }
         else {
-            fd_set tmp_set;
-
-            if (*checkForInput[0] == *checkForInput[1]) {
-                if (timers) {
-                    int expired = 0;
+            /* check here for DDXes that queue events during Block/Wakeup */
+            if (*checkForInput[0] != *checkForInput[1])
+                return FALSE;
 
-                    now = GetTimeInMillis();
-                    if ((int) (timers->expires - now) <= 0)
-                        expired = 1;
+            if (timers) {
+                int expired = 0;
 
-                    if (expired) {
-                        OsBlockSignals();
-                        while (timers && (int) (timers->expires - now) <= 0)
-                            DoTimer(timers, now, &timers);
-                        OsReleaseSignals();
+                now = GetTimeInMillis();
+                if ((int) (timers->expires - now) <= 0)
+                    expired = 1;
 
-                        return FALSE;
-                    }
-                }
-            }
+                if (expired) {
+                    OsBlockSignals();
+                    while (timers && (int) (timers->expires - now) <= 0)
+                        DoTimer(timers, now, &timers);
+                    OsReleaseSignals();
 
-            if (AnyWritesPending) {
-                XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
-                if (XFD_ANYSET(&clientsWritable)) {
-                    NewOutputPending = TRUE;
-                    XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
-                    XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
-                    if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
-                        AnyWritesPending = FALSE;
-                }
-                if (NumNotifyWriteFd != 0) {
-                    XFD_ANDSET(&tmp_set, &LastSelectWriteMask, &NotifyWriteFds);
-                    if (XFD_ANYSET(&tmp_set))
-                        someNotifyWriteReady = TRUE;
+                    return FALSE;
                 }
             }
 
-            XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
-
-            XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds);
-            if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
-                HandleNotifyFds();
-
-            if (are_ready || XFD_ANYSET(&clientsReadable))
+            are_ready = clients_are_ready();
+            if (are_ready)
                 break;
-
-            /* check here for DDXes that queue events during Block/Wakeup */
-            if (*checkForInput[0] != *checkForInput[1])
-                return FALSE;
         }
     }
 
-    nready = 0;
-    if (XFD_ANYSET(&clientsReadable)) {
-#ifndef WIN32
-        for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
-            while (clientsReadable.fds_bits[i]) {
-                int client_index;
-
-                curclient = mffs(clientsReadable.fds_bits[i]) - 1;
-                client_index =  /* raphael: modified */
-                    ConnectionTranslation[curclient +
-                                          (i * (sizeof(fd_mask) * 8))];
-#else
-        fd_set savedClientsReadable;
-
-        XFD_COPYSET(&clientsReadable, &savedClientsReadable);
-        for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++) {
-            int client_priority, client_index;
-
-            curclient = XFD_FD(&savedClientsReadable, i);
-            client_index = GetConnectionTranslation(curclient);
-#endif
-            nready++;
-            mark_client_ready(clients[client_index]);
-#ifndef WIN32
-            clientsReadable.fds_bits[i] &= ~(((fd_mask) 1L) << curclient);
-        }
-#else
-            FD_CLR(curclient, &clientsReadable);
-#endif
-        }
+    if (are_ready) {
+        were_ready = TRUE;
+        if (!timer_is_running)
+            SmartScheduleStartTimer();
     }
 
-    if (nready)
-        SmartScheduleStartTimer();
-
     return TRUE;
 }
 
diff --git a/os/connection.c b/os/connection.c
index d4e367a..1ae50b1 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -120,20 +120,10 @@ SOFTWARE.
 #include "probes.h"
 
 static int lastfdesc;           /* maximum file descriptor */
+struct ospoll   *server_poll;
 
-fd_set NotifyReadFds;           /* mask for other file descriptors */
-fd_set NotifyWriteFds;          /* mask for other write file descriptors */
-fd_set AllSockets;              /* select on this */
-fd_set AllClients;              /* available clients */
-fd_set LastSelectMask;          /* mask returned from last select call */
-fd_set LastSelectWriteMask;     /* mask returned from last select call */
-fd_set ClientsWithInput;        /* clients with FULL requests in buffer */
-fd_set ClientsWriteBlocked;     /* clients who cannot receive output */
-fd_set OutputPending;           /* clients with reply/event data ready to go */
 int MaxClients = 0;
-int NumNotifyWriteFd;           /* Number of NotifyFd members with write set */
 Bool NewOutputPending;          /* not yet attempted to write some new output */
-Bool AnyWritesPending;          /* true if some client blocked on write or NotifyFd with write */
 Bool NoListenAll;               /* Don't establish any listening sockets */
 
 static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
@@ -145,16 +135,17 @@ static Pid_t ParentProcess;
 
 static Bool debug_conns = FALSE;
 
-fd_set IgnoredClientsWithInput;
-static fd_set GrabImperviousClients;
-static fd_set SavedAllClients;
-static fd_set SavedAllSockets;
-static fd_set SavedClientsWithInput;
 int GrabInProgress = 0;
 
 static void
 QueueNewConnections(int curconn, int ready, void *data);
 
+static void
+set_poll_client(ClientPtr client);
+
+static void
+set_poll_clients(void);
+
 #if !defined(WIN32)
 int *ConnectionTranslation = NULL;
 #else
@@ -392,10 +383,9 @@ CreateWellKnownSockets(void)
     int i;
     int partial;
 
-    FD_ZERO(&AllSockets);
-    FD_ZERO(&AllClients);
-    FD_ZERO(&LastSelectMask);
-    FD_ZERO(&ClientsWithInput);
+    server_poll = ospoll_create();
+    if (!server_poll)
+        FatalError("failed to allocate poll structure");
 
 #if !defined(WIN32)
     for (i = 0; i < MaxClients; i++)
@@ -751,6 +741,21 @@ ClientAuthorized(ClientPtr client,
     return ((char *) NULL);
 }
 
+static void
+ClientReady(int fd, short revents, void *data)
+{
+    ClientPtr client = data;
+
+    if (revents & ~(POLLIN|POLLOUT)) {
+        CloseDownClient(client);
+        return;
+    }
+    if (revents & POLLIN)
+        mark_client_ready(client);
+    if (revents & POLLOUT)
+        NewOutputPending = TRUE;
+}
+
 static ClientPtr
 AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time)
 {
@@ -774,6 +779,7 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time)
     oc->output = (ConnectionOutputPtr) NULL;
     oc->auth_id = None;
     oc->conn_time = conn_time;
+    oc->flags = 0;
     if (!(client = NextAvailableClient((void *) oc))) {
         free(oc);
         return NullClient;
@@ -784,14 +790,11 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time)
 #else
     SetConnectionTranslation(fd, client->index);
 #endif
-    if (GrabInProgress) {
-        FD_SET(fd, &SavedAllClients);
-        FD_SET(fd, &SavedAllSockets);
-    }
-    else {
-        FD_SET(fd, &AllClients);
-        FD_SET(fd, &AllSockets);
-    }
+    ospoll_add(server_poll, fd,
+               ospoll_trigger_edge,
+               ClientReady,
+               client);
+    set_poll_client(client);
 
 #ifdef DEBUG
     ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
@@ -940,19 +943,7 @@ CloseDownFileDescriptor(OsCommPtr oc)
 #else
     SetConnectionTranslation(connection, 0);
 #endif
-    FD_CLR(connection, &AllSockets);
-    FD_CLR(connection, &AllClients);
-    FD_CLR(connection, &ClientsWithInput);
-    FD_CLR(connection, &GrabImperviousClients);
-    if (GrabInProgress) {
-        FD_CLR(connection, &SavedAllSockets);
-        FD_CLR(connection, &SavedAllClients);
-        FD_CLR(connection, &SavedClientsWithInput);
-    }
-    FD_CLR(connection, &ClientsWriteBlocked);
-    if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
-        AnyWritesPending = FALSE;
-    FD_CLR(connection, &OutputPending);
+    ospoll_remove(server_poll, connection);
 }
 
 /*****************
@@ -967,53 +958,25 @@ CloseDownFileDescriptor(OsCommPtr oc)
 void
 CheckConnections(void)
 {
-#ifndef WIN32
-    fd_mask mask;
-#endif
-    fd_set tmask;
-    int curclient, curoff;
     int i;
-    struct timeval notime;
     int r;
 
-#ifdef WIN32
-    fd_set savedAllClients;
-#endif
+    for (i = 1; i < currentMaxClients; i++) {
+        ClientPtr client = clients[i];
+        if (!client->clientGone) {
+            OsCommPtr           oc = (OsCommPtr) client->osPrivate;
+            struct pollfd       poll_fd;
 
-    notime.tv_sec = 0;
-    notime.tv_usec = 0;
+            poll_fd.fd = oc->fd;
+            poll_fd.events = POLLIN|POLLOUT;
 
-#ifndef WIN32
-    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
-        mask = AllClients.fds_bits[i];
-        while (mask) {
-            curoff = mffs(mask) - 1;
-            curclient = curoff + (i * (sizeof(fd_mask) * 8));
-            FD_ZERO(&tmask);
-            FD_SET(curclient, &tmask);
             do {
-                r = Select(curclient + 1, &tmask, NULL, NULL, &notime);
+                r = poll(&poll_fd, 1, 0);
             } while (r < 0 && (errno == EINTR || errno == EAGAIN));
             if (r < 0)
-                if (ConnectionTranslation[curclient] > 0)
-                    CloseDownClient(clients[ConnectionTranslation[curclient]]);
-            mask &= ~((fd_mask) 1 << curoff);
+                CloseDownClient(client);
         }
     }
-#else
-    XFD_COPYSET(&AllClients, &savedAllClients);
-    for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) {
-        curclient = XFD_FD(&savedAllClients, i);
-        FD_ZERO(&tmask);
-        FD_SET(curclient, &tmask);
-        do {
-            r = Select(curclient + 1, &tmask, NULL, NULL, &notime);
-        } while (r < 0 && (errno == EINTR || errno == EAGAIN));
-        if (r < 0)
-            if (GetConnectionTranslation(curclient) > 0)
-                CloseDownClient(clients[GetConnectionTranslation(curclient)]);
-    }
-#endif
 }
 
 /*****************
@@ -1043,28 +1006,28 @@ CloseDownConnection(ClientPtr client)
 }
 
 struct notify_fd {
-    struct xorg_list list;
-    int fd;
     int mask;
     NotifyFdProcPtr notify;
     void *data;
 };
 
-static struct xorg_list notify_fds;
+/*****************
+ * HandleNotifyFd
+ *    A poll callback to be called when the registered
+ *    file descriptor is ready.
+ *****************/
 
-void
-InitNotifyFds(void)
+static void
+HandleNotifyFd(int fd, short revents, void *data)
 {
-    struct notify_fd *s, *next;
-    static int been_here;
-
-    if (been_here)
-        xorg_list_for_each_entry_safe(s, next, &notify_fds, list)
-            RemoveNotifyFd(s->fd);
-
-    xorg_list_init(&notify_fds);
-    NumNotifyWriteFd = 0;
-    been_here = 1;
+    struct notify_fd *n = data;
+    int ready = 0;
+    if (n->mask & X_NOTIFY_READ && (revents & POLLIN))
+        ready |= X_NOTIFY_READ;
+    if (n->mask & X_NOTIFY_WRITE && (revents & POLLOUT))
+        ready |= X_NOTIFY_WRITE;
+    if (ready != 0)
+        n->notify(fd, ready, n->data);
 }
 
 /*****************
@@ -1079,52 +1042,40 @@ SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
     struct notify_fd *n;
     int changes;
 
-    xorg_list_for_each_entry(n, &notify_fds, list)
-        if (n->fd == fd)
-            break;
-
-    if (&n->list == &notify_fds) {
+    n = ospoll_data(server_poll, fd);
+    if (!n) {
         if (mask == 0)
             return TRUE;
 
         n = calloc(1, sizeof (struct notify_fd));
         if (!n)
             return FALSE;
-        n->fd = fd;
-        xorg_list_add(&n->list, &notify_fds);
+        ospoll_add(server_poll, fd,
+                   ospoll_trigger_level,
+                   HandleNotifyFd,
+                   n);
     }
 
     changes = n->mask ^ mask;
 
     if (changes & X_NOTIFY_READ) {
         if (mask & X_NOTIFY_READ) {
-            FD_SET(fd, &NotifyReadFds);
-            FD_SET(fd, &AllSockets);
-            if (GrabInProgress)
-                FD_SET(fd, &SavedAllSockets);
+            ospoll_listen(server_poll, fd, POLLIN);
         } else {
-            FD_CLR(fd, &AllSockets);
-            if (GrabInProgress)
-                FD_CLR(fd, &SavedAllSockets);
-            FD_CLR(fd, &NotifyReadFds);
+            ospoll_mute(server_poll, fd, POLLIN);
         }
     }
 
     if (changes & X_NOTIFY_WRITE) {
         if (mask & X_NOTIFY_WRITE) {
-            FD_SET(fd, &NotifyWriteFds);
-            if (!NumNotifyWriteFd++)
-                AnyWritesPending = TRUE;
+            ospoll_listen(server_poll, fd, POLLOUT);
         } else {
-            FD_CLR(fd, &NotifyWriteFds);
-            if (!--NumNotifyWriteFd)
-                if (!XFD_ANYSET(&ClientsWriteBlocked))
-                    AnyWritesPending = FALSE;
+            ospoll_mute(server_poll, fd, POLLOUT);
         }
     }
 
     if (mask == 0) {
-        xorg_list_del(&n->list);
+        ospoll_remove(server_poll, fd);
         free(n);
     } else {
         n->mask = mask;
@@ -1136,28 +1087,6 @@ SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
 }
 
 /*****************
- * HandlNotifyFds
- *    A WorkProc to be called when any of the registered
- *    file descriptors are readable.
- *****************/
-
-void
-HandleNotifyFds(void)
-{
-    struct notify_fd *n, *next;
-
-    xorg_list_for_each_entry_safe(n, next, &notify_fds, list) {
-        int ready = 0;
-        if ((n->mask & X_NOTIFY_READ) && FD_ISSET(n->fd, &LastSelectMask))
-            ready |= X_NOTIFY_READ;
-        if ((n->mask & X_NOTIFY_WRITE) & FD_ISSET(n->fd, &LastSelectWriteMask))
-            ready |= X_NOTIFY_WRITE;
-        if (ready != 0)
-            n->notify(n->fd, ready, n->data);
-    }
-}
-
-/*****************
  * OnlyListenToOneClient:
  *    Only accept requests from  one client.  Continue to handle new
  *    connections, but don't take any protocol requests from the new
@@ -1170,30 +1099,17 @@ HandleNotifyFds(void)
 int
 OnlyListenToOneClient(ClientPtr client)
 {
-    OsCommPtr oc = (OsCommPtr) client->osPrivate;
-    int rc, connection = oc->fd;
+    int rc;
 
     rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
     if (rc != Success)
         return rc;
 
     if (!GrabInProgress) {
-        XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
-        XFD_ANDSET(&ClientsWithInput,
-                   &ClientsWithInput, &GrabImperviousClients);
-        if (FD_ISSET(connection, &SavedClientsWithInput)) {
-            FD_CLR(connection, &SavedClientsWithInput);
-            FD_SET(connection, &ClientsWithInput);
-        }
-        XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
-        XFD_COPYSET(&AllSockets, &SavedAllSockets);
-        XFD_COPYSET(&AllClients, &SavedAllClients);
-        XFD_UNSET(&AllSockets, &AllClients);
-        XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
-        FD_SET(connection, &AllClients);
-        XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
         GrabInProgress = client->index;
+        set_poll_clients();
     }
+
     return rc;
 }
 
@@ -1206,10 +1122,8 @@ void
 ListenToAllClients(void)
 {
     if (GrabInProgress) {
-        XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
-        XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
-        XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
         GrabInProgress = 0;
+        set_poll_clients();
     }
 }
 
@@ -1223,7 +1137,6 @@ void
 IgnoreClient(ClientPtr client)
 {
     OsCommPtr oc = (OsCommPtr) client->osPrivate;
-    int connection = oc->fd;
 
     client->ignoreCount++;
     if (client->ignoreCount > 1)
@@ -1231,25 +1144,9 @@ IgnoreClient(ClientPtr client)
 
     isItTimeToYield = TRUE;
     mark_client_not_ready(client);
-    if (!GrabInProgress || FD_ISSET(connection, &AllClients)) {
-        if (FD_ISSET(connection, &ClientsWithInput))
-            FD_SET(connection, &IgnoredClientsWithInput);
-        else
-            FD_CLR(connection, &IgnoredClientsWithInput);
-        FD_CLR(connection, &ClientsWithInput);
-        FD_CLR(connection, &AllSockets);
-        FD_CLR(connection, &AllClients);
-        FD_CLR(connection, &LastSelectMask);
-    }
-    else {
-        if (FD_ISSET(connection, &SavedClientsWithInput))
-            FD_SET(connection, &IgnoredClientsWithInput);
-        else
-            FD_CLR(connection, &IgnoredClientsWithInput);
-        FD_CLR(connection, &SavedClientsWithInput);
-        FD_CLR(connection, &SavedAllSockets);
-        FD_CLR(connection, &SavedAllClients);
-    }
+
+    oc->flags |= OS_COMM_IGNORED;
+    set_poll_client(client);
 }
 
 /****************
@@ -1261,28 +1158,15 @@ void
 AttendClient(ClientPtr client)
 {
     OsCommPtr oc = (OsCommPtr) client->osPrivate;
-    int connection = oc->fd;
 
     client->ignoreCount--;
     if (client->ignoreCount)
         return;
 
-    if (!GrabInProgress || GrabInProgress == client->index ||
-        FD_ISSET(connection, &GrabImperviousClients)) {
-        FD_SET(connection, &AllClients);
-        FD_SET(connection, &AllSockets);
-        FD_SET(connection, &LastSelectMask);
-        if (FD_ISSET(connection, &IgnoredClientsWithInput)) {
-            FD_SET(connection, &ClientsWithInput);
-            mark_client_ready(client);
-        }
-    }
-    else {
-        FD_SET(connection, &SavedAllClients);
-        FD_SET(connection, &SavedAllSockets);
-        if (FD_ISSET(connection, &IgnoredClientsWithInput))
-            FD_SET(connection, &SavedClientsWithInput);
-    }
+    oc->flags &= ~OS_COMM_IGNORED;
+    set_poll_client(client);
+    if (listen_to_client(client))
+        mark_client_ready(client);
 }
 
 /* make client impervious to grabs; assume only executing client calls this */
@@ -1291,9 +1175,9 @@ void
 MakeClientGrabImpervious(ClientPtr client)
 {
     OsCommPtr oc = (OsCommPtr) client->osPrivate;
-    int connection = oc->fd;
 
-    FD_SET(connection, &GrabImperviousClients);
+    oc->flags |= OS_COMM_GRAB_IMPERVIOUS;
+    set_poll_client(client);
 
     if (ServerGrabCallback) {
         ServerGrabInfoRec grabinfo;
@@ -1310,18 +1194,10 @@ void
 MakeClientGrabPervious(ClientPtr client)
 {
     OsCommPtr oc = (OsCommPtr) client->osPrivate;
-    int connection = oc->fd;
 
-    FD_CLR(connection, &GrabImperviousClients);
-    if (GrabInProgress && (GrabInProgress != client->index)) {
-        if (FD_ISSET(connection, &ClientsWithInput)) {
-            FD_SET(connection, &SavedClientsWithInput);
-            FD_CLR(connection, &ClientsWithInput);
-        }
-        FD_CLR(connection, &AllSockets);
-        FD_CLR(connection, &AllClients);
-        isItTimeToYield = TRUE;
-    }
+    oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS;
+    set_poll_client(client);
+    isItTimeToYield = TRUE;
 
     if (ServerGrabCallback) {
         ServerGrabInfoRec grabinfo;
@@ -1404,3 +1280,46 @@ AddClientOnOpenFD(int fd)
 
     return TRUE;
 }
+
+Bool
+listen_to_client(ClientPtr client)
+{
+    OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+    if (oc->flags & OS_COMM_IGNORED)
+        return FALSE;
+
+    if (!GrabInProgress)
+        return TRUE;
+
+    if (client->index == GrabInProgress)
+        return TRUE;
+
+    if (oc->flags & OS_COMM_GRAB_IMPERVIOUS)
+        return TRUE;
+
+    return FALSE;
+}
+
+static void
+set_poll_client(ClientPtr client)
+{
+    OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+    if (listen_to_client(client))
+        ospoll_listen(server_poll, oc->fd, POLLIN);
+    else
+        ospoll_mute(server_poll, oc->fd, POLLIN);
+}
+
+static void
+set_poll_clients(void)
+{
+    int i;
+
+    for (i = 1; i < currentMaxClients; i++) {
+        ClientPtr client = clients[i];
+        if (client && !client->clientGone)
+            set_poll_client(client);
+    }
+}
diff --git a/os/io.c b/os/io.c
index d04ebd8..75fe6e3 100644
--- a/os/io.c
+++ b/os/io.c
@@ -74,7 +74,6 @@ SOFTWARE.
 #include <X11/Xproto.h>
 #include "os.h"
 #include "osdep.h"
-#include <X11/Xpoll.h>
 #include "opaque.h"
 #include "dixstruct.h"
 #include "misc.h"
@@ -202,7 +201,7 @@ static void
 YieldControlNoInput(int fd)
 {
     YieldControl();
-    FD_CLR(fd, &ClientsWithInput);
+    ospoll_reset_events(server_poll, fd);
 }
 
 static void
@@ -452,24 +451,8 @@ ReadRequestFromClient(ClientPtr client)
      */
 
     gotnow -= needed;
-    if (gotnow >= sizeof(xReq)) {
-        request = (xReq *) (oci->bufptr + needed);
-        if (gotnow >= (result = (get_req_len(request, client) << 2))
-            && (result ||
-                (client->big_requests &&
-                 (gotnow >= sizeof(xBigReq) &&
-                  gotnow >= (get_big_req_len(request, client) << 2))))
-            )
-            FD_SET(fd, &ClientsWithInput);
-        else {
-            FD_CLR(fd, &ClientsWithInput);
-        }
-    }
-    else {
-        if (!gotnow)
-            AvailableInput = oc;
-        FD_CLR(fd, &ClientsWithInput);
-    }
+    if (!gotnow)
+        AvailableInput = oc;
     if (move_header) {
         request = (xReq *) oci->bufptr;
         oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
@@ -562,7 +545,7 @@ InsertFakeRequest(ClientPtr client, char *data, int count)
     gotnow += count;
     if ((gotnow >= sizeof(xReq)) &&
         (gotnow >= (int) (get_req_len((xReq *) oci->bufptr, client) << 2)))
-        FD_SET(fd, &ClientsWithInput);
+        mark_client_ready(client);
     else
         YieldControlNoInput(fd);
     return TRUE;
@@ -602,12 +585,8 @@ ResetCurrentRequest(ClientPtr client)
             }
         }
         if (gotnow >= (needed << 2)) {
-            if (FD_ISSET(fd, &AllClients)) {
-                FD_SET(fd, &ClientsWithInput);
-            }
-            else {
-                FD_SET(fd, &IgnoredClientsWithInput);
-            }
+            if (listen_to_client(client))
+                mark_client_ready(client);
             YieldControl();
         }
         else
@@ -628,16 +607,10 @@ ResetCurrentRequest(ClientPtr client)
 void
 FlushAllOutput(void)
 {
-    register int index, base;
-    register fd_mask mask;      /* raphael */
     OsCommPtr oc;
-    register ClientPtr client;
+    register ClientPtr client, tmp;
     Bool newoutput = NewOutputPending;
 
-#if defined(WIN32)
-    fd_set newOutputPending;
-#endif
-
     if (FlushCallback)
         CallCallbacks(&FlushCallback, NULL);
 
@@ -652,48 +625,14 @@ FlushAllOutput(void)
     CriticalOutputPending = FALSE;
     NewOutputPending = FALSE;
 
-#ifndef WIN32
-    for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) {
-        mask = OutputPending.fds_bits[base];
-        OutputPending.fds_bits[base] = 0;
-        while (mask) {
-            index = ffs(mask) - 1;
-            mask &= ~lowbit(mask);
-            if ((index =
-                 ConnectionTranslation[(base * (sizeof(fd_mask) * 8)) +
-                                       index]) == 0)
-                continue;
-            client = clients[index];
-            if (client->clientGone)
-                continue;
-            oc = (OsCommPtr) client->osPrivate;
-            if (FD_ISSET(oc->fd, &ClientsWithInput)) {
-                FD_SET(oc->fd, &OutputPending); /* set the bit again */
-                NewOutputPending = TRUE;
-            }
-            else
-                (void) FlushClient(client, oc, (char *) NULL, 0);
-        }
-    }
-#else                           /* WIN32 */
-    FD_ZERO(&newOutputPending);
-    for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) {
-        index = XFD_FD(&OutputPending, base);
-        if ((index = GetConnectionTranslation(index)) == 0)
-            continue;
-        client = clients[index];
+    xorg_list_for_each_entry_safe(client, tmp, &output_pending_clients, output_pending) {
         if (client->clientGone)
             continue;
-        oc = (OsCommPtr) client->osPrivate;
-        if (FD_ISSET(oc->fd, &ClientsWithInput)) {
-            FD_SET(oc->fd, &newOutputPending);  /* set the bit again */
-            NewOutputPending = TRUE;
-        }
-        else
+        if (!client_is_ready(client)) {
+            oc = (OsCommPtr) client->osPrivate;
             (void) FlushClient(client, oc, (char *) NULL, 0);
+        }
     }
-    XFD_COPYSET(&newOutputPending, &OutputPending);
-#endif                          /* WIN32 */
 }
 
 void
@@ -835,8 +774,8 @@ WriteToClient(ClientPtr who, int count, const void *__buf)
     }
 #endif
     if (oco->count == 0 || oco->count + count + padBytes > oco->size) {
-        FD_CLR(oc->fd, &OutputPending);
-        if (!XFD_ANYSET(&OutputPending)) {
+        output_pending_clear(who);
+        if (!any_output_pending()) {
             CriticalOutputPending = FALSE;
             NewOutputPending = FALSE;
         }
@@ -848,7 +787,7 @@ WriteToClient(ClientPtr who, int count, const void *__buf)
     }
 
     NewOutputPending = TRUE;
-    FD_SET(oc->fd, &OutputPending);
+    output_pending_mark(who);
     memmove((char *) oco->buf + oco->count, buf, count);
     oco->count += count;
     if (padBytes) {
@@ -872,7 +811,6 @@ int
 FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
 {
     ConnectionOutputPtr oco = oc->output;
-    int connection = oc->fd;
     XtransConnInfo trans_conn = oc->trans_conn;
     struct iovec iov[3];
     static char padBuffer[3];
@@ -945,8 +883,7 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
             /* If we've arrived here, then the client is stuffed to the gills
                and not ready to accept more.  Make a note of it and buffer
                the rest. */
-            FD_SET(connection, &ClientsWriteBlocked);
-            AnyWritesPending = TRUE;
+            output_pending_mark(who);
 
             if (written < oco->count) {
                 if (written > 0) {
@@ -1008,12 +945,8 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
 
     /* everything was flushed out */
     oco->count = 0;
-    /* check to see if this client was write blocked */
-    if (AnyWritesPending) {
-        FD_CLR(oc->fd, &ClientsWriteBlocked);
-        if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
-            AnyWritesPending = FALSE;
-    }
+    output_pending_clear(who);
+
     if (oco->size > BUFWATERMARK) {
         free(oco->buf);
         free(oco);
diff --git a/os/osdep.h b/os/osdep.h
index 3dc2daf..d44df76 100644
--- a/os/osdep.h
+++ b/os/osdep.h
@@ -63,6 +63,8 @@ SOFTWARE.
 #undef _POSIX_SOURCE
 #endif
 
+#include <poll.h>
+
 #ifndef OPEN_MAX
 #ifdef SVR4
 #define OPEN_MAX 512
@@ -148,8 +150,12 @@ typedef struct _osComm {
     XID auth_id;                /* authorization id */
     CARD32 conn_time;           /* timestamp if not established, else 0  */
     struct _XtransConnInfo *trans_conn; /* transport connection object */
+    int flags;
 } OsCommRec, *OsCommPtr;
 
+#define OS_COMM_GRAB_IMPERVIOUS 1
+#define OS_COMM_IGNORED         2
+
 extern int FlushClient(ClientPtr /*who */ ,
                        OsCommPtr /*oc */ ,
                        const void * /*extraBuf */ ,
@@ -159,24 +165,13 @@ extern int FlushClient(ClientPtr /*who */ ,
 extern void FreeOsBuffers(OsCommPtr     /*oc */
     );
 
-extern void InitNotifyFds(void);
-
-extern void HandleNotifyFds(void);
-
 #include "dix.h"
+#include "ospoll.h"
+
+extern struct ospoll    *server_poll;
 
-extern fd_set AllSockets;
-extern fd_set AllClients;
-extern fd_set LastSelectMask;
-extern fd_set LastSelectWriteMask;
-extern fd_set WellKnownConnections;
-extern fd_set EnabledDevices;
-extern fd_set NotifyReadFds;
-extern fd_set NotifyWriteFds;
-extern fd_set ClientsWithInput;
-extern fd_set ClientsWriteBlocked;
-extern fd_set OutputPending;
-extern fd_set IgnoredClientsWithInput;
+Bool
+listen_to_client(ClientPtr client);
 
 #if !defined(WIN32) || defined(__CYGWIN__)
 extern int *ConnectionTranslation;
@@ -187,8 +182,6 @@ extern void ClearConnectionTranslation(void);
 #endif
 
 extern Bool NewOutputPending;
-extern Bool AnyWritesPending;
-extern Bool NumNotifyWriteFd;
 
 extern WorkQueuePtr workQueue;
 
diff --git a/os/osinit.c b/os/osinit.c
index 54b39a0..6ec2f11 100644
--- a/os/osinit.c
+++ b/os/osinit.c
@@ -314,7 +314,6 @@ OsInit(void)
         LockServer();
         been_here = TRUE;
     }
-    InitNotifyFds();
     TimerInit();
     OsVendorInit();
     OsResetSignals();
diff --git a/os/xdmcp.c b/os/xdmcp.c
index 2cb8d76..906c959 100644
--- a/os/xdmcp.c
+++ b/os/xdmcp.c
@@ -39,7 +39,6 @@
 #include <X11/X.h>
 #include <X11/Xmd.h>
 #include "misc.h"
-#include <X11/Xpoll.h>
 #include "osdep.h"
 #include "input.h"
 #include "dixstruct.h"
-- 
2.8.0.rc3



More information about the xorg-devel mailing list