Mark Kettenis <[email protected]> writes:

> Ugh.  Exporting global variables as part of the ABI is generally not
> such a good idea.  Perhaps it is better to use functions to acquire
> and release the input mutex instead?

Yeah, the mutex isn't exactly performance critical.

> Also, using TLS (i.e. __thread variables) isn't portable.  That
> mechanism certainly isn't supported by all platforms supported by
> Xorg.

Ok, I've added support for pthread_setspecific/pthread_getspecific and
made sure that works; I cannot test the autoconf bits (other than
verifying that if I misspell '__thread' as '__tread' it fails as
expected).

Here's just the diff from the existing patch; I'll squash this in if it
looks reasonable.

From ef34d763145deb636c771b9c7bd3fb1bcbaa08ad Mon Sep 17 00:00:00 2001
From: Keith Packard <[email protected]>
Date: Thu, 10 Dec 2015 11:36:34 -0800
Subject: [PATCH xserver 05/22] Disable input thread code with
 --disable-input-thread. pthread_getspecific support.

This is a pair of changes to the threaded input code which should be
merged with that patch; I'm publishing it separately for review before
doing that.

The first change is to respect the --disable-input-thread
configuration option and disable all of the threaded input code in
that case. What remains are just stubs that get input drivers to work
in this situation without changing the API or ABI.

The second is to add a configure check for compiler '__thread' support
and to use pthread_setspecific/pthread_getspecific calls where it
doesn't work. I have no way of testing the configuration checks to
make sure that matches what systems lacking support for __thread do,
but I did test the setspecific code to make sure it works correctly.

Signed-off-by: Keith Packard <[email protected]>
---
 configure.ac            |  17 +++++++
 hw/xfree86/sdksyms.sh   |   4 --
 include/dix-config.h.in |   6 +++
 include/input.h         |  23 ++-------
 os/inputthread.c        | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 150 insertions(+), 24 deletions(-)

diff --git a/configure.ac b/configure.ac
index bc15581..f7dccfc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -821,6 +821,21 @@ 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_LANG_PUSH([C])
+AC_MSG_CHECKING([for __thread variables...])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[__thread int x;]],
+                                   [[x = 0;]])],
+                  [HAVE_THREAD_VARIABLES="yes"],
+		  [HAVE_THREAD_VARIABLES="no"])
+AC_MSG_RESULT([$HAVE_THREAD_VARIABLES])
+AC_LANG_POP([C])
+
+case x"$HAVE_THREAD_VARIABLES" in
+xyes)
+	AC_DEFINE(HAVE_THREAD_VARIABLES, 1, [Thread local variables with __thread attribute])
+	;;
+esac
+
 # input thread setup
 case $host_os in
 linux*)
@@ -828,6 +843,7 @@ linux*)
 *)
 	THREAD_DEFAULT=no ;;
 esac
+
 AC_ARG_ENABLE(input-thread, AS_HELP_STRING([--enable-input-thread],
 	     [Enable input threads]),
 	     [INPUTTHREAD=$enableval], [INPUTTHREAD=$THREAD_DEFAULT])
@@ -848,6 +864,7 @@ if test "x$INPUTTHREAD" = "xyes" ; then
     esac
     SYS_LIBS="$SYS_LIBS $THREAD_LIB"
     CFLAGS="$CFLAGS $THREAD_CFLAGS"
+    AC_DEFINE(INPUTTHREAD, 1, [Use a separate input thread])
 fi
 
 REQUIRED_MODULES="$FIXESPROTO $DAMAGEPROTO $XCMISCPROTO $XTRANS $BIGREQSPROTO $SDK_REQUIRED_MODULES"
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index fb2eaa1..5391b72 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -344,10 +344,6 @@ BEGIN {
            n = 1;
         }
 
-	if ($n ~ /__thread/) {
-	   next;
-	}
-
 	# skip attribute, if any
 	while ($n ~ /^(__attribute__|__global)/ ||
 	    # skip modifiers, if any
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 940d2b7..52449c2 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -521,4 +521,10 @@
 /* Have setitimer support */
 #undef HAVE_SETITIMER
 
+/* Have __thread variables */
+#undef HAVE_THREAD_VARIABLES
+
+/* Use input thread */
+#undef INPUTTHREAD
+
 #endif /* _DIX_CONFIG_H_ */
diff --git a/include/input.h b/include/input.h
index 01ea4d9..afd066f 100644
--- a/include/input.h
+++ b/include/input.h
@@ -713,26 +713,9 @@ extern _X_HIDDEN void input_constrain_cursor(DeviceIntPtr pDev, ScreenPtr screen
                                              int *out_x, int *out_y,
                                              int *nevents, InternalEvent* events);
 
-extern _X_EXPORT pthread_mutex_t input_mutex;
-extern _X_EXPORT __thread int input_mutex_count;
-
-static inline void input_lock(void) {
-    if (input_mutex_count++ == 0)
-        pthread_mutex_lock(&input_mutex);
-}
-
-static inline void input_unlock(void) {
-    if (--input_mutex_count == 0)
-        pthread_mutex_unlock(&input_mutex);
-    assert(input_mutex_count >= 0);
-}
-
-static inline void input_force_unlock(void) {
-    if (input_mutex_count > 0) {
-        input_mutex_count = 0;
-        pthread_mutex_unlock(&input_mutex);
-    }
-}
+extern _X_EXPORT void input_lock(void);
+extern _X_EXPORT void input_unlock(void);
+extern _X_EXPORT void input_force_unlock(void);
 
 extern void InputThreadPreInit(void);
 extern void InputThreadInit(void);
diff --git a/os/inputthread.c b/os/inputthread.c
index 7c87e87..3209898 100644
--- a/os/inputthread.c
+++ b/os/inputthread.c
@@ -40,6 +40,8 @@
 #include "opaque.h"
 #include "osdep.h"
 
+#if INPUTTHREAD
+
 Bool InputThreadEnable = TRUE;
 
 /**
@@ -377,3 +379,125 @@ InputThreadFini(void)
     free(inputThreadInfo);
     inputThreadInfo = NULL;
 }
+
+static pthread_mutex_t input_mutex;
+
+#if HAVE_THREAD_VARIABLES
+
+static __thread int input_mutex_count;
+
+static inline Bool input_mutex_count_up(void) {
+    return input_mutex_count++ == 0;
+}
+
+static inline Bool input_mutex_count_down(void) {
+    assert(input_mutex_count > 0);
+    return --input_mutex_count == 0;
+}
+
+static inline Bool input_mutex_count_reset(void) {
+    if (input_mutex_count > 0) {
+        input_mutex_count = 0;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+#else
+
+static pthread_once_t   input_count_is_initialized;
+static pthread_key_t    input_count_key;
+
+static void
+input_count_initialize(void)
+{
+    if (pthread_key_create(&input_count_key, NULL) != 0)
+        FatalError("input thread count key");
+}
+
+static inline int input_mutex_count_get(void) {
+    void        *p;
+    p = pthread_getspecific(input_count_key);
+    return (int) (intptr_t) p;
+}
+
+static inline void input_mutex_count_put(int count) {
+    if (pthread_setspecific(input_count_key, (void *) (intptr_t) count) != 0)
+        FatalError("input thread set count");
+}
+
+static inline Bool input_mutex_count_up(void) {
+    int count;
+    pthread_once(&input_count_is_initialized, input_count_initialize);
+
+    count = input_mutex_count_get();
+    ++count;
+    input_mutex_count_put(count);
+    return count == 1;
+}
+
+static inline Bool input_mutex_count_down(void) {
+    int count;
+    pthread_once(&input_count_is_initialized, input_count_initialize);
+
+    count = input_mutex_count_get();
+    --count;
+    input_mutex_count_put(count);
+    return count == 0;
+}
+
+static inline Bool input_mutex_count_reset(void) {
+    int count;
+    pthread_once(&input_count_is_initialized, input_count_initialize);
+
+    count = input_mutex_count_get();
+    if (count > 0) {
+        input_mutex_count_put(0);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+#endif
+
+void input_lock(void) {
+    if (input_mutex_count_up())
+        pthread_mutex_lock(&input_mutex);
+}
+
+void input_unlock(void) {
+    if (input_mutex_count_down())
+        pthread_mutex_unlock(&input_mutex);
+}
+
+void input_force_unlock(void) {
+    if (input_mutex_count_reset())
+        pthread_mutex_unlock(&input_mutex);
+}
+
+#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;
+}
+
+#endif
-- 
2.6.2


-- 
-keith

Attachment: signature.asc
Description: PGP signature

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to