[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