[PATCH libX11] config: Add an option to initialize threads by default.

Rami Ylimäki rami.ylimaki at vincit.fi
Mon Jan 31 02:46:56 PST 2011

It's sometimes impossible to know in advance whether an X client is
using Xlib from multiple threads or not. For example, there could be
some generic X client that acts as a plugin container. Plugins could
be loaded to the container at runtime, but the container doesn't know
whether the plugins are using Xlib from a separate thread or not.

This change makes it possible to guard a system against a missing
XInitThreads call in X clients. One might argue that this is a client
problem and that all X clients should call XInitThreads if it's
possible that they could use Xlib from multiple threads. However,
experience has shown that it's just too easy for developers to
overlook the need for this call.

Enabling thread safety by default causes a performance regression,
because even single threaded applications would start to lock data
structures. However, the performance regression is only noticeable in
a theoretical worst case situation. In realistic use cases the
overhead from unnecessary locking can't be seen. Relative x11perf
results showing the amount of regression for worst case and some
common operations are shown below.

enabled disabled Operation
------- -------- ---------
  1.00     1.00  Copy 10x10 from window to window
  1.00     1.00  Copy 500x500 from window to window
  1.00     2.68  X protocol NoOperation

Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
 configure.ac  |   36 ++++++++++++++++++++++++++++++++++++
 src/locking.c |   10 ++++++++++
 2 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/configure.ac b/configure.ac
index 40d032d..27ed595 100644
--- a/configure.ac
+++ b/configure.ac
@@ -270,6 +270,37 @@ AC_ARG_ENABLE(xthreads,
                 [Disable Xlib support for Multithreading]),
+dnl Check if the user wants XInitThreads to be called by default on
+dnl library initialization.
+        init_xthreads,
+        AC_HELP_STRING(
+                [--enable-init-xthreads],
+                [Call XInitThreads on library initialization]),
+        [init_xthreads=$enableval],
+        [init_xthreads=no])
+dnl Check if XInitThreads can be called by default on library
+dnl initialization. The following conditions must be true for that.
+dnl - Option --enable-xthreads is given.
+dnl - Option --enable-init-xthreads is given.
+dnl - Compiler is GCC.
+dnl - GCC supports library contructors.
+if test "x$xthreads" = xyes && test "x$init_xthreads" = xyes && test "x$GCC" = xyes ; then
+   dnl Set warnings as errors so that GCC fails if the attribute is
+   dnl not supported.
+   old_CFLAGS="$CFLAGS"
+   CFLAGS="-Werror"
+   dnl Check if GCC recognizes constructor attribute.
+           [ void __attribute__((constructor)) test(void) {}; ],
+           init_xthreads=yes,
+           init_xthreads=no)
+   dnl Restore flags.
+   CFLAGS="$old_CFLAGS"
 AC_CHECK_LIB(c, getpwuid_r, [mtsafeapi="yes"], [mtsafeapi="no"])
 case x$xthreads in
@@ -279,6 +310,10 @@ xyes)
 	AC_DEFINE(XUSE_MTSAFE_API,1,[Whether libX11 needs to use MT safe API's])
+	if test x$init_xthreads = xyes
+	then
+	AC_DEFINE(INIT_XTHREADS,1,[Whether XInitThreads is called on library initialization])
+	fi
@@ -480,6 +515,7 @@ echo " Loadable xcursor library support:        "$XLIB_LOADABLE_XCURSOR
 echo " Threading support:                       "$xthreads
 echo " Use Threads safe API:                    "$mtsafeapi
 echo " Threads stubs in libX11:                 "$thrstubs
+echo " Threads initialized by default:          "$init_xthreads
 echo " XCMS:                                    "$XCMS
 echo " Internationalization support:            "$XLOCALE
 echo " XF86BigFont support:                     "$XF86BIGFONT
diff --git a/src/locking.c b/src/locking.c
index 4f9a40f..7673a20 100644
--- a/src/locking.c
+++ b/src/locking.c
@@ -615,6 +615,16 @@ Status XInitThreads(void)
     return 1;
+/** Initialize threads by default when Xlib is loaded. */
+static void __attribute__((constructor)) XInitLib(void)
+    if (!XInitThreads())
+        exit(1);
+#endif /* INIT_XTHREADS*/
 #else /* XTHREADS */
 Status XInitThreads(void)

More information about the xorg-devel mailing list