[PATCH 6/7] Provide pthread-based alternative implementation

Keith Packard keithp at keithp.com
Wed Nov 20 11:56:00 PST 2013


This uses pthread mutexes and condition variables instead of futexes.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 configure.ac            |  25 +++++++++
 src/Makefile.am         |  10 +++-
 src/xshmfence_pthread.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/xshmfence_pthread.h |  39 ++++++++++++++
 src/xshmfenceint.h      |   7 +++
 test/Makefile.am        |   2 +-
 xshmfence.pc.in         |   1 +
 7 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 src/xshmfence_pthread.c
 create mode 100644 src/xshmfence_pthread.h

diff --git a/configure.ac b/configure.ac
index ee09faf..0c8a325 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,31 @@ dnl
 dnl Locate a suitable tmp file system for creating shared memeory files
 dnl
 
+AC_ARG_ENABLE(futex,	AS_HELP_STRING([--enable-futex], [Enable futexes (default: auto)]),
+		[FUTEX=$enableval], [FUTEX=auto])
+
+if test "x$FUTEX" = "xauto"; then
+	AC_CHECK_HEADER([linux/futex.h], [FUTEX=yes], [FUTEX=no])
+fi
+
+if test "x$FUTEX" = "xyes"; then
+	PTHREAD=no
+	AC_DEFINE(HAVE_FUTEX,1,[Use futexes])
+else
+	PTHREAD=yes
+	AC_DEFINE(HAVE_PTHREAD,1,[Use pthread primitives])
+fi
+
+PTHREAD_LIBS=
+if test "x$PTHREAD" = "xyes"; then
+	AC_CHECK_LIB(pthread,pthread_create,[PTHREAD_LIBS=-lpthread],[PTHREAD_LIBS=])
+fi
+
+AC_SUBST([PTHREAD_LIBS])
+
+AM_CONDITIONAL([FUTEX], [test x"$FUTEX" = xyes])
+AM_CONDITIONAL([PTHREAD], [test x"$PTHREAD" = xyes])
+
 AC_ARG_WITH(shared-memory-dir, AS_HELP_STRING([--with-shared-memory-dir=PATH], [Path to directory in a world-writable temporary directory for anonymous shared memory (default: auto)]),
 [],
 [with_shared_memory_dir=yes])
diff --git a/src/Makefile.am b/src/Makefile.am
index d817326..cac6de5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,14 +1,22 @@
 lib_LTLIBRARIES = libxshmfence.la
 
+if PTHREAD
+PTHREAD_SOURCES=xshmfence_pthread.c
+endif
+
+if FUTEX
 FUTEX_SOURCES=xshmfence_futex.c
+endif
 
 libxshmfence_la_SOURCES = \
         xshmfence_alloc.c \
+	$(PTHREAD_SOURCES) \
 	$(FUTEX_SOURCES)
 
-noinst_HEADERS = xshmfence_futex.h xshmfenceint.h
+noinst_HEADERS = xshmfence_pthread.h xshmfence_futex.h xshmfenceint.h
 
 libxshmfence_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libxshmfence_la_LIBADD = @PTHREAD_LIBS@
 
 libxshmfenceincludedir = $(includedir)/X11
 libxshmfenceinclude_HEADERS = xshmfence.h
diff --git a/src/xshmfence_pthread.c b/src/xshmfence_pthread.c
new file mode 100644
index 0000000..6324b31
--- /dev/null
+++ b/src/xshmfence_pthread.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xshmfenceint.h"
+
+/**
+ * xshmfence_trigger:
+ * @f: An X fence
+ *
+ * Set @f to triggered, waking all waiters.
+ *
+ * Return value: 0 on success and -1 on error (in which case, errno
+ * will be set as appropriate).
+ **/
+int
+xshmfence_trigger(struct xshmfence *f) {
+    pthread_mutex_lock(&f->lock);
+    if (f->value == 0) {
+        f->value = 1;
+        if (f->waiting) {
+            f->waiting = 0;
+            pthread_cond_broadcast(&f->wakeup);
+        }
+    }
+    pthread_mutex_unlock(&f->lock);
+    return 0;
+}
+
+/**
+ * xshmfence_await:
+ * @f: An X fence
+ *
+ * Wait for @f to be triggered. If @f is already triggered, this
+ * function returns immediately.
+ *
+ * Return value: 0 on success and -1 on error (in which case, errno
+ * will be set as appropriate).
+ **/
+int
+xshmfence_await(struct xshmfence *f) {
+    int ret;
+    pthread_mutex_lock(&f->lock);
+    while (f->value == 0) {
+        f->waiting = 1;
+        pthread_cond_wait(&f->wakeup, &f->lock);
+    }
+    pthread_mutex_unlock(&f->lock);
+    return 0;
+}
+
+/**
+ * xshmfence_query:
+ * @f: An X fence
+ *
+ * Return value: 1 if @f is triggered, else returns 0.
+ **/
+int
+xshmfence_query(struct xshmfence *f) {
+    int value;
+
+    pthread_mutex_lock(&f->lock);
+    value = f->value;
+    pthread_mutex_unlock(&f->lock);
+    return value;
+}
+
+/**
+ * xshmfence_reset:
+ * @f: An X fence
+ *
+ * Reset @f to untriggered. If @f is already untriggered,
+ * this function has no effect.
+ **/
+void
+xshmfence_reset(struct xshmfence *f) {
+
+    pthread_mutex_lock(&f->lock);
+    f->value = 0;
+    pthread_mutex_unlock(&f->lock);
+}
+
+/**
+ * xshmfence_init:
+ * @fd: An fd for an X fence
+ *
+ * Initialize the fence when first allocated
+ **/
+
+void
+xshmfence_init(int fd)
+{
+    struct xshmfence *f = xshmfence_map_shm(fd);
+    pthread_mutexattr_t mutex_attr;
+    pthread_condattr_t cond_attr;
+
+    if (!f)
+        return;
+
+    pthread_mutexattr_init(&mutex_attr);
+    pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
+    pthread_mutex_init(&f->lock, &mutex_attr);
+
+    pthread_condattr_init(&cond_attr);
+    pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
+    pthread_cond_init(&f->wakeup, &cond_attr);
+    f->value = 0;
+    f->waiting = 0;
+    xshmfence_unmap_shm(f);
+}
diff --git a/src/xshmfence_pthread.h b/src/xshmfence_pthread.h
new file mode 100644
index 0000000..9d6b0c8
--- /dev/null
+++ b/src/xshmfence_pthread.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _XSHMFENCE_PTHREAD_H_
+#define _XSHMFENCE_PTHREAD_H_
+
+#include <pthread.h>
+#include <sys/types.h>
+
+struct xshmfence {
+    pthread_mutex_t lock;
+    pthread_cond_t  wakeup;
+    int             value;
+    int             waiting;
+};
+
+void
+xshmfence_init(int fd);
+
+#endif /* _XSHMFENCE_PTHREAD_H_ */
diff --git a/src/xshmfenceint.h b/src/xshmfenceint.h
index 3452a55..178cbdd 100644
--- a/src/xshmfenceint.h
+++ b/src/xshmfenceint.h
@@ -27,6 +27,13 @@
 #include <unistd.h>
 #include <sys/mman.h>
 #include "xshmfence.h"
+
+#if HAVE_FUTEX
 #include "xshmfence_futex.h"
+#endif
+
+#if HAVE_PTHREAD
+#include "xshmfence_pthread.h"
+#endif
 
 #endif /* _XSHMFENCEINT_H_ */
diff --git a/test/Makefile.am b/test/Makefile.am
index c67014a..57bf1ae 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -5,5 +5,5 @@ TESTS=$(check_PROGRAMS)
 xshmfence_test_SOURCES = xshmfence_test.c
 
 xshmfence_test_CFLAGS = -I$(top_srcdir)/src
-xshmfence_test_LDADD = $(top_builddir)/src/libxshmfence.la
+xshmfence_test_LDADD = $(top_builddir)/src/libxshmfence.la @PTHREAD_LIBS@
 
diff --git a/xshmfence.pc.in b/xshmfence.pc.in
index cfc1860..579af0b 100644
--- a/xshmfence.pc.in
+++ b/xshmfence.pc.in
@@ -8,3 +8,4 @@ Description: The X Shared Memory Fence Library
 Version: @PACKAGE_VERSION@
 Cflags: -I${includedir}
 Libs: -L${libdir} -lxshmfence
+Libs.private: @PTHREAD_LIBS@
-- 
1.8.4.2



More information about the xorg-devel mailing list