xserver: Branch 'master' - 10 commits

Keith Packard keithp at kemper.freedesktop.org
Thu May 26 23:08:13 UTC 2016


 Xi/exevents.c                             |    4 
 config/config.c                           |    4 
 configure.ac                              |   33 +-
 dix/devices.c                             |   10 
 dix/globals.c                             |    9 
 dix/main.c                                |    9 
 dix/ptrveloc.c                            |    4 
 dix/touch.c                               |   92 +----
 hw/dmx/input/dmxevents.c                  |   24 -
 hw/dmx/input/dmxsigio.c                   |    2 
 hw/kdrive/ephyr/ephyr.c                   |    4 
 hw/kdrive/src/kinput.c                    |   80 -----
 hw/xfree86/common/xf86Config.c            |   21 -
 hw/xfree86/common/xf86Cursor.c            |    8 
 hw/xfree86/common/xf86Events.c            |   32 --
 hw/xfree86/common/xf86Helper.c            |    6 
 hw/xfree86/common/xf86Init.c              |    9 
 hw/xfree86/common/xf86PM.c                |    8 
 hw/xfree86/common/xf86Xinput.c            |    8 
 hw/xfree86/os-support/shared/sigio.c      |   57 +--
 hw/xfree86/os-support/shared/sigiostubs.c |   23 -
 hw/xfree86/os-support/xf86_OSproc.h       |    4 
 include/dix-config.h.in                   |    3 
 include/input.h                           |   17 +
 include/misc.h                            |    1 
 include/os.h                              |   11 
 include/xorg-config.h.in                  |    3 
 mi/mieq.c                                 |  141 ++-------
 mi/mipointer.c                            |    4 
 os/Makefile.am                            |    1 
 os/inputthread.c                          |  470 ++++++++++++++++++++++++++++++
 os/utils.c                                |   64 ----
 test/Makefile.am                          |    2 
 test/os.c                                 |  166 ----------
 xkb/xkbActions.c                          |    5 
 35 files changed, 703 insertions(+), 636 deletions(-)

New commits:
commit e69061e605c66084056cf2064dcc5d4c6c8aa0cf
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 14:26:50 2015 -0800

    kdrive: Use threaded input
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index b415a86..4119b08 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -146,7 +146,7 @@ static void
 KdAddFd(int fd, int i)
 {
     KdNonBlockFd(fd);
-    SetNotifyFd(fd, KdNotifyFd, X_NOTIFY_READ, (void *) (intptr_t) i);
+    InputThreadRegisterDev(fd, KdNotifyFd, (void *) (intptr_t) i);
 }
 
 static void
@@ -154,7 +154,7 @@ KdRemoveFd(int fd)
 {
     int flags;
 
-    RemoveNotifyFd(fd);
+    InputThreadUnregisterDev(fd);
     flags = fcntl(fd, F_GETFL);
     flags &= ~(FASYNC | NOBLOCK);
     fcntl(fd, F_SETFL, flags);
@@ -1306,6 +1306,8 @@ KdInitInput(void)
     KdKeyboardInfo *ki;
     struct KdConfigDevice *dev;
 
+    InputThreadPreInit();
+
     kdInputEnabled = TRUE;
 
     for (dev = kdConfigPointers; dev; dev = dev->next) {
commit a977c9c4d07a04c0c7b3713a21eefb92a8d3005b
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 14:53:08 2015 -0800

    xfree86: Use threaded input mechanism [v2]
    
    Switch the XFree86 DDX over to threaded input
    
    v2: Rewrite comment in xf86Helper about silken mouse
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index df8c7b6..7191980 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -310,7 +310,7 @@ xf86ReadInput(int fd, int ready, void *closure)
 void
 xf86AddEnabledDevice(InputInfoPtr pInfo)
 {
-    SetNotifyFd(pInfo->fd, xf86ReadInput, X_NOTIFY_READ, pInfo);
+    InputThreadRegisterDev(pInfo->fd, xf86ReadInput, pInfo);
 }
 
 /*
@@ -320,7 +320,7 @@ xf86AddEnabledDevice(InputInfoPtr pInfo)
 void
 xf86RemoveEnabledDevice(InputInfoPtr pInfo)
 {
-    RemoveNotifyFd(pInfo->fd);
+    InputThreadUnregisterDev(pInfo->fd);
 }
 
 static int *xf86SignalIntercept = NULL;
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 284858b..bceb017 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1719,15 +1719,9 @@ xf86SetSilkenMouse(ScreenPtr pScreen)
     }
     free(options);
     /*
-     * XXX quick hack to report correctly for OSs that can't do SilkenMouse
-     * yet.  Should handle this differently so that alternate async methods
-     * work correctly with this too.
+     * Use silken mouse if requested and if we have threaded input
      */
-    /* Disable this completely when removing SIGIO support. It
-     * will get re-enabled correctly when we add threaded input
-     * support
-     */
-    pScrn->silkenMouse = useSM && FALSE;
+    pScrn->silkenMouse = useSM && InputThreadEnable;
     if (serverGeneration == 1)
         xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
                    pScrn->silkenMouse ? "enabled" : "disabled");
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index cf726d4..323ac11 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -887,6 +887,9 @@ InitInput(int argc, char **argv)
 
     xf86Info.vtRequestsPending = FALSE;
 
+    /* Enable threaded input */
+    InputThreadPreInit();
+
     mieqInit();
 
     /* Initialize all configured input devices */
commit f84703b50cc908a127f4ad923ebbf56f8f244c0d
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 14:20:21 2015 -0800

    dix: Reallocate touchpoint buffer at input event time [v2]
    
    Now that input is threaded, malloc can be used at event time to resize
    the touchpoint buffer as needed.x
    
    v2: Remove "Need to grow the queue means dropping events."
        from comment as it no longer applies. (Peter Hutterer)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/touch.c b/dix/touch.c
index 4c0412a..37902bd 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -42,9 +42,6 @@
 
 #define TOUCH_HISTORY_SIZE 100
 
-/* If a touch queue resize is needed, the device id's bit is set. */
-static unsigned char resize_waiting[(MAXDEVICES + 7) / 8];
-
 /**
  * Some documentation about touch points:
  * The driver submits touch events with it's own (unique) touch point ID.
@@ -74,47 +71,27 @@ static unsigned char resize_waiting[(MAXDEVICES + 7) / 8];
  * @return Always True. If we fail to grow we probably will topple over soon
  * anyway and re-executing this won't help.
  */
+
 static Bool
-TouchResizeQueue(ClientPtr client, void *closure)
+TouchResizeQueue(DeviceIntPtr dev)
 {
-    int i;
-
-    input_lock();
-
-    /* first two ids are reserved */
-    for (i = 2; i < MAXDEVICES; i++) {
-        DeviceIntPtr dev;
-        DDXTouchPointInfoPtr tmp;
-        size_t size;
-
-        if (!BitIsOn(resize_waiting, i))
-            continue;
+    DDXTouchPointInfoPtr tmp;
+    size_t size;
 
-        ClearBit(resize_waiting, i);
+    /* Grow sufficiently so we don't need to do it often */
+    size = dev->last.num_touches + dev->last.num_touches / 2 + 1;
 
-        /* device may have disappeared by now */
-        dixLookupDevice(&dev, i, serverClient, DixWriteAccess);
-        if (!dev)
-            continue;
-
-        /* Need to grow the queue means dropping events. Grow sufficiently so we
-         * don't need to do it often */
-        size = dev->last.num_touches + dev->last.num_touches / 2 + 1;
-
-        tmp = reallocarray(dev->last.touches, size, sizeof(*dev->last.touches));
-        if (tmp) {
-            int j;
-
-            dev->last.touches = tmp;
-            for (j = dev->last.num_touches; j < size; j++)
-                TouchInitDDXTouchPoint(dev, &dev->last.touches[j]);
-            dev->last.num_touches = size;
-        }
+    tmp = reallocarray(dev->last.touches, size, sizeof(*dev->last.touches));
+    if (tmp) {
+        int j;
 
+        dev->last.touches = tmp;
+        for (j = dev->last.num_touches; j < size; j++)
+            TouchInitDDXTouchPoint(dev, &dev->last.touches[j]);
+        dev->last.num_touches = size;
+        return TRUE;
     }
-    input_unlock();
-
-    return TRUE;
+    return FALSE;
 }
 
 /**
@@ -172,14 +149,20 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
     if (TouchFindByDDXID(dev, ddx_id, FALSE))
         return NULL;
 
-    for (i = 0; i < dev->last.num_touches; i++) {
-        /* Only emulate pointer events on the first touch */
-        if (dev->last.touches[i].active)
-            emulate_pointer = FALSE;
-        else if (!ti)           /* ti is now first non-active touch rec */
-            ti = &dev->last.touches[i];
+    for (;;) {
+        for (i = 0; i < dev->last.num_touches; i++) {
+            /* Only emulate pointer events on the first touch */
+            if (dev->last.touches[i].active)
+                emulate_pointer = FALSE;
+            else if (!ti)           /* ti is now first non-active touch rec */
+                ti = &dev->last.touches[i];
 
-        if (!emulate_pointer && ti)
+            if (!emulate_pointer && ti)
+                break;
+        }
+        if (ti)
+            break;
+        if (!TouchResizeQueue(dev))
             break;
     }
 
@@ -194,21 +177,8 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
             next_client_id = 1;
         ti->client_id = client_id;
         ti->emulate_pointer = emulate_pointer;
-        return ti;
     }
-
-    /* If we get here, then we've run out of touches and we need to drop the
-     * event (we're inside the SIGIO handler here) schedule a WorkProc to
-     * grow the queue for us for next time. */
-    ErrorFSigSafe("%s: not enough space for touch events (max %u touchpoints). "
-                  "Dropping this event.\n", dev->name, dev->last.num_touches);
-
-    if (!BitIsOn(resize_waiting, dev->id)) {
-        SetBit(resize_waiting, dev->id);
-        QueueWorkProc(TouchResizeQueue, serverClient, NULL);
-    }
-
-    return NULL;
+    return ti;
 }
 
 void
commit e2df803fcabd7c2d2fc7991c794856378dcb5489
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 19:53:36 2015 -0800

    mi: Grow event queue while reading events
    
    Now that events are read at normal process time, we can use malloc to
    grow the event queue instead of discarding events.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/mi/mieq.c b/mi/mieq.c
index 8a67213..f2db5a6 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -119,7 +119,7 @@ mieqNumEnqueued(EventQueuePtr eventQueue)
     return n_enqueued;
 }
 
-/* Pre-condition: Called with miEventQueueMutex held */
+/* Pre-condition: Called with input_lock held */
 static Bool
 mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
 {
@@ -142,11 +142,6 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
 
     n_enqueued = mieqNumEnqueued(eventQueue);
 
-    /* We lock input, so an mieqEnqueue does not
-     * write to our queue as we are modifying it.
-     */
-    input_lock();
-
     /* First copy the existing events */
     first_hunk = eventQueue->nevents - eventQueue->head;
     memcpy(new_events,
@@ -178,7 +173,6 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
     free(eventQueue->events);
     eventQueue->events = new_events;
 
-    input_unlock();
     return TRUE;
 }
 
@@ -188,8 +182,10 @@ mieqInit(void)
     memset(&miEventQueue, 0, sizeof(miEventQueue));
     miEventQueue.lastEventTime = GetTimeInMillis();
 
+    input_lock();
     if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
         FatalError("Could not allocate event queue.\n");
+    input_unlock();
 
     SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
     return TRUE;
@@ -209,32 +205,9 @@ mieqFini(void)
     free(miEventQueue.events);
 }
 
-/* This function will determine if the given event is allowed to used the reserved
- * queue space.
- */
-static Bool
-mieqReservedCandidate(InternalEvent *e)
-{
-    switch (e->any.type) {
-    case ET_KeyRelease:
-    case ET_ButtonRelease:
-#if XFreeXDGA
-    case ET_DGAEvent:
-#endif
-    case ET_RawKeyRelease:
-    case ET_RawButtonRelease:
-    case ET_XQuartz:
-        return TRUE;
-    default:
-        return FALSE;
-    }
-}
-
 /*
  * Must be reentrant with ProcessInputEvents.  Assumption: mieqEnqueue
- * will never be interrupted.  If this is called from both signal
- * handlers and regular code, make sure the signal is suspended when
- * called from regular code.
+ * will never be interrupted. Must be called with input_lock held
  */
 
 void
@@ -263,36 +236,36 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
         oldtail != miEventQueue.head) {
         oldtail = (oldtail - 1) % miEventQueue.nevents;
     }
-    else if ((n_enqueued + 1 == miEventQueue.nevents) ||
-             ((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) &&
-              !mieqReservedCandidate(e))) {
-        /* Toss events which come in late.  Usually this means your server's
-         * stuck in an infinite loop somewhere, but SIGIO is still getting
-         * handled.
-         */
-        miEventQueue.dropped++;
-        if (miEventQueue.dropped == 1) {
-            ErrorFSigSafe("[mi] EQ overflowing.  Additional events will be "
-                         "discarded until existing events are processed.\n");
-            xorg_backtrace();
-            ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
-                         "a culprit higher up the stack.\n");
-            ErrorFSigSafe("[mi] mieq is *NOT* the cause.  It is a victim.\n");
-        }
-        else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
-                 miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <=
-                 QUEUE_DROP_BACKTRACE_MAX) {
-            ErrorFSigSafe("[mi] EQ overflow continuing.  %zu events have been "
-                         "dropped.\n", miEventQueue.dropped);
-            if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
-                QUEUE_DROP_BACKTRACE_MAX) {
-                ErrorFSigSafe("[mi] No further overflow reports will be "
-                             "reported until the clog is cleared.\n");
+    else if (n_enqueued + 1 == miEventQueue.nevents) {
+        if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
+            /* Toss events which come in late.  Usually this means your server's
+             * stuck in an infinite loop somewhere, but SIGIO is still getting
+             * handled.
+             */
+            miEventQueue.dropped++;
+            if (miEventQueue.dropped == 1) {
+                ErrorFSigSafe("[mi] EQ overflowing.  Additional events will be "
+                              "discarded until existing events are processed.\n");
+                xorg_backtrace();
+                ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
+                              "a culprit higher up the stack.\n");
+                ErrorFSigSafe("[mi] mieq is *NOT* the cause.  It is a victim.\n");
+            }
+            else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
+                     miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <=
+                     QUEUE_DROP_BACKTRACE_MAX) {
+                ErrorFSigSafe("[mi] EQ overflow continuing.  %zu events have been "
+                              "dropped.\n", miEventQueue.dropped);
+                if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
+                    QUEUE_DROP_BACKTRACE_MAX) {
+                    ErrorFSigSafe("[mi] No further overflow reports will be "
+                                  "reported until the clog is cleared.\n");
+                }
+                xorg_backtrace();
             }
-            xorg_backtrace();
+            return;
         }
-
-        return;
+        oldtail = miEventQueue.tail;
     }
 
     evlen = e->any.length;
@@ -556,7 +529,6 @@ mieqProcessInputEvents(void)
     ScreenPtr screen;
     InternalEvent event;
     DeviceIntPtr dev = NULL, master = NULL;
-    size_t n_enqueued;
     static Bool inProcessInputEvents = FALSE;
 
     input_lock();
@@ -569,17 +541,6 @@ mieqProcessInputEvents(void)
     BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n");
     inProcessInputEvents = TRUE;
 
-    /* Grow our queue if we are reaching capacity: < 2 * QUEUE_RESERVED_SIZE remaining */
-    n_enqueued = mieqNumEnqueued(&miEventQueue);
-    if (n_enqueued >= (miEventQueue.nevents - (2 * QUEUE_RESERVED_SIZE)) &&
-        miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) {
-        ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n",
-               (unsigned long) (miEventQueue.nevents << 1));
-        if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
-            ErrorF("[mi] Increasing the size of EQ failed.\n");
-        }
-    }
-
     if (miEventQueue.dropped) {
         ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n",
                (unsigned long) miEventQueue.dropped);
commit 30ac7567980a1eb79d084a63e0e74e1d9a3af673
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 11:37:51 2015 -0800

    Create a threaded mechanism for input [v7]
    
    The current SIGIO signal handler method, used at generation of input events,
    has a bunch of oddities. This patch introduces an alternative way using a
    thread, which is used to select() all input device file descriptors.
    
    A mutex was used to control the access to input structures by the main and input
    threads. Two pipes to emit alert events (such hotplug ones) and guarantee the
    proper communication between them was also used.
    
    Co-authored-by: Fernando Carrijo <fcarrijo at freedesktop.org>
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    
    v2: Fix non-Xorg link. Enable where supported by default.
    
        This also splits out the actual enabling of input threads to
        DDX-specific patches which follow
    
    v3: Make the input lock recursive
    
    v4: Use regular RECURSIVE_MUTEXes instead of rolling our own
        Respect the --disable-input-thread configuration option by
        providing stubs that expose the same API/ABI.
    
        Respond to style comments from Peter Hutterer.
    
    v5: use __func__ in inputthread debug and error mesages.
    
        Respond to style comments from Peter Hutterer.
    
    v6: use AX_PTHREAD instead of inlining pthread tests.
    
        Suggested by Emil Velikov <emil.l.velikov at gmail.com>
    
    v7: Use pthread_sigmask instead of sigprocmask when using threads
    
        Suggested by Adam Jackson <ajax at redhat.com>
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index c728d30..6c96de2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -832,6 +832,25 @@ SDK_REQUIRED_MODULES="$XPROTO $RANDRPROTO $RENDERPROTO $XEXTPROTO $INPUTPROTO $K
 # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
 AC_SUBST(SDK_REQUIRED_MODULES)
 
+AC_CHECK_DECL([PTHREAD_MUTEX_RECURSIVE], [HAVE_RECURSIVE_MUTEX=yes], [HAVE_RECURSIVE_MUTEX=no], [[#include <pthread.h>]])
+
+THREAD_DEFAULT=no
+
+if test "x$HAVE_RECURSIVE_MUTEX" = "xyes" ; then
+	THREAD_DEFAULT=yes
+fi
+
+AC_ARG_ENABLE(input-thread, AS_HELP_STRING([--enable-input-thread],
+	     [Enable input threads]),
+	     [INPUTTHREAD=$enableval], [INPUTTHREAD=$THREAD_DEFAULT])
+
+if test "x$INPUTTHREAD" = "xyes" ; then
+    AX_PTHREAD(,AC_MSG_ERROR([threaded input requested but no pthread support has been found]))
+    SYS_LIBS="$SYS_LIBS $PTHREAD_LIBS"
+    CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+    AC_DEFINE(INPUTTHREAD, 1, [Use a separate input thread])
+fi
+
 REQUIRED_MODULES="$FIXESPROTO $DAMAGEPROTO $XCMISCPROTO $XTRANS $BIGREQSPROTO $SDK_REQUIRED_MODULES"
 
 dnl systemd socket activation
diff --git a/dix/globals.c b/dix/globals.c
index f36a938..e313930 100644
--- a/dix/globals.c
+++ b/dix/globals.c
@@ -132,3 +132,12 @@ Bool explicit_display = FALSE;
 char *ConnectionInfo;
 
 CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
+
+#if DEBUG_INPUT_MUTEX
+#define INPUT_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+#else
+#define INPUT_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#endif
+
+pthread_mutex_t input_mutex = INPUT_MUTEX_INITIALIZER;
+__thread int input_mutex_count;
diff --git a/dix/main.c b/dix/main.c
index 77e0f2e..4ba4313 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -121,12 +121,9 @@ Equipment Corporation.
 extern void Dispatch(void);
 
 #ifdef XQUARTZ
-#include <pthread.h>
-
-BOOL serverRunning = FALSE;
+BOOL serverRunning;
 pthread_mutex_t serverRunningMutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t serverRunningCond = PTHREAD_COND_INITIALIZER;
-
 #endif
 
 CallbackListPtr RootWindowFinalizeCallback = NULL;
@@ -299,6 +296,8 @@ dix_main(int argc, char *argv[], char *envp[])
 
         NotifyParentProcess();
 
+        InputThreadInit();
+
         Dispatch();
 
 #ifdef XQUARTZ
@@ -331,6 +330,8 @@ dix_main(int argc, char *argv[], char *envp[])
 
         CloseInput();
 
+        InputThreadFini();
+
         for (i = 0; i < screenInfo.numScreens; i++)
             screenInfo.screens[i]->root = NullWindow;
 
diff --git a/hw/dmx/input/dmxsigio.c b/hw/dmx/input/dmxsigio.c
index 6ef543c..ebfd3d9 100644
--- a/hw/dmx/input/dmxsigio.c
+++ b/hw/dmx/input/dmxsigio.c
@@ -99,7 +99,7 @@ dmxSigioHook(void)
     sigaction(SIGIO, &a, 0);
 
     sigemptyset(&s);
-    sigprocmask(SIG_SETMASK, &s, 0);
+    xthread_sigmask(SIG_SETMASK, &s, 0);
 }
 
 static void
diff --git a/hw/xfree86/os-support/shared/sigio.c b/hw/xfree86/os-support/shared/sigio.c
index e0cd7a8..37d35f7 100644
--- a/hw/xfree86/os-support/shared/sigio.c
+++ b/hw/xfree86/os-support/shared/sigio.c
@@ -137,7 +137,7 @@ xf86BlockSIGIO(void)
 
     sigemptyset(&set);
     sigaddset(&set, SIGIO);
-    sigprocmask(SIG_BLOCK, &set, NULL);
+    xthread_sigmask(SIG_BLOCK, &set, NULL);
 }
 
 static void
@@ -147,7 +147,7 @@ xf86ReleaseSIGIO(void)
 
     sigemptyset(&set);
     sigaddset(&set, SIGIO);
-    sigprocmask(SIG_UNBLOCK, &set, NULL);
+    xthread_sigmask(SIG_UNBLOCK, &set, NULL);
 }
 
 int
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index a164c15..fc7d1a1 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -524,4 +524,7 @@
 /* Have posix_fallocate() */
 #undef HAVE_POSIX_FALLOCATE
 
+/* Use input thread */
+#undef INPUTTHREAD
+
 #endif /* _DIX_CONFIG_H_ */
diff --git a/include/input.h b/include/input.h
index 9069a1c..e0f6b9b 100644
--- a/include/input.h
+++ b/include/input.h
@@ -56,6 +56,7 @@ SOFTWARE.
 #include "xkbrules.h"
 #include "events.h"
 #include "list.h"
+#include "os.h"
 #include <X11/extensions/XI2.h>
 
 #define DEVICE_INIT	0
@@ -714,13 +715,20 @@ extern _X_HIDDEN void input_constrain_cursor(DeviceIntPtr pDev, ScreenPtr screen
                                              int *out_x, int *out_y,
                                              int *nevents, InternalEvent* events);
 
-static inline void input_lock(void) {
-}
+extern _X_EXPORT void input_lock(void);
+extern _X_EXPORT void input_unlock(void);
+extern _X_EXPORT void input_force_unlock(void);
 
-static inline void input_unlock(void) {
-}
+extern void InputThreadPreInit(void);
+extern void InputThreadInit(void);
+extern void InputThreadFini(void);
 
-static inline void input_force_unlock(void) {
-}
+extern int InputThreadRegisterDev(int fd,
+                                  NotifyFdProcPtr readInputProc,
+                                  void *readInputArgs);
+
+extern int InputThreadUnregisterDev(int fd);
+
+extern _X_EXPORT Bool InputThreadEnable;
 
 #endif                          /* INPUT_H */
diff --git a/include/misc.h b/include/misc.h
index 56e138c..006f768 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -79,6 +79,7 @@ OF THIS SOFTWARE.
 
 #include <stddef.h>
 #include <stdint.h>
+#include <pthread.h>
 
 #ifndef MAXSCREENS
 #define MAXSCREENS	16
diff --git a/include/os.h b/include/os.h
index e9b3709..20224f1 100644
--- a/include/os.h
+++ b/include/os.h
@@ -706,4 +706,9 @@ xorg_backtrace(void);
 extern _X_EXPORT int
 os_move_fd(int fd);
 
+#include <signal.h>
+
+extern _X_EXPORT int
+xthread_sigmask(int how, const sigset_t *set, sigset_t *oldest);
+
 #endif                          /* OS_H */
diff --git a/mi/mieq.c b/mi/mieq.c
index 8fbe6c3..8a67213 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -88,9 +88,6 @@ typedef struct _EventQueue {
 static EventQueueRec miEventQueue;
 
 #ifdef XQUARTZ
-#include  <pthread.h>
-static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
-
 extern BOOL serverRunning;
 extern pthread_mutex_t serverRunningMutex;
 extern pthread_cond_t serverRunningCond;
@@ -252,7 +249,6 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
 #ifdef XQUARTZ
     wait_for_server_init();
-    pthread_mutex_lock(&miEventQueueMutex);
 #endif
 
     verify_internal_event(e);
@@ -296,9 +292,6 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
             xorg_backtrace();
         }
 
-#ifdef XQUARTZ
-        pthread_mutex_unlock(&miEventQueueMutex);
-#endif
         return;
     }
 
@@ -319,9 +312,6 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 
     miEventQueue.lastMotion = isMotion;
     miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents;
-#ifdef XQUARTZ
-    pthread_mutex_unlock(&miEventQueueMutex);
-#endif
 }
 
 /**
@@ -342,31 +332,19 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
 void
 mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool set_dequeue_screen)
 {
-#ifdef XQUARTZ
-    pthread_mutex_lock(&miEventQueueMutex);
-#endif
     EnqueueScreen(pDev) = pScreen;
     if (set_dequeue_screen)
         DequeueScreen(pDev) = pScreen;
-#ifdef XQUARTZ
-    pthread_mutex_unlock(&miEventQueueMutex);
-#endif
 }
 
 void
 mieqSetHandler(int event, mieqHandler handler)
 {
-#ifdef XQUARTZ
-    pthread_mutex_lock(&miEventQueueMutex);
-#endif
     if (handler && miEventQueue.handlers[event])
         ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
                "event %d\n", miEventQueue.handlers[event], handler, event);
 
     miEventQueue.handlers[event] = handler;
-#ifdef XQUARTZ
-    pthread_mutex_unlock(&miEventQueueMutex);
-#endif
 }
 
 /**
@@ -581,9 +559,7 @@ mieqProcessInputEvents(void)
     size_t n_enqueued;
     static Bool inProcessInputEvents = FALSE;
 
-#ifdef XQUARTZ
-    pthread_mutex_lock(&miEventQueueMutex);
-#endif
+    input_lock();
 
     /*
      * report an error if mieqProcessInputEvents() is called recursively;
@@ -621,9 +597,7 @@ mieqProcessInputEvents(void)
 
         miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents;
 
-#ifdef XQUARTZ
-        pthread_mutex_unlock(&miEventQueueMutex);
-#endif
+        input_unlock();
 
         master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL;
 
@@ -647,14 +621,10 @@ mieqProcessInputEvents(void)
               event.device_event.flags & TOUCH_POINTER_EMULATED)))
             miPointerUpdateSprite(dev);
 
-#ifdef XQUARTZ
-        pthread_mutex_lock(&miEventQueueMutex);
-#endif
+        input_lock();
     }
 
     inProcessInputEvents = FALSE;
 
-#ifdef XQUARTZ
-    pthread_mutex_unlock(&miEventQueueMutex);
-#endif
+    input_unlock();
 }
diff --git a/os/Makefile.am b/os/Makefile.am
index a1bbb4d..fc49a73 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -14,6 +14,7 @@ libos_la_SOURCES = 	\
 	backtrace.c	\
 	client.c	\
 	connection.c	\
+	inputthread.c	\
 	io.c		\
 	mitauth.c	\
 	oscolor.c	\
diff --git a/os/inputthread.c b/os/inputthread.c
new file mode 100644
index 0000000..b6bbf35
--- /dev/null
+++ b/os/inputthread.c
@@ -0,0 +1,470 @@
+/* inputthread.c -- Threaded generation of input events.
+ *
+ * Copyright © 2007-2008 Tiago Vignatti <vignatti at freedesktop org>
+ * Copyright © 2010 Nokia
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Fernando Carrijo <fcarrijo at freedesktop org>
+ *          Tiago Vignatti <vignatti at freedesktop org>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <X11/Xpoll.h>
+#include "inputstr.h"
+#include "opaque.h"
+#include "osdep.h"
+
+#if INPUTTHREAD
+
+Bool InputThreadEnable = TRUE;
+
+/**
+ * An input device as seen by the threaded input facility
+ */
+typedef struct _InputThreadDevice {
+    struct xorg_list node;
+    NotifyFdProcPtr readInputProc;
+    void *readInputArgs;
+    int fd;
+} InputThreadDevice;
+
+/**
+ * The threaded input facility.
+ *
+ * For now, we have one instance for all input devices.
+ */
+typedef struct {
+    pthread_t thread;
+    struct xorg_list devs;
+    fd_set fds;
+    int readPipe;
+    int writePipe;
+} InputThreadInfo;
+
+static InputThreadInfo *inputThreadInfo;
+
+static int hotplugPipeRead = -1;
+static int hotplugPipeWrite = -1;
+
+static int input_mutex_count;
+
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+static pthread_mutex_t input_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#else
+static pthread_mutex_t input_mutex;
+static Bool input_mutex_initialized;
+#endif
+
+void
+input_lock(void)
+{
+#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+    if (!input_mutex_initialized) {
+        pthread_mutexattr_t mutex_attr;
+
+        input_mutex_initialized = TRUE;
+        pthread_mutexattr_init(&mutex_attr);
+        pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&input_mutex, &mutex_attr);
+    }
+#endif
+    pthread_mutex_lock(&input_mutex);
+    ++input_mutex_count;
+}
+
+void
+input_unlock(void)
+{
+    --input_mutex_count;
+    pthread_mutex_unlock(&input_mutex);
+}
+
+void
+input_force_unlock(void)
+{
+    if (pthread_mutex_trylock(&input_mutex) == 0) {
+        /* unlock +1 times for the trylock */
+        while (input_mutex_count-- >= 0)
+            pthread_mutex_unlock(&input_mutex);
+    }
+}
+
+/**
+ * Notify a thread about the availability of new asynchronously enqueued input
+ * events.
+ *
+ * @see WaitForSomething()
+ */
+static void
+InputThreadFillPipe(int writeHead)
+{
+    int ret;
+    char byte = 0;
+    fd_set writePipe;
+
+    FD_ZERO(&writePipe);
+
+    while (1) {
+        ret = write(writeHead, &byte, 1);
+        if (!ret)
+            FatalError("input-thread: write() returned 0");
+        if (ret > 0)
+            break;
+
+        if (errno != EAGAIN)
+            FatalError("input-thread: filling pipe");
+
+        DebugF("input-thread: pipe full\n");
+        FD_SET(writeHead, &writePipe);
+        Select(writeHead + 1, NULL, &writePipe, NULL, NULL);
+    }
+}
+
+/**
+ * Consume eventual notifications left by a thread.
+ *
+ * @see WaitForSomething()
+ * @see InputThreadFillPipe()
+ */
+static int
+InputThreadReadPipe(int readHead)
+{
+    int ret, array[10];
+
+    ret = read(readHead, &array, sizeof(array));
+    if (ret >= 0)
+        return ret;
+
+    if (errno != EAGAIN)
+        FatalError("input-thread: draining pipe (%d)", errno);
+
+    return 1;
+}
+
+/**
+ * Register an input device in the threaded input facility
+ *
+ * @param fd File descriptor which identifies the input device
+ * @param readInputProc Procedure used to read input from the device
+ * @param readInputArgs Arguments to be consumed by the above procedure
+ *
+ * return 1 if success; 0 otherwise.
+ */
+int
+InputThreadRegisterDev(int fd,
+                       NotifyFdProcPtr readInputProc,
+                       void *readInputArgs)
+{
+    InputThreadDevice *dev;
+
+    if (!inputThreadInfo)
+        return SetNotifyFd(fd, readInputProc, X_NOTIFY_READ, readInputArgs);
+
+    dev = calloc(1, sizeof(InputThreadDevice));
+    if (dev == NULL) {
+        DebugF("input-thread: could not register device\n");
+        return 0;
+    }
+
+    dev->fd = fd;
+    dev->readInputProc = readInputProc;
+    dev->readInputArgs = readInputArgs;
+
+    xorg_list_add(&dev->node, &inputThreadInfo->devs);
+
+    FD_SET(fd, &inputThreadInfo->fds);
+
+    InputThreadFillPipe(hotplugPipeWrite);
+    DebugF("input-thread: registered device %d\n", fd);
+
+    return 1;
+}
+
+/**
+ * Unregister a device in the threaded input facility
+ *
+ * @param fd File descriptor which identifies the input device
+ *
+ * @return 1 if success; 0 otherwise.
+ */
+int
+InputThreadUnregisterDev(int fd)
+{
+    InputThreadDevice *dev;
+    Bool found_device = FALSE;
+
+    /* return silently if input thread is already finished (e.g., at
+     * DisableDevice time, evdev tries to call this function again through
+     * xf86RemoveEnabledDevice) */
+    if (!inputThreadInfo) {
+        RemoveNotifyFd(fd);
+        return 1;
+    }
+
+    xorg_list_for_each_entry(dev, &inputThreadInfo->devs, node)
+        if (dev->fd == fd) {
+            found_device = TRUE;
+            break;
+        }
+
+    /* fd didn't match any registered device. */
+    if (!found_device)
+        return 0;
+
+    xorg_list_del(&dev->node);
+
+    FD_CLR(fd, &inputThreadInfo->fds);
+    free(dev);
+
+    InputThreadFillPipe(hotplugPipeWrite);
+    DebugF("input-thread: unregistered device: %d\n", fd);
+
+    return 1;
+}
+
+/**
+ * The workhorse of threaded input event generation.
+ *
+ * Or if you prefer: The WaitForSomething for input devices. :)
+ *
+ * Runs in parallel with the server main thread, listening to input devices in
+ * an endless loop. Whenever new input data is made available, calls the
+ * proper device driver's routines which are ultimately responsible for the
+ * generation of input events.
+ *
+ * @see InputThreadPreInit()
+ * @see InputThreadInit()
+ */
+
+static void*
+InputThreadDoWork(void *arg)
+{
+    fd_set readyFds;
+    InputThreadDevice *dev, *next;
+    sigset_t set;
+
+    /* Don't handle any signals on this thread */
+    sigfillset(&set);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    FD_ZERO(&readyFds);
+
+    while (1)
+    {
+        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 (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;
+        }
+    }
+    return NULL;
+}
+
+static void
+InputThreadNotifyPipe(int fd, int mask, void *data)
+{
+    InputThreadReadPipe(fd);
+}
+
+/**
+ * Pre-initialize the facility used for threaded generation of input events
+ *
+ */
+void
+InputThreadPreInit(void)
+{
+    int fds[2], hotplugPipe[2];
+
+    if (!InputThreadEnable)
+        return;
+
+    if (pipe(fds) < 0)
+        FatalError("input-thread: could not create pipe");
+
+     if (pipe(hotplugPipe) < 0)
+        FatalError("input-thread: could not create pipe");
+
+    inputThreadInfo = malloc(sizeof(InputThreadInfo));
+    if (!inputThreadInfo)
+        FatalError("input-thread: could not allocate memory");
+
+    inputThreadInfo->thread = 0;
+    xorg_list_init(&inputThreadInfo->devs);
+    FD_ZERO(&inputThreadInfo->fds);
+
+    /* By making read head non-blocking, we ensure that while the main thread
+     * is busy servicing client requests, the dedicated input thread can work
+     * in parallel.
+     */
+    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];
+
+    hotplugPipeRead = hotplugPipe[0];
+    fcntl(hotplugPipeRead, F_SETFL, O_NONBLOCK | O_CLOEXEC);
+    hotplugPipeWrite = hotplugPipe[1];
+}
+
+/**
+ * Start the threaded generation of input events. This routine complements what
+ * was previously done by InputThreadPreInit(), being only responsible for
+ * creating the dedicated input thread.
+ *
+ */
+void
+InputThreadInit(void)
+{
+    pthread_attr_t attr;
+
+    /* If the driver hasn't asked for input thread support by calling
+     * InputThreadPreInit, then do nothing here
+     */
+    if (!inputThreadInfo)
+        return;
+
+    pthread_attr_init(&attr);
+
+    /* For OSes that differentiate between processes and threads, the following
+     * lines have sense. Linux uses the 1:1 thread model. The scheduler handles
+     * every thread as a normal process. Therefore this probably has no meaning
+     * if we are under Linux.
+     */
+    if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0)
+        ErrorF("input-thread: error setting thread scope\n");
+
+    DebugF("input-thread: creating thread\n");
+    pthread_create(&inputThreadInfo->thread, &attr,
+                   &InputThreadDoWork, NULL);
+
+    pthread_attr_destroy (&attr);
+}
+
+/**
+ * Stop the threaded generation of input events
+ *
+ * This function is supposed to be called at server shutdown time only.
+ */
+void
+InputThreadFini(void)
+{
+    InputThreadDevice *dev, *next;
+
+    if (!inputThreadInfo)
+        return;
+
+    /* Close the pipe to get the input thread to shut down */
+    close(hotplugPipeWrite);
+    pthread_join(inputThreadInfo->thread, NULL);
+
+    xorg_list_for_each_entry_safe(dev, next, &inputThreadInfo->devs, node) {
+        FD_CLR(dev->fd, &inputThreadInfo->fds);
+        free(dev);
+    }
+    xorg_list_init(&inputThreadInfo->devs);
+    FD_ZERO(&inputThreadInfo->fds);
+
+    RemoveNotifyFd(inputThreadInfo->readPipe);
+    close(inputThreadInfo->readPipe);
+    close(inputThreadInfo->writePipe);
+    inputThreadInfo->readPipe = -1;
+    inputThreadInfo->writePipe = -1;
+
+    close(hotplugPipeRead);
+    hotplugPipeRead = -1;
+    hotplugPipeWrite = -1;
+
+    free(inputThreadInfo);
+    inputThreadInfo = NULL;
+}
+
+int xthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+    return pthread_sigmask(how, set, oldset);
+}
+
+#else /* INPUTTHREAD */
+
+Bool InputThreadEnable = FALSE;
+
+void input_lock(void) {}
+void input_unlock(void) {}
+void input_force_unlock(void) {}
+
+void InputThreadPreInit(void) {}
+void InputThreadInit(void) {}
+void InputThreadFini(void) {}
+
+int InputThreadRegisterDev(int fd,
+                           NotifyFdProcPtr readInputProc,
+                           void *readInputArgs)
+{
+    return SetNotifyFd(fd, readInputProc, X_NOTIFY_READ, readInputArgs);
+}
+
+extern int InputThreadUnregisterDev(int fd)
+{
+    RemoveNotifyFd(fd);
+    return 1;
+}
+
+int xthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+    return sigprocmask(how, set, oldset);
+}
+
+#endif
diff --git a/os/utils.c b/os/utils.c
index db875c1..b5c5c5d 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -586,7 +586,7 @@ UseMsg(void)
     ErrorF("-xinerama              Disable XINERAMA extension\n");
 #endif
     ErrorF
-        ("-dumbSched             Disable smart scheduling, enable old behavior\n");
+        ("-dumbSched             Disable smart scheduling and threaded input, enable old behavior\n");
     ErrorF("-schedInterval int     Set scheduler interval in msec\n");
     ErrorF("-sigstop               Enable SIGSTOP based startup\n");
     ErrorF("+extension name        Enable extension\n");
@@ -1004,11 +1004,12 @@ ProcessCommandLine(int argc, char *argv[])
             i = skip - 1;
         }
 #endif
-#if HAVE_SETITIMER
         else if (strcmp(argv[i], "-dumbSched") == 0) {
+            InputThreadEnable = FALSE;
+#if HAVE_SETITIMER
             SmartScheduleSignalEnable = FALSE;
-        }
 #endif
+        }
         else if (strcmp(argv[i], "-schedInterval") == 0) {
             if (++i < argc) {
                 SmartScheduleInterval = atoi(argv[i]);
@@ -1304,7 +1305,6 @@ OsBlockSignals(void)
     if (BlockedSignalCount++ == 0) {
         sigset_t set;
 
-        input_lock();
         sigemptyset(&set);
         sigaddset(&set, SIGALRM);
         sigaddset(&set, SIGVTALRM);
@@ -1315,7 +1315,7 @@ OsBlockSignals(void)
         sigaddset(&set, SIGTTIN);
         sigaddset(&set, SIGTTOU);
         sigaddset(&set, SIGCHLD);
-        sigprocmask(SIG_BLOCK, &set, &PreviousSignalMask);
+        xthread_sigmask(SIG_BLOCK, &set, &PreviousSignalMask);
     }
 #endif
 }
@@ -1325,8 +1325,7 @@ OsReleaseSignals(void)
 {
 #ifdef SIG_BLOCK
     if (--BlockedSignalCount == 0) {
-        sigprocmask(SIG_SETMASK, &PreviousSignalMask, 0);
-        input_unlock();
+        xthread_sigmask(SIG_SETMASK, &PreviousSignalMask, 0);
     }
 #endif
 }
commit 728c9570a05f03bd90343ff6f5b1a8fd3988864c
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Dec 9 14:27:05 2015 -0800

    xkb: Hold input lock across injected key event processing
    
    This makes the code more consistent with other versions of
    out-of-queue event processing
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index afe5edf..048ed44 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1534,13 +1534,12 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
         UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
                          &nevents);
     miPointerSetWaitForUpdate(pScreen, saveWait);
-    input_unlock();
 
     for (i = 0; i < nevents; i++)
         mieqProcessDeviceEvent(ptr, &events[i], NULL);
+    input_unlock();
 
     FreeEventList(events, GetMaximumEventsNum());
-
 }
 
 static void
commit 05d549d60440126105d5a70272e72ea2319724bd
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Dec 17 22:21:46 2015 -0800

    xfree86: Remove unnecessary errno save/restore in xf86ReadInput
    
    When this code was called from SIGIO, saving and restoring errno could
    possibly have made sense in some strange environment. Now that this
    will not be called from a signal handler, there is no reason to do that.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 81416ed..df8c7b6 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -298,12 +298,9 @@ xf86Wakeup(void *blockData, int err, void *pReadmask)
 static void
 xf86ReadInput(int fd, int ready, void *closure)
 {
-    int errno_save = errno;
     InputInfoPtr pInfo = closure;
 
     pInfo->read_input(pInfo);
-
-    errno = errno_save;
 }
 
 /*
commit 0bbb5aabf794720fa99ae5ea3f55138ded159705
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 16 21:33:41 2016 -0500

    kdrive: Don't lock input across read in KdNotifyFd
    
    We won't need these locks with the new threaded input code as it holds
    the input lock across all of the input device I/O operations.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 0cf45bb..b415a86 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -139,9 +139,7 @@ static void
 KdNotifyFd(int fd, int ready, void *data)
 {
     int i = (int) (intptr_t) data;
-    input_lock();
     (*kdInputFds[i].read)(fd, kdInputFds[i].closure);
-    input_unlock();
 }
 
 static void
commit 6a5a4e60373c1386b311b2a8bb666c32d68a9d99
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Dec 8 14:39:46 2015 -0800

    Remove SIGIO support for input [v5]
    
    This removes all of the SIGIO handling support used for input
    throughout the X server, preparing the way for using threads for input
    handling instead.
    
    Places calling OsBlockSIGIO and OsReleaseSIGIO are marked with calls
    to stub functions input_lock/input_unlock so that we don't lose this
    information.
    
    xfree86 SIGIO support is reworked to use internal versions of
    OsBlockSIGIO and OsReleaseSIGIO.
    
    v2: Don't change locking order (Peter Hutterer)
    v3: Comment weird && FALSE in xf86Helper.c
        Leave errno save/restore in xf86ReadInput
        Squash with stub adding patch (Peter Hutterer)
    v4: Leave UseSIGIO config parameter so that
        existing config files don't break (Peter Hutterer)
    v5: Split a couple of independent patch bits out
        of kinput.c (Peter Hutterer)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 5a0b68d..fc5298e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -661,7 +661,7 @@ void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
                       DeviceChangedEvent *dce)
 {
-    OsBlockSIGIO();
+    input_lock();
 
     /* generic feedback classes, not tied to pointer and/or keyboard */
     DeepCopyFeedbackClasses(from, to);
@@ -671,7 +671,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
     if ((dce->flags & DEVCHANGE_POINTER_EVENT))
         DeepCopyPointerClasses(from, to);
 
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 /**
diff --git a/config/config.c b/config/config.c
index de45cc3..1fb368c 100644
--- a/config/config.c
+++ b/config/config.c
@@ -86,10 +86,10 @@ remove_device(const char *backend, DeviceIntPtr dev)
 
     /* Call PIE here so we don't try to dereference a device that's
      * already been removed. */
-    OsBlockSignals();
+    input_lock();
     ProcessInputEvents();
     DeleteInputDeviceRequest(dev);
-    OsReleaseSignals();
+    input_unlock();
 }
 
 void
diff --git a/configure.ac b/configure.ac
index cf13123..c728d30 100644
--- a/configure.ac
+++ b/configure.ac
@@ -381,7 +381,6 @@ AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes])
 AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes])
 
 DRI=no
-USE_SIGIO_BY_DEFAULT="yes"
 dnl it would be nice to autodetect these *CONS_SUPPORTs
 case $host_os in
   *freebsd* | *dragonfly*)
@@ -411,9 +410,6 @@ case $host_os in
 	;;
   *solaris*)
 	PKG_CHECK_EXISTS(libdrm, DRI=yes, DRI=no)
-	# Disable use of SIGIO by default until some system bugs are
-	# fixed - see Sun/OpenSolaris bug id 6879897
-	USE_SIGIO_BY_DEFAULT="no"
 	;;
   darwin*)
 	AC_DEFINE(CSRG_BASED, 1, [System is BSD-like])
@@ -446,9 +442,6 @@ AC_ARG_ENABLE(werror,        AS_HELP_STRING([--enable-werror],
 AC_ARG_ENABLE(debug,         AS_HELP_STRING([--enable-debug],
 				  [Enable debugging (default: disabled)]),
 			        [DEBUGGING=$enableval], [DEBUGGING=no])
-AC_ARG_ENABLE(use-sigio-by-default, AS_HELP_STRING([--enable-use-sigio-by-default]
-  [Enable SIGIO input handlers by default (default: $USE_SIGIO_BY_DEFAULT)]),
-                                [USE_SIGIO_BY_DEFAULT=$enableval], [])
 AC_ARG_WITH(int10,           AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]),
 				[INT10="$withval"],
 				[INT10="$DEFAULT_INT10"])
@@ -967,13 +960,6 @@ if test "x$CONFIG_WSCONS" = xyes; then
 	AC_DEFINE(CONFIG_WSCONS, 1, [Use wscons for input auto configuration])
 fi
 
-if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then
-	USE_SIGIO_BY_DEFAULT_VALUE=TRUE
-else
-	USE_SIGIO_BY_DEFAULT_VALUE=FALSE
-fi
-AC_DEFINE_UNQUOTED([USE_SIGIO_BY_DEFAULT], [$USE_SIGIO_BY_DEFAULT_VALUE],
-		   [Use SIGIO handlers for input device events by default])
 
 AC_MSG_CHECKING([for glibc...])
 AC_PREPROC_IFELSE([AC_LANG_SOURCE([
diff --git a/dix/devices.c b/dix/devices.c
index fcd0c08..9de84a6 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -493,14 +493,14 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
 
     FreeSprite(dev);
 
-    /* now that the device is disabled, we can reset the signal handler's
+    /* now that the device is disabled, we can reset the event reader's
      * last.slave */
-    OsBlockSignals();
+    input_lock();
     for (other = inputInfo.devices; other; other = other->next) {
         if (other->last.slave == dev)
             other->last.slave = NULL;
     }
-    OsReleaseSignals();
+    input_unlock();
 
     LeaveWindow(dev);
     SetFocusOut(dev);
@@ -1033,7 +1033,7 @@ CloseDownDevices(void)
 {
     DeviceIntPtr dev;
 
-    OsBlockSignals();
+    input_lock();
 
     /* Float all SDs before closing them. Note that at this point resources
      * (e.g. cursors) have been freed already, so we can't just call
@@ -1060,7 +1060,7 @@ CloseDownDevices(void)
     XkbDeleteRulesDflts();
     XkbDeleteRulesUsed();
 
-    OsReleaseSignals();
+    input_unlock();
 }
 
 /**
diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index 727602e..ff39d7b 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -165,7 +165,7 @@ AccelerationDefaultCleanup(DeviceIntPtr dev)
          * AccelSchemeProc(), but that seems impossible. Schemes don't get
          * switched often anyway.
          */
-        OsBlockSignals();
+        input_lock();
         dev->valuator->accelScheme.AccelSchemeProc = NULL;
         FreeVelocityData(vel);
         free(vel);
@@ -175,7 +175,7 @@ AccelerationDefaultCleanup(DeviceIntPtr dev)
                                                 accelData);
         free(dev->valuator->accelScheme.accelData);
         dev->valuator->accelScheme.accelData = NULL;
-        OsReleaseSignals();
+        input_unlock();
     }
 }
 
diff --git a/dix/touch.c b/dix/touch.c
index 54da132..4c0412a 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -79,7 +79,7 @@ TouchResizeQueue(ClientPtr client, void *closure)
 {
     int i;
 
-    OsBlockSignals();
+    input_lock();
 
     /* first two ids are reserved */
     for (i = 2; i < MAXDEVICES; i++) {
@@ -112,7 +112,7 @@ TouchResizeQueue(ClientPtr client, void *closure)
         }
 
     }
-    OsReleaseSignals();
+    input_unlock();
 
     return TRUE;
 }
@@ -1077,7 +1077,7 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
     InternalEvent *eventlist = InitEventList(GetMaximumEventsNum());
     int i;
 
-    OsBlockSignals();
+    input_lock();
     mieqProcessInputEvents();
     for (i = 0; i < dev->last.num_touches; i++) {
         DDXTouchPointInfoPtr ddxti = dev->last.touches + i;
@@ -1091,7 +1091,7 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
                 mieqProcessDeviceEvent(dev, eventlist + j, NULL);
         }
     }
-    OsReleaseSignals();
+    input_unlock();
 
     FreeEventList(eventlist, GetMaximumEventsNum());
 }
diff --git a/hw/dmx/input/dmxevents.c b/hw/dmx/input/dmxevents.c
index 2b579ee..3789602 100644
--- a/hw/dmx/input/dmxevents.c
+++ b/hw/dmx/input/dmxevents.c
@@ -227,25 +227,25 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
             && pScreen->myNum == dmxScreen->index) {
             /* Screen is old screen */
             if (block)
-                OsBlockSIGIO();
+                input_lock();
             if (pDev)
                 enqueueMotion(pDev, localX, localY);
             if (block)
-                OsReleaseSIGIO();
+                input_unlock();
         }
         else {
             /* Screen is new */
             DMXDBG4("   New screen: old=%d new=%d localX=%d localY=%d\n",
                     pScreen->myNum, dmxScreen->index, localX, localY);
             if (block)
-                OsBlockSIGIO();
+                input_lock();
             mieqProcessInputEvents();
             miPointerSetScreen(inputInfo.pointer, dmxScreen->index,
                                localX, localY);
             if (pDev)
                 enqueueMotion(pDev, localX, localY);
             if (block)
-                OsReleaseSIGIO();
+                input_unlock();
         }
 #if 00
         miPointerGetPosition(inputInfo.pointer, &localX, &localY);
@@ -387,12 +387,12 @@ dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
     }
 
     if (block)
-        OsBlockSIGIO();
+        input_lock();
     valuator_mask_set_range(&mask, firstAxis, axesCount, v);
     QueuePointerEvents(pDevice, MotionNotify, 0, POINTER_ABSOLUTE, &mask);
 
     if (block)
-        OsReleaseSIGIO();
+        input_unlock();
 }
 
 static int
@@ -489,10 +489,10 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     case XI_DeviceKeyPress:
     case XI_DeviceKeyRelease:
         if (block)
-            OsBlockSIGIO();
+            input_lock();
         QueueKeyboardEvents(pDevice, event, ke->keycode);
         if (block)
-            OsReleaseSIGIO();
+            input_unlock();
         break;
     case XI_DeviceButtonPress:
     case XI_DeviceButtonRelease:
@@ -500,11 +500,11 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
         valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
                                 valuators);
         if (block)
-            OsBlockSIGIO();
+            input_lock();
         QueuePointerEvents(pDevice, event, ke->keycode,
                            POINTER_ABSOLUTE, &mask);
         if (block)
-            OsReleaseSIGIO();
+            input_unlock();
         break;
     case XI_ProximityIn:
     case XI_ProximityOut:
@@ -512,10 +512,10 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
         valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count,
                                 valuators);
         if (block)
-            OsBlockSIGIO();
+            input_lock();
         QueueProximityEvents(pDevice, event, &mask);
         if (block)
-            OsReleaseSIGIO();
+            input_unlock();
         break;
 
         break;
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index f6897cc..2e7c86c 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -818,11 +818,11 @@ ScreenPtr ephyrCursorScreen; /* screen containing the cursor */
 static void
 ephyrWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
-    OsBlockSIGIO();
+    input_lock();
     ephyrCursorScreen = pScreen;
     miPointerWarpCursor(inputInfo.pointer, pScreen, x, y);
 
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 miPointerScreenFuncRec ephyrPointerScreenFuncs = {
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 64541a3..0cf45bb 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -108,38 +108,6 @@ extern const char *kdGlobalXkbLayout;
 extern const char *kdGlobalXkbVariant;
 extern const char *kdGlobalXkbOptions;
 
-static void
-KdSigio(int sig)
-{
-    int i;
-
-    for (i = 0; i < kdNumInputFds; i++)
-        (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
-}
-
-#ifdef DEBUG_SIGIO
-
-void
-KdAssertSigioBlocked(char *where)
-{
-    sigset_t set, old;
-
-    sigemptyset(&set);
-    sigprocmask(SIG_BLOCK, &set, &old);
-    if (!sigismember(&old, SIGIO)) {
-        ErrorF("SIGIO not blocked at %s\n", where);
-        KdBacktrace(0);
-    }
-}
-
-#else
-
-#define KdAssertSigioBlocked(s)
-
-#endif
-
-static int kdnFds;
-
 #ifdef FNONBLOCK
 #define NOBLOCK FNONBLOCK
 #else
@@ -171,49 +139,27 @@ static void
 KdNotifyFd(int fd, int ready, void *data)
 {
     int i = (int) (intptr_t) data;
-    OsBlockSIGIO();
+    input_lock();
     (*kdInputFds[i].read)(fd, kdInputFds[i].closure);
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 static void
 KdAddFd(int fd, int i)
 {
-    struct sigaction act;
-    sigset_t set;
-
-    kdnFds++;
-    fcntl(fd, F_SETOWN, getpid());
     KdNonBlockFd(fd);
     SetNotifyFd(fd, KdNotifyFd, X_NOTIFY_READ, (void *) (intptr_t) i);
-    memset(&act, '\0', sizeof act);
-    act.sa_handler = KdSigio;
-    sigemptyset(&act.sa_mask);
-    sigaddset(&act.sa_mask, SIGIO);
-    sigaddset(&act.sa_mask, SIGALRM);
-    sigaddset(&act.sa_mask, SIGVTALRM);
-    sigaction(SIGIO, &act, 0);
-    sigemptyset(&set);
-    sigprocmask(SIG_SETMASK, &set, 0);
 }
 
 static void
 KdRemoveFd(int fd)
 {
-    struct sigaction act;
     int flags;
 
-    kdnFds--;
     RemoveNotifyFd(fd);
     flags = fcntl(fd, F_GETFL);
     flags &= ~(FASYNC | NOBLOCK);
     fcntl(fd, F_SETFL, flags);
-    if (kdnFds == 0) {
-        memset(&act, '\0', sizeof act);
-        act.sa_handler = SIG_IGN;
-        sigemptyset(&act.sa_mask);
-        sigaction(SIGIO, &act, 0);
-    }
 }
 
 Bool
@@ -265,7 +211,7 @@ KdDisableInput(void)
     KdPointerInfo *pi;
     int found = 0, i = 0;
 
-    OsBlockSIGIO();
+    input_lock();
 
     for (ki = kdKeyboards; ki; ki = ki->next) {
         if (ki->driver && ki->driver->Disable)
@@ -348,7 +294,7 @@ KdEnableInput(void)
         NoticeEventTime (&ev, pi->dixdev);
     }
 
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 static KdKeyboardDriver *
@@ -1850,7 +1796,7 @@ KdReleaseAllKeys(void)
     int key;
     KdKeyboardInfo *ki;
 
-    OsBlockSIGIO();
+    input_lock();
 
     for (ki = kdKeyboards; ki; ki = ki->next) {
         for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; key++) {
@@ -1861,7 +1807,7 @@ KdReleaseAllKeys(void)
         }
     }
 
-    OsReleaseSIGIO();
+    input_unlock();
 #endif
 }
 
@@ -2049,9 +1995,9 @@ KdWakeupHandler(ScreenPtr pScreen, unsigned long lresult, void *readmask)
         if (pi->timeoutPending) {
             if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) {
                 pi->timeoutPending = FALSE;
-                OsBlockSIGIO();
+                input_lock();
                 KdReceiveTimeout(pi);
-                OsReleaseSIGIO();
+                input_unlock();
             }
         }
     }
@@ -2148,10 +2094,10 @@ int KdCurScreen;                /* current event screen */
 static void
 KdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
-    OsBlockSIGIO();
+    input_lock();
     KdCurScreen = pScreen->myNum;
     miPointerWarpCursor(pDev, pScreen, x, y);
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 miPointerScreenFuncRec kdPointerScreenFuncs = {
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 07f8fb4..5a9f8d2 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -807,27 +807,6 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
         xf86Msg(X_CONFIG, "Ignoring ABI Version\n");
     }
 
-    if (xf86SIGIOSupported()) {
-        xf86Info.useSIGIO =
-            xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO,
-                                 USE_SIGIO_BY_DEFAULT);
-        if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) {
-            from = X_CONFIG;
-        }
-        else {
-            from = X_DEFAULT;
-        }
-        if (!xf86Info.useSIGIO) {
-            xf86Msg(from, "Disabling SIGIO handlers for input devices\n");
-        }
-        else if (from == X_CONFIG) {
-            xf86Msg(from, "Enabling SIGIO handlers for input devices\n");
-        }
-    }
-    else {
-        xf86Info.useSIGIO = FALSE;
-    }
-
     if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) {
         xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES,
                           &xf86Info.autoAddDevices);
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 92c08af..de054fb 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -221,7 +221,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
     if (pScreen == pCursorScreen)
         miPointerGetPosition(dev, &px, &py);
 
-    OsBlockSIGIO();
+    input_lock();
     Switched = (*pScr->SwitchMode) (pScr, mode);
     if (Switched) {
         pScr->currentMode = mode;
@@ -260,7 +260,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
             pScr->frameY1 = pScr->virtualY - 1;
         }
     }
-    OsReleaseSIGIO();
+    input_unlock();
 
     if (pScr->AdjustFrame)
         (*pScr->AdjustFrame) (pScr, pScr->frameX0, pScr->frameY0);
@@ -452,11 +452,11 @@ xf86CrossScreen(ScreenPtr pScreen, Bool entering)
 static void
 xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
-    OsBlockSIGIO();
+    input_lock();
     miPointerWarpCursor(pDev, pScreen, x, y);
 
     xf86Info.currentScreen = pScreen;
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 void *
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 709afd6..81416ed 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -259,7 +259,7 @@ xf86Wakeup(void *blockData, int err, void *pReadmask)
             while (pInfo) {
                 if (pInfo->read_input && pInfo->fd >= 0 &&
                     (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
-                    OsBlockSIGIO();
+                    input_lock();
 
                     /*
                      * Remove the descriptior from the set because more than one
@@ -268,7 +268,7 @@ xf86Wakeup(void *blockData, int err, void *pReadmask)
                     FD_CLR(pInfo->fd, &devicesWithInput);
 
                     pInfo->read_input(pInfo);
-                    OsReleaseSIGIO();
+                    input_unlock();
                 }
                 pInfo = pInfo->next;
             }
@@ -291,11 +291,12 @@ xf86Wakeup(void *blockData, int err, void *pReadmask)
 }
 
 /*
- * xf86SigioReadInput --
- *    signal handler for the SIGIO signal.
+ * xf86ReadInput --
+ *    input thread handler
  */
+
 static void
-xf86SigioReadInput(int fd, void *closure)
+xf86ReadInput(int fd, int ready, void *closure)
 {
     int errno_save = errno;
     InputInfoPtr pInfo = closure;
@@ -312,9 +313,7 @@ xf86SigioReadInput(int fd, void *closure)
 void
 xf86AddEnabledDevice(InputInfoPtr pInfo)
 {
-    if (!xf86InstallSIGIOHandler(pInfo->fd, xf86SigioReadInput, pInfo)) {
-        AddEnabledDevice(pInfo->fd);
-    }
+    SetNotifyFd(pInfo->fd, xf86ReadInput, X_NOTIFY_READ, pInfo);
 }
 
 /*
@@ -324,9 +323,7 @@ xf86AddEnabledDevice(InputInfoPtr pInfo)
 void
 xf86RemoveEnabledDevice(InputInfoPtr pInfo)
 {
-    if (!xf86RemoveSIGIOHandler(pInfo->fd)) {
-        RemoveEnabledDevice(pInfo->fd);
-    }
+    RemoveNotifyFd(pInfo->fd);
 }
 
 static int *xf86SignalIntercept = NULL;
@@ -402,9 +399,9 @@ xf86ReleaseKeys(DeviceIntPtr pDev)
     for (i = keyc->xkbInfo->desc->min_key_code;
          i < keyc->xkbInfo->desc->max_key_code; i++) {
         if (key_is_down(pDev, i, KEY_POSTED)) {
-            OsBlockSIGIO();
+            input_lock();
             QueueKeyboardEvents(pDev, KeyRelease, i);
-            OsReleaseSIGIO();
+            input_unlock();
         }
     }
 }
@@ -487,7 +484,7 @@ xf86VTLeave(void)
     for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
         xf86DisableInputDeviceForVTSwitch(pInfo);
 
-    OsBlockSIGIO();
+    input_lock();
     for (i = 0; i < xf86NumScreens; i++)
         xf86Screens[i]->LeaveVT(xf86Screens[i]);
     for (i = 0; i < xf86NumGPUScreens; i++)
@@ -545,7 +542,7 @@ switch_failed:
         else
             xf86EnableGeneralHandler(ih);
     }
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 void
@@ -603,7 +600,7 @@ xf86VTEnter(void)
 
     xf86UpdateHasVTProperty(TRUE);
 
-    OsReleaseSIGIO();
+    input_unlock();
 }
 
 /*
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 1d4b431..284858b 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1723,7 +1723,11 @@ xf86SetSilkenMouse(ScreenPtr pScreen)
      * yet.  Should handle this differently so that alternate async methods
      * work correctly with this too.
      */
-    pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
+    /* Disable this completely when removing SIGIO support. It
+     * will get re-enabled correctly when we add threaded input
+     * support
+     */
+    pScrn->silkenMouse = useSM && FALSE;
     if (serverGeneration == 1)
         xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
                    pScrn->silkenMouse ? "enabled" : "disabled");
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 66c6689..cf726d4 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -762,7 +762,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
             ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ);
 #endif
             xf86AccessEnter();
-            OsBlockSIGIO();
+            input_lock();
             sigio_blocked = TRUE;
         }
     }
@@ -864,7 +864,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
 
     xf86VGAarbiterWrapFunctions();
     if (sigio_blocked)
-        OsReleaseSIGIO();
+        input_unlock();
 
     xf86InitOrigins();
 
@@ -1010,7 +1010,7 @@ AbortDDX(enum ExitCode error)
 {
     int i;
 
-    OsBlockSIGIO();
+    input_lock();
 
     /*
      * try to restore the original video state
diff --git a/hw/xfree86/common/xf86PM.c b/hw/xfree86/common/xf86PM.c
index 9e49e8e..3f08c81 100644
--- a/hw/xfree86/common/xf86PM.c
+++ b/hw/xfree86/common/xf86PM.c
@@ -107,7 +107,7 @@ suspend(pmEvent event, Bool undo)
         DisableDevice(pInfo->dev, TRUE);
         pInfo = pInfo->next;
     }
-    OsBlockSIGIO();
+    input_lock();
     for (i = 0; i < xf86NumScreens; i++) {
         if (xf86Screens[i]->PMEvent)
             xf86Screens[i]->PMEvent(xf86Screens[i], event, undo);
@@ -135,7 +135,7 @@ resume(pmEvent event, Bool undo)
             xf86Screens[i]->EnterVT(xf86Screens[i]);
         }
     }
-    OsReleaseSIGIO();
+    input_unlock();
     for (i = 0; i < xf86NumScreens; i++) {
         if (xf86Screens[i]->EnableDisableFBAccess)
             (*xf86Screens[i]->EnableDisableFBAccess) (xf86Screens[i], TRUE);
@@ -182,13 +182,13 @@ DoApmEvent(pmEvent event, Bool undo)
         }
         break;
     default:
-        OsBlockSIGIO();
+        input_lock();
         for (i = 0; i < xf86NumScreens; i++) {
             if (xf86Screens[i]->PMEvent) {
                 xf86Screens[i]->PMEvent(xf86Screens[i], event, undo);
             }
         }
-        OsReleaseSIGIO();
+        input_unlock();
         break;
     }
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index b02a162..9ed88f2 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -931,7 +931,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
 
     /* Enable it if it's properly initialised and we're currently in the VT */
     if (enable && dev->inited && dev->startup && xf86VTOwner()) {
-        OsBlockSignals();
+        input_lock();
         EnableDevice(dev, TRUE);
         if (!dev->enabled) {
             OsReleaseSignals();
@@ -942,7 +942,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
         }
         /* send enter/leave event, update sprite window */
         CheckMotion(NULL, dev);
-        OsReleaseSignals();
+        input_unlock();
     }
 
     *pdev = dev;
@@ -1075,7 +1075,7 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
     if (pInfo)                  /* need to get these before RemoveDevice */
         drv = pInfo->drv;
 
-    OsBlockSignals();
+    input_lock();
     RemoveDevice(pDev, TRUE);
 
     if (!isMaster && pInfo != NULL) {
@@ -1084,7 +1084,7 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
         else
             xf86DeleteInput(pInfo, 0);
     }
-    OsReleaseSignals();
+    input_unlock();
 }
 
 /*
diff --git a/hw/xfree86/os-support/shared/sigio.c b/hw/xfree86/os-support/shared/sigio.c
index c746d02..e0cd7a8 100644
--- a/hw/xfree86/os-support/shared/sigio.c
+++ b/hw/xfree86/os-support/shared/sigio.c
@@ -130,6 +130,26 @@ xf86IsPipe(int fd)
     return S_ISFIFO(buf.st_mode);
 }
 
+static void
+xf86BlockSIGIO(void)
+{
+    sigset_t set;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigprocmask(SIG_BLOCK, &set, NULL);
+}
+
+static void
+xf86ReleaseSIGIO(void)
+{
+    sigset_t set;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigprocmask(SIG_UNBLOCK, &set, NULL);
+}
+
 int
 xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
 {
@@ -145,7 +165,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
         if (!xf86SigIOFuncs[i].f) {
             if (xf86IsPipe(fd))
                 return 0;
-            OsBlockSIGIO();
+            xf86BlockSIGIO();
 #ifdef O_ASYNC
             if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC) == -1) {
                 xf86Msg(X_WARNING, "fcntl(%d, O_ASYNC): %s\n",
@@ -173,7 +193,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
             }
 #endif
             if (!installed) {
-                OsReleaseSIGIO();
+                xf86ReleaseSIGIO();
                 return 0;
             }
             sigemptyset(&sa.sa_mask);
@@ -189,7 +209,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
             if (fd >= xf86SigIOMaxFd)
                 xf86SigIOMaxFd = fd + 1;
             FD_SET(fd, &xf86SigIOMask);
-            OsReleaseSIGIO();
+            xf86ReleaseSIGIO();
             return 1;
         }
         /* Allow overwriting of the closure and callback */
@@ -258,34 +278,3 @@ xf86RemoveSIGIOHandler(int fd)
     }
     return ret;
 }
-
-int
-xf86BlockSIGIO(void)
-{
-    return OsBlockSIGIO();
-}
-
-void
-xf86UnblockSIGIO(int wasset)
-{
-    OsReleaseSIGIO();
-}
-
-void
-xf86AssertBlockedSIGIO(char *where)
-{
-    sigset_t set, old;
-
-    sigemptyset(&set);
-    sigprocmask(SIG_BLOCK, &set, &old);
-    if (!sigismember(&old, SIGIO))
-        xf86Msg(X_ERROR, "SIGIO not blocked at %s\n", where);
-}
-
-/* XXX This is a quick hack for the benefit of xf86SetSilkenMouse() */
-
-int
-xf86SIGIOSupported(void)
-{
-    return 1;
-}
diff --git a/hw/xfree86/os-support/shared/sigiostubs.c b/hw/xfree86/os-support/shared/sigiostubs.c
index ba8e234..d1792e8 100644
--- a/hw/xfree86/os-support/shared/sigiostubs.c
+++ b/hw/xfree86/os-support/shared/sigiostubs.c
@@ -45,26 +45,3 @@ xf86RemoveSIGIOHandler(int fd)
 {
     return 0;
 }
-
-int
-xf86BlockSIGIO(void)
-{
-    return 0;
-}
-
-void
-xf86UnblockSIGIO(int wasset)
-{
-}
-
-void
-xf86AssertBlockedSIGIO(char *where)
-{
-}
-
-/* XXX This is a quick hack for the benefit of xf86SetSilkenMouse() */
-Bool
-xf86SIGIOSupported()
-{
-    return FALSE;
-}
diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h
index fa3ff0e..99ca902 100644
--- a/hw/xfree86/os-support/xf86_OSproc.h
+++ b/hw/xfree86/os-support/xf86_OSproc.h
@@ -169,10 +169,6 @@ extern _X_EXPORT Bool xf86GARTCloseScreen(int screenNum);
 extern _X_EXPORT int xf86InstallSIGIOHandler(int fd, void (*f) (int, void *),
                                              void *);
 extern _X_EXPORT int xf86RemoveSIGIOHandler(int fd);
-extern _X_EXPORT int xf86BlockSIGIO(void);
-extern _X_EXPORT void xf86UnblockSIGIO(int);
-extern _X_EXPORT void xf86AssertBlockedSIGIO(char *);
-extern _X_EXPORT Bool xf86SIGIOSupported(void);
 
 #ifdef XF86_OS_PRIVS
 typedef void (*PMClose) (void);
diff --git a/include/input.h b/include/input.h
index cfdea2a..9069a1c 100644
--- a/include/input.h
+++ b/include/input.h
@@ -714,4 +714,13 @@ extern _X_HIDDEN void input_constrain_cursor(DeviceIntPtr pDev, ScreenPtr screen
                                              int *out_x, int *out_y,
                                              int *nevents, InternalEvent* events);
 
+static inline void input_lock(void) {
+}
+
+static inline void input_unlock(void) {
+}
+
+static inline void input_force_unlock(void) {
+}
+
 #endif                          /* INPUT_H */
diff --git a/include/os.h b/include/os.h
index 461d5d6..e9b3709 100644
--- a/include/os.h
+++ b/include/os.h
@@ -336,12 +336,6 @@ OsBlockSignals(void);
 extern _X_EXPORT void
 OsReleaseSignals(void);
 
-extern _X_EXPORT int
-OsBlockSIGIO(void);
-
-extern _X_EXPORT void
-OsReleaseSIGIO(void);
-
 extern void
 OsResetSignals(void);
 
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 7c03126..63dc5b3 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -127,9 +127,6 @@
 /* Path to text files containing PCI IDs */
 #undef PCI_TXT_IDS_PATH
 
-/* Use SIGIO handlers for input device events by default */
-#undef USE_SIGIO_BY_DEFAULT
-
 /* Build with libdrm support */
 #undef WITH_LIBDRM
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 01812bd..8fbe6c3 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -145,10 +145,10 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
 
     n_enqueued = mieqNumEnqueued(eventQueue);
 
-    /* We block signals, so an mieqEnqueue triggered by SIGIO does not
+    /* We lock input, so an mieqEnqueue does not
      * write to our queue as we are modifying it.
      */
-    OsBlockSignals();
+    input_lock();
 
     /* First copy the existing events */
     first_hunk = eventQueue->nevents - eventQueue->head;
@@ -181,7 +181,7 @@ mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
     free(eventQueue->events);
     eventQueue->events = new_events;
 
-    OsReleaseSignals();
+    input_unlock();
     return TRUE;
 }
 
diff --git a/mi/mipointer.c b/mi/mipointer.c
index caa7a9f..3f6252d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -750,7 +750,7 @@ miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
                                POINTER_SCREEN | POINTER_ABSOLUTE |
                                POINTER_NORAW, &mask);
 
-    OsBlockSignals();
+    input_lock();
 #ifdef XQUARTZ
     darwinEvents_lock();
 #endif
@@ -759,5 +759,5 @@ miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 #ifdef XQUARTZ
     darwinEvents_unlock();
 #endif
-    OsReleaseSignals();
+    input_unlock();
 }
diff --git a/os/utils.c b/os/utils.c
index e48d9f8..db875c1 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1304,9 +1304,7 @@ OsBlockSignals(void)
     if (BlockedSignalCount++ == 0) {
         sigset_t set;
 
-#ifdef SIGIO
-        OsBlockSIGIO();
-#endif
+        input_lock();
         sigemptyset(&set);
         sigaddset(&set, SIGALRM);
         sigaddset(&set, SIGVTALRM);
@@ -1322,57 +1320,13 @@ OsBlockSignals(void)
 #endif
 }
 
-#ifdef SIG_BLOCK
-static sig_atomic_t sigio_blocked;
-static sigset_t PreviousSigIOMask;
-#endif
-
-/**
- * returns zero if this call caused SIGIO to be blocked now, non-zero if it
- * was already blocked by a previous call to this function.
- */
-int
-OsBlockSIGIO(void)
-{
-#ifdef SIGIO
-#ifdef SIG_BLOCK
-    if (sigio_blocked++ == 0) {
-        sigset_t set;
-        int ret;
-
-        sigemptyset(&set);
-        sigaddset(&set, SIGIO);
-        sigprocmask(SIG_BLOCK, &set, &PreviousSigIOMask);
-        ret = sigismember(&PreviousSigIOMask, SIGIO);
-        return ret;
-    }
-#endif
-#endif
-    return 1;
-}
-
-void
-OsReleaseSIGIO(void)
-{
-#ifdef SIGIO
-#ifdef SIG_BLOCK
-    if (--sigio_blocked == 0) {
-        sigprocmask(SIG_SETMASK, &PreviousSigIOMask, 0);
-    } else if (sigio_blocked < 0) {
-        BUG_WARN(sigio_blocked < 0);
-        sigio_blocked = 0;
-    }
-#endif
-#endif
-}
-
 void
 OsReleaseSignals(void)
 {
 #ifdef SIG_BLOCK
     if (--BlockedSignalCount == 0) {
         sigprocmask(SIG_SETMASK, &PreviousSignalMask, 0);
-        OsReleaseSIGIO();
+        input_unlock();
     }
 #endif
 }
@@ -1383,10 +1337,7 @@ OsResetSignals(void)
 #ifdef SIG_BLOCK
     while (BlockedSignalCount > 0)
         OsReleaseSignals();
-#ifdef SIGIO
-    while (sigio_blocked > 0)
-        OsReleaseSIGIO();
-#endif
+    input_force_unlock();
 #endif
 }
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 9f13e26..f5e5468 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -5,7 +5,7 @@ if XORG
 # Tests that require at least some DDX functions in order to fully link
 # For now, requires xf86 ddx, could be adjusted to use another
 SUBDIRS += xi1 xi2
-noinst_PROGRAMS += xkb input xtest misc fixes xfree86 os signal-logging touch
+noinst_PROGRAMS += xkb input xtest misc fixes xfree86 signal-logging touch
 if RES
 noinst_PROGRAMS += hashtabletest
 endif
diff --git a/test/os.c b/test/os.c
deleted file mode 100644
index d85dcff..0000000
--- a/test/os.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * Copyright © 2012 Red Hat, Inc.
- *
- *  Permission is hereby granted, free of charge, to any person obtaining a
- *  copy of this software and associated documentation files (the "Software"),
- *  to deal in the Software without restriction, including without limitation
- *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
- *  and/or sell copies of the Software, and to permit persons to whom the
- *  Software is furnished to do so, subject to the following conditions:
- *
- *  The above copyright notice and this permission notice (including the next
- *  paragraph) shall be included in all copies or substantial portions of the
- *  Software.
- *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- *  DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <signal.h>
-#include "os.h"
-
-static int last_signal = 0;
-static int expect_signal = 0;
-
-static void sighandler(int signal)
-{
-    assert(expect_signal);
-    expect_signal = 0;
-    if (!last_signal)
-        raise(signal);
-    OsBlockSignals();
-    OsReleaseSignals();
-    last_signal = 1;
-    expect_signal = 1;
-}
-
-static int
-sig_is_blocked(int sig)
-{
-    sigset_t current;
-
-    sigemptyset(&current);
-    assert(sigprocmask(SIG_BLOCK, NULL, &current) == 0);
-    return sigismember(&current, sig);
-}
-
-static void block_sigio_test(void)
-{
-#ifdef SIG_BLOCK
-    sigset_t current;
-
-    sigemptyset(&current);
-    assert(!sig_is_blocked(SIGIO));
-
-    /* block once */
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* block twice, nested */
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* block all */
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* block all nested */
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* mix the two */
-    /* ABBA */
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* ABAB */
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* BAAB */
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(!sig_is_blocked(SIGIO));
-
-    /* BABA */
-    OsBlockSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsBlockSignals();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSIGIO();
-    assert(sig_is_blocked(SIGIO));
-    OsReleaseSignals();
-    assert(!sig_is_blocked(SIGIO));
-#endif
-}
-
-static void block_sigio_test_nested(void)
-{
-#ifdef SIG_BLOCK
-    /* Check for bug releasing SIGIO during SIGIO signal handling.
-       test case:
-           raise signal
-           → in signal handler:
-                raise signal
-                OsBlockSignals()
-                OsReleaseSignals()
-                tail guard
-       tail guard must be hit.
-     */
-    void (*old_handler)(int);
-    old_handler = OsSignal(SIGIO, sighandler);
-    expect_signal = 1;
-    assert(raise(SIGIO) == 0);
-    assert(OsSignal(SIGIO, old_handler) == sighandler);
-#endif
-}
-
-int
-main(int argc, char **argv)
-{
-    block_sigio_test();
-    block_sigio_test_nested();
-    return 0;
-}
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index aeb702c..afe5edf 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1526,7 +1526,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
         return;
 
     events = InitEventList(GetMaximumEventsNum() + 1);
-    OsBlockSignals();
+    input_lock();
     pScreen = miPointerGetScreen(ptr);
     saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
     nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
@@ -1534,7 +1534,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
         UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
                          &nevents);
     miPointerSetWaitForUpdate(pScreen, saveWait);
-    OsReleaseSignals();
+    input_unlock();
 
     for (i = 0; i < nevents; i++)
         mieqProcessDeviceEvent(ptr, &events[i], NULL);
commit 8cf832c288dec13cbf3c25478a8ccef52d61f3db
Author: Keith Packard <keithp at keithp.com>
Date:   Mon May 16 21:28:48 2016 -0500

    kdrive: Remove unneeded AddEnabledDevice/RemoveEnabledDevice calls
    
    kdrive uses the NotifyFd interface, which handles all of the necessary
    fd configuration in the OS layer. Having it also use the old
    EnableDevice interfaces is incorrect.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 52be7ad..64541a3 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -185,7 +185,6 @@ KdAddFd(int fd, int i)
     kdnFds++;
     fcntl(fd, F_SETOWN, getpid());
     KdNonBlockFd(fd);
-    AddEnabledDevice(fd);
     SetNotifyFd(fd, KdNotifyFd, X_NOTIFY_READ, (void *) (intptr_t) i);
     memset(&act, '\0', sizeof act);
     act.sa_handler = KdSigio;
@@ -205,7 +204,6 @@ KdRemoveFd(int fd)
     int flags;
 
     kdnFds--;
-    RemoveEnabledDevice(fd);
     RemoveNotifyFd(fd);
     flags = fcntl(fd, F_GETFL);
     flags &= ~(FASYNC | NOBLOCK);


More information about the xorg-commit mailing list