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
--- /dev/null
+/*
+ * 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;
+ }
+}
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.
[
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
]
-AC_MSG_CHECKING([presence of sys_futex()])
+AC_MSG_CHECKING([sys_futex()])
AC_TRY_COMPILE(
[
#include <sys/syscall.h>
],
[
AC_MSG_RESULT([yes])
- AC_DEFINE([CONFIG_HAVE_FUTEX], [1])
+ AC_DEFINE([CONFIG_URCU_HAVE_FUTEX], [1])
compat_futex_test=0
]
,
echo "SMP support disabled."
else
]
- AC_DEFINE([CONFIG_SMP], [1])
+ AC_DEFINE([CONFIG_URCU_SMP], [1])
[
echo "SMP support enabled."
fi
* 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/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 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 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()
+#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()
#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 rmc() barrier()
#define wmc() barrier()
-#ifdef CONFIG_SMP
+#ifdef CONFIG_URCU_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
--- /dev/null
+/* 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
--- /dev/null
+#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 */