Compat futex
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Thu, 8 Oct 2009 21:36:31 +0000 (17:36 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Thu, 8 Oct 2009 21:36:31 +0000 (17:36 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Makefile.am
compat_futex.c [new file with mode: 0644]
configure.ac
urcu-pointer.c
urcu/arch_ppc.h
urcu/arch_s390.h
urcu/arch_x86.h
urcu/config.h.in [new file with mode: 0644]
urcu/urcu-futex.h [new file with mode: 0644]

index df67b1e3fef0fd8c8f7ce71d37b7f0a994a49987..e4858340f66514f8298cb16149810437cd59709d 100644 (file)
@@ -37,7 +37,7 @@ liburcu_defer_la_SOURCES = urcu-defer.c $(COMPAT)
 
 liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c $(COMPAT)
 
 
 liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c $(COMPAT)
 
-*.h *.c: urcu/arch.h urcu/uatomic_arch.h
+$(top_srcdir)/*.h $(top_srcdir)/*.c: urcu/arch.h urcu/uatomic_arch.h
 
 urcu/arch.h: $(top_srcdir)/urcu/arch_@ARCHTYPE@.h
        $(MKDIR_P) $(top_builddir)/urcu
 
 urcu/arch.h: $(top_srcdir)/urcu/arch_@ARCHTYPE@.h
        $(MKDIR_P) $(top_builddir)/urcu
diff --git a/compat_futex.c b/compat_futex.c
new file mode 100644 (file)
index 0000000..27fc66b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * compat_futex.c
+ *
+ * Userspace RCU library - sys_futex compatibility code
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <signal.h>
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <urcu/arch.h>
+#include <urcu/urcu-futex.h>
+
+static pthread_mutex_t compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t compat_futex_cond = PTHREAD_COND_INITIALIZER;
+
+/*
+ * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
+ * For now, timeout, uaddr2 and val3 are unused.
+ * Waiter will relinquish the CPU until woken up.
+ */
+
+int compat_futex_noasync(int *uaddr, int op, int val,
+       const struct timespec *timeout, int *uaddr2, int val3)
+{
+       int ret, i, gret = 0;
+
+       /*
+        * Check if NULL. Don't let users expect that they are taken into
+        * account. 
+        */
+       assert(!timeout);
+       assert(!uaddr2);
+       assert(!val3);
+
+       /*
+        * memory barriers to serialize with the previous uaddr modification.
+        */
+       smp_mb();
+
+       ret = pthread_mutex_lock(&compat_futex_lock);
+       assert(!ret);
+       switch (op) {
+       case FUTEX_WAIT:
+               if (*uaddr != val)
+                       goto end;
+               pthread_cond_wait(&compat_futex_cond, &compat_futex_lock);
+               break;
+       case FUTEX_WAKE:
+               for (i = 0; i < val; i++)
+                       pthread_cond_signal(&compat_futex_cond);
+               break;
+       default:
+               gret = -EINVAL;
+       }
+end:
+       ret = pthread_mutex_unlock(&compat_futex_lock);
+       assert(!ret);
+       return gret;
+}
+
+/*
+ * _ASYNC SIGNAL-SAFE_.
+ * For now, timeout, uaddr2 and val3 are unused.
+ * Waiter will busy-loop trying to read the condition.
+ */
+
+int compat_futex_async(int *uaddr, int op, int val,
+       const struct timespec *timeout, int *uaddr2, int val3)
+{
+       int ret, i;
+
+       /*
+        * Check if NULL. Don't let users expect that they are taken into
+        * account. 
+        */
+       assert(!timeout);
+       assert(!uaddr2);
+       assert(!val3);
+
+       /*
+        * Ensure previous memory operations on uaddr have completed.
+        */
+       smp_mb();
+
+       switch (op) {
+       case FUTEX_WAIT:
+               while (*uaddr == val)
+                       poll(NULL, 0, 10);
+               break;
+       case FUTEX_WAKE:
+               break;
+       default:
+               return -EINVAL;
+       }
+}
index e7cc18106a2a4f2ce5f9024118ebda835c975c53..be9fd72b499b7e9fef75d02da51ce01f93a8bbae 100644 (file)
@@ -9,10 +9,9 @@ AC_CANONICAL_HOST
 AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip])
 AC_CONFIG_SRCDIR([urcu.h])
 
 AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip])
 AC_CONFIG_SRCDIR([urcu.h])
 
-AH_TEMPLATE([CONFIG_SMP], [Enable SMP support. With SMP support enabled, uniprocessors are also supported. With SMP support disabled, UP systems work fine, but the behavior of SMP systems is undefined.])
-AH_TEMPLATE([CONFIG_HAVE_FENCE], [Defined when on a system that has memory fence
-instructions.])
-AH_TEMPLATE([CONFIG_HAVE_FUTEX], [Defined when on a system with futex support.])
+AH_TEMPLATE([CONFIG_URCU_SMP], [Enable SMP support. With SMP support enabled, uniprocessors are also supported. With SMP support disabled, UP systems work fine, but the behavior of SMP systems is undefined.])
+AH_TEMPLATE([CONFIG_URCU_HAVE_FENCE], [Defined when on a system that has memory fence instructions.])
+AH_TEMPLATE([CONFIG_URCU_HAVE_FUTEX], [Defined when on a system with futex support.])
 AC_CONFIG_HEADERS([urcu/config.h])
 
 # Checks for programs.
 AC_CONFIG_HEADERS([urcu/config.h])
 
 # Checks for programs.
@@ -55,12 +54,12 @@ AC_SUBST(SUBARCHTYPE)
 [
 if test "x$ARCHTYPE" = "xx86" -a "x$target_cpu" != "xi386" -a "x$target_cpu" != "xi486" -a "x$target_cpu" != "xi586"; then
 ]
 [
 if test "x$ARCHTYPE" = "xx86" -a "x$target_cpu" != "xi386" -a "x$target_cpu" != "xi486" -a "x$target_cpu" != "xi586"; then
 ]
-       AC_DEFINE([CONFIG_HAVE_FENCE], [1])
+       AC_DEFINE([CONFIG_URCU_HAVE_FENCE], [1])
 [
 fi
 ]
 
 [
 fi
 ]
 
-AC_MSG_CHECKING([presence of sys_futex()])
+AC_MSG_CHECKING([sys_futex()])
 AC_TRY_COMPILE(
 [
 #include <sys/syscall.h>
 AC_TRY_COMPILE(
 [
 #include <sys/syscall.h>
@@ -72,7 +71,7 @@ AC_TRY_COMPILE(
 ],
 [
        AC_MSG_RESULT([yes])
 ],
 [
        AC_MSG_RESULT([yes])
-       AC_DEFINE([CONFIG_HAVE_FUTEX], [1])
+       AC_DEFINE([CONFIG_URCU_HAVE_FUTEX], [1])
        compat_futex_test=0
 ]
 ,
        compat_futex_test=0
 ]
 ,
@@ -96,7 +95,7 @@ if test "$def_smp_support" = "no"; then
        echo "SMP support disabled."
 else
 ]
        echo "SMP support disabled."
 else
 ]
-       AC_DEFINE([CONFIG_SMP], [1])
+       AC_DEFINE([CONFIG_URCU_SMP], [1])
 [
        echo "SMP support enabled."
 fi
 [
        echo "SMP support enabled."
 fi
index 79ee72a08e7110ba67a44b80f834096543eaa379..83f0ffdacb388cdc87016a9a10408fe7b712e62d 100644 (file)
@@ -24,6 +24,8 @@
  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
  */
 
  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
  */
 
+#include <urcu/uatomic_arch.h>
+
 #include "urcu-pointer-static.h"
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #include "urcu-pointer.h"
 #include "urcu-pointer-static.h"
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #include "urcu-pointer.h"
index 2f9460b8542d6a8a43baa5f55c59b324284e34d2..12b018eef7d90276524d56e8606ab3786e615a0b 100644 (file)
@@ -25,7 +25,6 @@
 #include <urcu/compiler.h>
 #include <urcu/config.h>
 
 #include <urcu/compiler.h>
 #include <urcu/config.h>
 
-#define CONFIG_HAVE_FENCE 1
 #define CONFIG_HAVE_MEM_COHERENCY
 
 /* Include size of POWER5+ L3 cache lines: 256 bytes */
 #define CONFIG_HAVE_MEM_COHERENCY
 
 /* Include size of POWER5+ L3 cache lines: 256 bytes */
@@ -54,7 +53,7 @@
 #define rmc()  barrier()
 #define wmc()  barrier()
 
 #define rmc()  barrier()
 #define wmc()  barrier()
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_URCU_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
index aec91b92c1f6fef6d771e20511a8b5428c0b8e8d..bf46d3b56e6b660b0868eade0dec1ccf42a0fa69 100644 (file)
 #define rmc()  barrier()
 #define wmc()  barrier()
 
 #define rmc()  barrier()
 #define wmc()  barrier()
 
+#ifdef CONFIG_URCU_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_mc()       mc()
 #define smp_rmc()      rmc()
 #define smp_wmc()      wmc()
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_mc()       mc()
 #define smp_rmc()      rmc()
 #define smp_wmc()      wmc()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_mc()       barrier()
+#define smp_rmc()      barrier()
+#define smp_wmc()      barrier()
+#endif
 
 /* Nop everywhere except on alpha. */
 #define smp_read_barrier_depends()
 
 /* Nop everywhere except on alpha. */
 #define smp_read_barrier_depends()
index a72ef064d236c21d45086fd86293edd251943591..4ba08f7a288796186aeda16679d3fe8a7d558506 100644 (file)
@@ -33,7 +33,7 @@
 #define BITS_PER_LONG  (__SIZEOF_LONG__ * 8)
 #endif
 
 #define BITS_PER_LONG  (__SIZEOF_LONG__ * 8)
 #endif
 
-#ifdef CONFIG_HAVE_FENCE
+#ifdef CONFIG_URCU_HAVE_FENCE
 #define mb()    asm volatile("mfence":::"memory")
 #define rmb()   asm volatile("lfence":::"memory")
 #define wmb()   asm volatile("sfence"::: "memory")
 #define mb()    asm volatile("mfence":::"memory")
 #define rmb()   asm volatile("lfence":::"memory")
 #define wmb()   asm volatile("sfence"::: "memory")
@@ -62,7 +62,7 @@
 #define rmc()  barrier()
 #define wmc()  barrier()
 
 #define rmc()  barrier()
 #define wmc()  barrier()
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_URCU_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
diff --git a/urcu/config.h.in b/urcu/config.h.in
new file mode 100644 (file)
index 0000000..d61d2a9
--- /dev/null
@@ -0,0 +1,12 @@
+/* urcu/config.h.in. Manually generatad for control over the contained defs. */
+
+/* Defined when on a system that has memory fence instructions. */
+#undef CONFIG_URCU_HAVE_FENCE
+
+/* Defined when on a system with futex support. */
+#undef CONFIG_URCU_HAVE_FUTEX
+
+/* Enable SMP support. With SMP support enabled, uniprocessors are also
+   supported. With SMP support disabled, UP systems work fine, but the
+   behavior of SMP systems is undefined. */
+#undef CONFIG_URCU_SMP
diff --git a/urcu/urcu-futex.h b/urcu/urcu-futex.h
new file mode 100644 (file)
index 0000000..14fb5c0
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _URCU_FUTEX_H
+#define _URCU_FUTEX_H
+
+/*
+ * urcu-futex.h
+ *
+ * Userspace RCU - sys_futex/compat_futex header.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <urcu/config.h>
+
+#define FUTEX_WAIT             0
+#define FUTEX_WAKE             1
+
+/*
+ * sys_futex compatibility header.
+ * Use *only* *either of* futex_noasync OR futex_async on a given address.
+ *
+ * futex_noasync cannot be executed in signal handlers, but ensures that
+ * it will be put in a wait queue even in compatibility mode.
+ *
+ * futex_async is signal-handler safe for the wakeup. It uses polling
+ * on the wait-side in compatibility mode.
+ */
+
+#ifdef CONFIG_URCU_HAVE_FUTEX
+#include <sys/syscall.h>
+#define futex(...)     syscall(__NR_futex, __VA_ARGS__)
+#define futex_noasync(uaddr, op, val, timeout, uaddr2, val3)   \
+               futex(uaddr, op, val, timeout, uaddr2, val3)
+#define futex_async(uaddr, op, val, timeout, uaddr2, val3)     \
+               futex(uaddr, op, val, timeout, uaddr2, val3)
+#else
+extern int compat_futex_noasync(int *uaddr, int op, int val,
+       const struct timespec *timeout, int *uaddr2, int val3);
+#define futex_noasync(uaddr, op, val, timeout, uaddr2, val3)   \
+               compat_futex_noasync(uaddr, op, val, timeout, uaddr2, val3)
+extern int compat_futex_async(int *uaddr, int op, int val,
+       const struct timespec *timeout, int *uaddr2, int val3);
+#define futex_async(uaddr, op, val, timeout, uaddr2, val3)     \
+               compat_futex_async(uaddr, op, val, timeout, uaddr2, val3)
+#endif
+
+#endif /* _URCU_FUTEX_H */
This page took 0.029943 seconds and 4 git commands to generate.