--- /dev/null
+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.
--- /dev/null
+#
+# 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.
+#
+
+SUBDIRS = src test
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xshmfence.pc
+
+EXTRA_DIST = xshmfence.pc.in ChangeLog
+MAINTAINERCLEANFILES = ChangeLog
+
+.PHONY: ChangeLog
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog
+
+if LINT
+lint:
+ (cd src && $(MAKE) $(MFLAGS) lint)
+endif LINT
--- /dev/null
+libxshmfence - Shared memory 'SyncFence' synchronization primitive
+
+This library offers a CPU-based synchronization primitive compatible
+with the X SyncFence objects that can be shared between processes
+using file descriptor passing.
+
+There are two underlying implementations:
+
+ 1) On Linux, the library uses futexes
+
+ 2) On other systems, the library uses posix mutexes and condition
+ variables.
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+ http://lists.freedesktop.org/mailman/listinfo/xorg
+
+Please submit bug reports to the Xorg bugzilla:
+
+ https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+The master development code repository can be found at:
+
+ git://anongit.freedesktop.org/git/xorg/lib/libxshmfence
+
+ http://cgit.freedesktop.org/xorg/lib/libxshmfence
+
+For patch submission instructions, see:
+
+ http://www.x.org/wiki/Development/Documentation/SubmittingPatches
+
+For more information on the git code manager, see:
+
+ http://wiki.x.org/wiki/GitPage
+
--- /dev/null
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
--- /dev/null
+dnl
+dnl Copyright © 2013 Keith Packard
+dnl
+dnl Permission to use, copy, modify, distribute, and sell this software and its
+dnl documentation for any purpose is hereby granted without fee, provided that
+dnl the above copyright notice appear in all copies and that both that copyright
+dnl notice and this permission notice appear in supporting documentation, and
+dnl that the name of the copyright holders not be used in advertising or
+dnl publicity pertaining to distribution of the software without specific,
+dnl written prior permission. The copyright holders make no representations
+dnl about the suitability of this software for any purpose. It is provided "as
+dnl is" without express or implied warranty.
+dnl
+dnl THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+dnl EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+dnl OF THIS SOFTWARE.
+dnl
+dnl
+dnl Process this file with autoconf to create configure.
+
+AC_PREREQ([2.60])
+AC_INIT([libxshmfence], [1.1],
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libxshmfence])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+# Initialize libtool
+AC_PROG_LIBTOOL
+
+# Require xorg-macros: XORG_DEFAULT_OPTIONS, XORG_WITH_LINT
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.3 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.3)
+XORG_DEFAULT_OPTIONS
+
+dnl Allow checking code with lint, sparse, etc.
+XORG_WITH_LINT
+LINT_FLAGS="${LINT_FLAGS} ${FONTENC_CFLAGS}"
+
+
+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])
+
+PKG_CHECK_MODULES(XPROTO, xproto)
+
+AC_SUBST([XPROTO_CFLAGS])
+
+CFLAGS="$CFLAGS $XPROTO_CFLAGS"
+
+AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symbol visibility (default: auto)]),
+ [SYMBOL_VISIBILITY=$enableval],
+ [SYMBOL_VISIBILITY=auto])
+
+dnl ==================================================================
+dnl symbol visibility
+symbol_visibility=
+have_visibility=disabled
+if test x$SYMBOL_VISIBILITY != xno; then
+ AC_MSG_CHECKING(for symbol visibility support)
+ if test x$GCC = xyes; then
+ VISIBILITY_CFLAGS="-fvisibility=hidden"
+ else
+ if test x$SUNCC = xyes; then
+ VISIBILITY_CFLAGS="-xldscope=hidden"
+ else
+ have_visibility=no
+ fi
+ fi
+ if test x$have_visibility != xno; then
+ AC_TRY_COMPILE(
+ [#include <X11/Xfuncproto.h>
+ extern _X_HIDDEN int hidden_int;
+ extern _X_EXPORT int public_int;
+ extern _X_HIDDEN int hidden_int_func(void);
+ extern _X_EXPORT int public_int_func(void);],
+ [],
+ have_visibility=yes,
+ have_visibility=no)
+ fi
+ AC_MSG_RESULT([$have_visibility])
+ if test x$have_visibility != xno; then
+ symbol_visibility=$VISIBILITY_CFLAGS
+ CFLAGS="$CFLAGS $VISIBILITY_CFLAGS"
+ fi
+fi
+
+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])
+
+shmdirs="/run/shm /var/tmp /tmp"
+
+case x"$with_shared_memory_dir" in
+xyes)
+ for dir in $shmdirs; do
+ case x"$with_shared_memory_dir" in
+ xyes)
+ echo Checking temp dir "$dir"
+ if test -d "$dir"; then
+ with_shared_memory_dir="$dir"
+ fi
+ ;;
+ esac
+ done
+ ;;
+x/*)
+ ;;
+xno)
+ ;;
+*)
+ AC_MSG_ERROR([Invalid directory specified for --with-shared-memory-dir: $with_shared_memory_dir])
+ ;;
+esac
+
+case x"$with_shared_memory_dir" in
+xyes)
+ AC_MSG_ERROR([No directory found for shared memory temp files.])
+ ;;
+xno)
+ ;;
+*)
+ AC_DEFINE_UNQUOTED(SHMDIR, ["$with_shared_memory_dir"], [Directory for shared memory temp files])
+ ;;
+esac
+
+AC_CONFIG_FILES([Makefile
+ src/Makefile
+ test/Makefile
+ xshmfence.pc])
+AC_OUTPUT
--- /dev/null
+libxshmfence
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+Name: libXshmfence
+Version: 1.1
+Release: 1
+License: MIT
+Summary: X Fixes library
+Url: http://www.x.org
+Group: Graphics/X Window System
+Source: %{name}-%{version}.tar.bz2
+Source1001: libXshmfence.manifest
+
+BuildRequires: pkgconfig(xorg-macros)
+BuildRequires: pkgconfig(xproto)
+
+%description
+X Fixes library.
+
+%package devel
+Summary: Development files for %{name}
+Group: Development/Libraries
+Requires: %{name} = %{version}
+Requires: pkgconfig
+
+%description devel
+libxshmfence development package
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+%autogen --disable-static --with-shared-memory-dir=/tmp
+make %{?_smp_mflags}
+
+%install
+mkdir -p %{buildroot}/usr/share/license
+cp -af COPYING %{buildroot}/usr/share/license/%{name}
+%make_install
+%remove_docs
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libxshmfence.so.1
+%{_libdir}/libxshmfence.so.1.0.0
+
+%files devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+/usr/share/license/%{name}
+%{_includedir}/X11/xshmfence.h
+%{_libdir}/libxshmfence.so
+%{_libdir}/pkgconfig/xshmfence.pc
--- /dev/null
+lib_LTLIBRARIES = libxshmfence.la
+
+if PTHREAD
+PTHREAD_SOURCES=xshmfence_pthread.c xshmfence_pthread.h
+endif
+
+if FUTEX
+FUTEX_SOURCES=xshmfence_futex.c xshmfence_futex.h
+endif
+
+libxshmfence_la_SOURCES = \
+ xshmfenceint.h \
+ xshmfence_alloc.c \
+ $(PTHREAD_SOURCES) \
+ $(FUTEX_SOURCES)
+
+AM_CFLAGS = $(CWARNFLAGS)
+
+libxshmfence_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libxshmfence_la_LIBADD = @PTHREAD_LIBS@
+
+libxshmfenceincludedir = $(includedir)/X11
+libxshmfenceinclude_HEADERS = xshmfence.h
+
+if LINT
+ALL_LINT_FLAGS=$(LINT_FLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS)
+
+lint:
+ $(LINT) $(ALL_LINT_FLAGS) $(libxshmfence_la_SOURCES) $(LIBS)
+endif LINT
--- /dev/null
+/*
+ * 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_H_
+#define _XSHMFENCE_H_
+
+#include <X11/Xfuncproto.h>
+
+#define HAVE_STRUCT_XSHMFENCE 1
+
+struct xshmfence;
+
+_X_EXPORT int
+xshmfence_trigger(struct xshmfence *f);
+
+_X_EXPORT int
+xshmfence_await(struct xshmfence *f);
+
+_X_EXPORT int
+xshmfence_query(struct xshmfence *f);
+
+_X_EXPORT void
+xshmfence_reset(struct xshmfence *f);
+
+_X_EXPORT int
+xshmfence_alloc_shm(void);
+
+_X_EXPORT struct xshmfence *
+xshmfence_map_shm(int fd);
+
+_X_EXPORT void
+xshmfence_unmap_shm(struct xshmfence *f);
+
+#endif /* _XSHMFENCE_H_ */
--- /dev/null
+/*
+ * 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_alloc_shm:
+ *
+ * Allocates a shared memory object large enough to hold a single
+ * fence.
+ *
+ * Return value: the file descriptor of the object, or -1 on failure
+ * (in which case, errno will be set as appropriate).
+ **/
+int
+xshmfence_alloc_shm(void)
+{
+ char template[] = SHMDIR "/shmfd-XXXXXX";
+ int fd;
+
+#ifdef O_TMPFILE
+ fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666);
+ if (fd < 0)
+#endif
+ {
+ fd = mkstemp(template);
+ if (fd < 0)
+ return fd;
+ unlink(template);
+ }
+ ftruncate(fd, sizeof (struct xshmfence));
+ xshmfence_init(fd);
+ return fd;
+}
+
+/**
+ * xshmfence_map_shm:
+ *
+ * Map a shared memory fence referenced by @fd.
+ *
+ * Return value: the fence or NULL (in which case, errno will be set
+ * as appropriate).
+ **/
+struct xshmfence *
+xshmfence_map_shm(int fd)
+{
+ struct xshmfence *addr;
+ addr = mmap (NULL, sizeof (struct xshmfence) , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (addr == MAP_FAILED) {
+ close (fd);
+ return 0;
+ }
+ return addr;
+}
+
+/**
+ * xshmfence_unmap_shm:
+ *
+ * Unap a shared memory fence @f.
+ **/
+void
+xshmfence_unmap_shm(struct xshmfence *f)
+{
+ munmap(f, sizeof (struct xshmfence));
+}
--- /dev/null
+/*
+ * 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)
+{
+ if (__sync_val_compare_and_swap(&f->v, 0, 1) == -1) {
+ atomic_store(&f->v, 1);
+ if (futex_wake(&f->v) < 0)
+ return -1;
+ }
+ 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)
+{
+ while (__sync_val_compare_and_swap(&f->v, 0, -1) != 1) {
+ if (futex_wait(&f->v, -1)) {
+ if (errno != EWOULDBLOCK)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * xshmfence_query:
+ * @f: An X fence
+ *
+ * Return value: 1 if @f is triggered, else returns 0.
+ **/
+int
+xshmfence_query(struct xshmfence *f)
+{
+ return atomic_fetch(&f->v) == 1;
+}
+
+/**
+ * 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)
+{
+ __sync_bool_compare_and_swap(&f->v, 1, 0);
+}
--- /dev/null
+/*
+ * 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_FUTEX_H_
+#define _XSHMFENCE_FUTEX_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <values.h>
+#include <linux/futex.h>
+#include <sys/time.h>
+#include <sys/syscall.h>
+
+static inline long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
+{
+ return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
+}
+
+static inline int futex_wake(int32_t *addr) {
+ return sys_futex(addr, FUTEX_WAKE, MAXINT, NULL, NULL, 0);
+}
+
+static inline int futex_wait(int32_t *addr, int32_t value) {
+ return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
+}
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+static inline void atomic_store(int32_t *f, int32_t v)
+{
+ barrier();
+ *f = v;
+ barrier();
+}
+
+static inline int32_t atomic_fetch(int32_t *a)
+{
+ int32_t v;
+ barrier();
+ v = *a;
+ barrier();
+ return v;
+}
+
+struct xshmfence {
+ int32_t v;
+};
+
+#define xshmfence_init(fd)
+
+#endif /* _XSHMFENCE_FUTEX_H_ */
--- /dev/null
+/*
+ * 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) {
+ 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);
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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 _XSHMFENCEINT_H_
+#define _XSHMFENCEINT_H_
+
+#include <stdlib.h>
+#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_ */
--- /dev/null
+check_PROGRAMS = xshmfence_test
+
+TESTS=$(check_PROGRAMS)
+
+xshmfence_test_SOURCES = xshmfence_test.c
+
+xshmfence_test_CFLAGS = -I$(top_srcdir)/src
+xshmfence_test_LDADD = $(top_builddir)/src/libxshmfence.la @PTHREAD_LIBS@
+
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <xshmfence.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define NCHILD 5 /* number of child processes to fork */
+#define NCHECK 10 /* number of times to signal the fence */
+
+/* Catch an alarm and bail
+ */
+static void
+sigalrm(int sig)
+{
+ write(2, "caught alarm\n", 13);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ struct xshmfence *x;
+ int i;
+ int c;
+ int pid;
+ int status;
+ int failed = 0;
+
+ /* Allocate a fence
+ */
+ fd = xshmfence_alloc_shm();
+ if (fd < 0) {
+ perror("xshmfence_alloc_shm");
+ exit(1);
+ }
+
+ /* fork NCHILD processes to wait for the fence
+ */
+ for (c = 0; c < NCHILD; c++) {
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ exit(1);
+ case 0:
+
+ /* Set an alarm to limit how long
+ * to wait
+ */
+ signal(SIGALRM, sigalrm);
+ alarm(10);
+
+ /* Map the fence
+ */
+ x = xshmfence_map_shm(fd);
+ if (!x) {
+ fprintf(stderr, "%6d: ", c);
+ perror("xshmfence_map_shm");
+ exit(1);
+ }
+
+ for (i = 0; i < NCHECK; i++) {
+
+ /* Verify that the fence is currently reset
+ */
+ if (xshmfence_query(x) != 0) {
+ fprintf(stderr, "%6d: query reset failed\n", c);
+ exit(1);
+ }
+
+ /* Wait for the fence
+ */
+ fprintf(stderr, "%6d: waiting\n", c);
+ if (xshmfence_await(x) < 0) {
+ fprintf(stderr, "%6d: ", c);
+ perror("xshmfence_await");
+ exit(1);
+ }
+
+ fprintf(stderr, "%6d: awoken\n", c);
+
+ /* Verify that the fence is currently triggered
+ */
+ if (xshmfence_query(x) == 0) {
+ fprintf(stderr, "%6d: query triggered failed\n", c);
+ exit(1);
+ }
+
+ usleep(10 * 1000);
+
+ /* Reset the fence
+ */
+ if (c == 0)
+ xshmfence_reset(x);
+
+ usleep(10 * 1000);
+ }
+ fprintf(stderr, "%6d: done\n", c);
+ exit(0);
+ }
+ }
+
+ /* Map the fence into the parent process
+ */
+ x = xshmfence_map_shm(fd);
+ if (!x) {
+ perror("xshmfence_map_shm");
+ exit(1);
+ }
+
+ for (i = 0; i < NCHECK; i++) {
+ usleep(100 * 1000);
+ fprintf(stderr, "trigger\n");
+
+ /* Verify that the fence is reset
+ */
+ if (xshmfence_query(x) != 0) {
+ fprintf(stderr, "query reset failed\n");
+ exit(1);
+ }
+
+ /* Trigger the fence
+ */
+ if (xshmfence_trigger(x) < 0) {
+ perror("xshmfence_trigger");
+ exit(1);
+ }
+
+ /* Verify that the fence is triggered
+ */
+ if (xshmfence_query(x) == 0) {
+ fprintf (stderr, "query triggered failed\n");
+ exit(1);
+ }
+
+ fprintf(stderr, "trigger done\n");
+ }
+
+ /* Reap all of the child processes
+ */
+ for (c = 0; c < NCHILD; c++) {
+ pid = wait(&status);
+ if (pid < 0) {
+ perror("wait");
+ exit(1);
+ }
+ fprintf(stderr, "child %d done %d\n", pid, status);
+ if (status)
+ failed++;
+ }
+ exit(failed);
+}
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: xshmfence
+Description: The X Shared Memory Fence Library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir} @XPROTO_CFLAGS@
+Libs: -L${libdir} -lxshmfence
+Libs.private: @PTHREAD_LIBS@