[PATCH xserver 20/23] os: Use poll(2) for input thread

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


Replace use of select(2) to avoid fd limits

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 os/inputthread.c | 85 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 48 insertions(+), 37 deletions(-)

diff --git a/os/inputthread.c b/os/inputthread.c
index b6bbf35..3d8e6da 100644
--- a/os/inputthread.c
+++ b/os/inputthread.c
@@ -35,7 +35,6 @@
 #include <unistd.h>
 #include <pthread.h>
 
-#include <X11/Xpoll.h>
 #include "inputstr.h"
 #include "opaque.h"
 #include "osdep.h"
@@ -62,7 +61,7 @@ typedef struct _InputThreadDevice {
 typedef struct {
     pthread_t thread;
     struct xorg_list devs;
-    fd_set fds;
+    struct ospoll *fds;
     int readPipe;
     int writePipe;
 } InputThreadInfo;
@@ -126,9 +125,10 @@ InputThreadFillPipe(int writeHead)
 {
     int ret;
     char byte = 0;
-    fd_set writePipe;
+    struct pollfd poll_fd;
 
-    FD_ZERO(&writePipe);
+    poll_fd.fd = writeHead;
+    poll_fd.events = POLLOUT;
 
     while (1) {
         ret = write(writeHead, &byte, 1);
@@ -141,8 +141,7 @@ InputThreadFillPipe(int writeHead)
             FatalError("input-thread: filling pipe");
 
         DebugF("input-thread: pipe full\n");
-        FD_SET(writeHead, &writePipe);
-        Select(writeHead + 1, NULL, &writePipe, NULL, NULL);
+        poll(&poll_fd, 1, -1);
     }
 }
 
@@ -167,6 +166,18 @@ InputThreadReadPipe(int readHead)
     return 1;
 }
 
+static void
+InputReady(int fd, short revents, void *data)
+{
+    InputThreadDevice *dev = data;
+
+    if (revents & POLLIN) {
+        input_lock();
+        dev->readInputProc(fd, X_NOTIFY_READ, dev->readInputArgs);
+        input_unlock();
+    }
+}
+
 /**
  * Register an input device in the threaded input facility
  *
@@ -198,7 +209,11 @@ InputThreadRegisterDev(int fd,
 
     xorg_list_add(&dev->node, &inputThreadInfo->devs);
 
-    FD_SET(fd, &inputThreadInfo->fds);
+    ospoll_add(inputThreadInfo->fds, fd,
+               ospoll_trigger_level,
+               InputReady,
+               dev);
+    ospoll_listen(inputThreadInfo->fds, fd, POLLIN);
 
     InputThreadFillPipe(hotplugPipeWrite);
     DebugF("input-thread: registered device %d\n", fd);
@@ -239,7 +254,7 @@ InputThreadUnregisterDev(int fd)
 
     xorg_list_del(&dev->node);
 
-    FD_CLR(fd, &inputThreadInfo->fds);
+    ospoll_remove(inputThreadInfo->fds, fd);
     free(dev);
 
     InputThreadFillPipe(hotplugPipeWrite);
@@ -248,6 +263,16 @@ InputThreadUnregisterDev(int fd)
     return 1;
 }
 
+static void
+InputThreadPipeNotify(int fd, short revents, void *data)
+{
+    /* Empty pending input, shut down if the pipe has been closed */
+    if (InputThreadReadPipe(hotplugPipeRead) == 0) {
+        Bool        *running = data;
+        *running = FALSE;
+    }
+}
+
 /**
  * The workhorse of threaded input event generation.
  *
@@ -265,51 +290,36 @@ InputThreadUnregisterDev(int fd)
 static void*
 InputThreadDoWork(void *arg)
 {
-    fd_set readyFds;
-    InputThreadDevice *dev, *next;
+    Bool        running = TRUE;
     sigset_t set;
 
     /* Don't handle any signals on this thread */
     sigfillset(&set);
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 
-    FD_ZERO(&readyFds);
+    ospoll_add(inputThreadInfo->fds, hotplugPipeRead,
+               ospoll_trigger_level,
+               InputThreadPipeNotify,
+               &running);
 
-    while (1)
+    while (running)
     {
-        XFD_COPYSET(&inputThreadInfo->fds, &readyFds);
-        FD_SET(hotplugPipeRead, &readyFds);
-
         DebugF("input-thread: %s waiting for devices\n", __func__);
 
-        if (Select(MAXSELECT, &readyFds, NULL, NULL, NULL) < 0) {
+        if (ospoll_wait(inputThreadInfo->fds, -1) < 0) {
             if (errno == EINVAL)
                 FatalError("input-thread: %s (%s)", __func__, strerror(errno));
             else if (errno != EINTR)
                 ErrorF("input-thread: %s (%s)\n", __func__, strerror(errno));
         }
 
-        DebugF("input-thread: %s generating events\n", __func__);
-
-        /* Call the device drivers to generate input events for us */
-        xorg_list_for_each_entry_safe(dev, next, &inputThreadInfo->devs, node) {
-            if (FD_ISSET(dev->fd, &readyFds) && dev->readInputProc) {
-                input_lock();
-                dev->readInputProc(dev->fd, X_NOTIFY_READ, dev->readInputArgs);
-                input_unlock();
-            }
-        }
-
         /* Kick main thread to process the generated input events and drain
          * events from hotplug pipe */
         InputThreadFillPipe(inputThreadInfo->writePipe);
-
-        /* Empty pending input, shut down if the pipe has been closed */
-        if (FD_ISSET(hotplugPipeRead, &readyFds)) {
-            if (InputThreadReadPipe(hotplugPipeRead) == 0)
-                break;
-        }
     }
+
+    ospoll_remove(inputThreadInfo->fds, hotplugPipeRead);
+
     return NULL;
 }
 
@@ -343,7 +353,7 @@ InputThreadPreInit(void)
 
     inputThreadInfo->thread = 0;
     xorg_list_init(&inputThreadInfo->devs);
-    FD_ZERO(&inputThreadInfo->fds);
+    inputThreadInfo->fds = ospoll_create();
 
     /* By making read head non-blocking, we ensure that while the main thread
      * is busy servicing client requests, the dedicated input thread can work
@@ -351,7 +361,6 @@ InputThreadPreInit(void)
      */
     inputThreadInfo->readPipe = fds[0];
     fcntl(inputThreadInfo->readPipe, F_SETFL, O_NONBLOCK | O_CLOEXEC);
-    SetNotifyFd(inputThreadInfo->readPipe, InputThreadNotifyPipe, X_NOTIFY_READ, NULL);
 
     inputThreadInfo->writePipe = fds[1];
 
@@ -387,6 +396,8 @@ InputThreadInit(void)
     if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0)
         ErrorF("input-thread: error setting thread scope\n");
 
+    SetNotifyFd(inputThreadInfo->readPipe, InputThreadNotifyPipe, X_NOTIFY_READ, NULL);
+
     DebugF("input-thread: creating thread\n");
     pthread_create(&inputThreadInfo->thread, &attr,
                    &InputThreadDoWork, NULL);
@@ -412,11 +423,11 @@ InputThreadFini(void)
     pthread_join(inputThreadInfo->thread, NULL);
 
     xorg_list_for_each_entry_safe(dev, next, &inputThreadInfo->devs, node) {
-        FD_CLR(dev->fd, &inputThreadInfo->fds);
+        ospoll_remove(inputThreadInfo->fds, dev->fd);
         free(dev);
     }
     xorg_list_init(&inputThreadInfo->devs);
-    FD_ZERO(&inputThreadInfo->fds);
+    ospoll_destroy(inputThreadInfo->fds);
 
     RemoveNotifyFd(inputThreadInfo->readPipe);
     close(inputThreadInfo->readPipe);
-- 
2.8.0.rc3



More information about the xorg-devel mailing list