Blob Blame Raw
From 645de09fc84482a55b5234312027efd007e53d8c Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Sat, 7 Nov 2009 15:29:05 -0500
Subject: [PATCH] xfree86: Use SA_SIGINFO if available for SIGIO handlers

siginfo_t gives us the file descriptor that raised the signal directly,
so we don't need to select() for it.  This gets evdev event processing
down to exactly one syscall in the common case.

Signed-off-by: Adam Jackson <ajax@redhat.com>
---
 hw/xfree86/os-support/shared/sigio.c |   40 ++++++++++++++++++++++++++++-----
 1 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/hw/xfree86/os-support/shared/sigio.c b/hw/xfree86/os-support/shared/sigio.c
index aed5654..4f1ec55 100644
--- a/hw/xfree86/os-support/shared/sigio.c
+++ b/hw/xfree86/os-support/shared/sigio.c
@@ -95,12 +95,11 @@ static int		xf86SigIOMax;
 static int		xf86SigIOMaxFd;
 static fd_set		xf86SigIOMask;
 
-/*
- * SIGIO gives no way of discovering which fd signalled, select
- * to discover
- */
+#ifndef SA_SIGINFO
+
+/* plain signals have no way of discovering which fd signalled. */
 static void
-xf86SIGIO (int sig)
+sigio_handler (int sig)
 {
     int	    i;
     fd_set  ready;
@@ -126,6 +125,27 @@ xf86SIGIO (int sig)
     errno = save_errno;
 }
 
+#else /* have SA_SIGINFO */
+
+/* siginfo passes the triggering fd in, no need to select() */
+static void
+sigio_sigaction(int sig, siginfo_t *si, void *ctx)
+{
+    int i;
+    int save_errno = errno;
+
+    for (i = 0; i < MAX_FUNCS; i++) {
+        if (xf86SigIOFuncs[i].f && xf86SigIOFuncs[i].fd == si->si_fd) {
+            (*xf86SigIOFuncs[i].f)(si->si_fd, xf86SigIOFuncs[i].closure);
+            break;
+        }
+    }
+
+    errno = save_errno;
+}
+
+#endif
+
 static int
 xf86IsPipe (int fd)
 {
@@ -164,6 +184,9 @@ xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *closure)
 		    xf86Msg(X_WARNING, "fcntl(%d, F_SETOWN): %s\n",
 			    fd, strerror(errno));
 		} else {
+#ifdef SA_SIGINFO
+                    fcntl(fd, F_SETSIG, SIGIO);
+#endif
 		    installed = TRUE;
 		}
 	    }
@@ -184,8 +207,13 @@ xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *closure)
 	    }
 	    sigemptyset(&sa.sa_mask);
 	    sigaddset(&sa.sa_mask, SIGIO);
+#ifndef SA_SIGINFO
 	    sa.sa_flags   = 0;
-	    sa.sa_handler = xf86SIGIO;
+	    sa.sa_handler = sigio_handler;
+#else
+            sa.sa_flags     = SA_SIGINFO;
+            sa.sa_sigaction = sigio_sigaction;
+#endif
 	    sigaction(SIGIO, &sa, &osa);
 	    xf86SigIOFuncs[i].fd = fd;
 	    xf86SigIOFuncs[i].closure = closure;
-- 
1.6.5.rc2