* #include <urcu.h>
* Link the application with "-lurcu".
- * This is the preferred version of the library, both in terms of speed
- and flexibility. Requires a signal, typically SIGUSR1. Can be
- overridden with -DSIGRCU by modifying Makefile.build.inc.
-
-Usage of liburcu-mb
-
- * #include <urcu.h>
- * Compile any _LGPL_SOURCE code using this library with "-DRCU_MB".
- * Link with "-lurcu-mb".
- * This version of the urcu library does not need to
- reserve a signal number. RCU_MB uses full memory barriers for
- readers. This eliminates the need for signals but results in slower
- reads.
+ * This is the preferred version of the library, in terms of
+ grace-period detection speed, read-side speed and flexibility.
+ Dynamically detects kernel support for sys_membarrier(). Falls back
+ on urcu-mb scheme if support is not present, which has slower
+ read-side.
Usage of liburcu-qsbr
the threads are not active. It provides the fastest read-side at the
expense of more intrusiveness in the application code.
+Usage of liburcu-mb
+
+ * #include <urcu.h>
+ * Compile any _LGPL_SOURCE code using this library with "-DRCU_MB".
+ * Link with "-lurcu-mb".
+ * This version of the urcu library uses memory barriers on the writer
+ and reader sides. This results in faster grace-period detection, but
+ results in slower reads.
+
+Usage of liburcu-signal
+
+ * #include <urcu-signal.h>
+ * Link the application with "-lurcu-signal".
+ * Version of the library that requires a signal, typically SIGUSR1. Can
+ be overridden with -DSIGRCU by modifying Makefile.build.inc.
+
Usage of liburcu-bp
* #include <urcu-bp.h>
AM_CFLAGS=-I$(top_srcdir) -I$(top_builddir)
noinst_PROGRAMS = test_urcu test_urcu_dynamic_link test_urcu_timing \
+ test_urcu_signal test_urcu_signal_dynamic_link test_urcu_signal_timing \
test_rwlock_timing test_rwlock test_perthreadlock_timing \
- test_perthreadlock test_urcu_yield test_urcu_mb \
- test_qsbr_timing test_qsbr rcutorture_urcu \
+ test_perthreadlock test_urcu_yield test_urcu_signal_yield test_urcu_mb \
+ test_qsbr_timing test_qsbr rcutorture_urcu rcutorture_urcu_signal \
rcutorture_urcu_mb rcutorture_urcu_bp rcutorture_qsbr \
- test_mutex test_looplen test_urcu_gc \
- test_urcu_gc_mb test_qsbr_gc test_qsbr_lgc test_urcu_lgc \
- test_urcu_lgc_mb test_qsbr_dynamic_link test_urcu_mb_defer \
+ test_mutex test_looplen test_urcu_gc test_urcu_signal_gc \
+ test_urcu_lgc \
+ test_urcu_mb_gc test_qsbr_gc test_qsbr_lgc test_urcu_signal_lgc \
+ test_urcu_mb_lgc test_qsbr_dynamic_link test_urcu_defer \
test_uatomic test_urcu_assign test_urcu_assign_dynamic_link \
test_urcu_bp test_urcu_bp_dynamic_link
noinst_HEADERS = rcutorture.h
COMPAT+=$(top_srcdir)/compat_futex.c
endif
-URCU_SIGNAL=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
-# URCU_SIGNAL_YIELD uses urcu.c but -DDEBUG_YIELD must be defined
-URCU_SIGNAL_YIELD=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
+URCU=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
+URCU_QSBR=$(top_srcdir)/urcu-qsbr.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
# URCU_MB uses urcu.c but -DRCU_MB must be defined
URCU_MB=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
+# URCU_SIGNAL uses urcu.c but -DRCU_SIGNAL must be defined
+URCU_SIGNAL=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
URCU_BP=$(top_srcdir)/urcu-bp.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
-URCU_QSBR=$(top_srcdir)/urcu-qsbr.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
-# -DRCU_MB must be defined
-URCU_MB_DEFER=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-defer.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
+URCU_DEFER=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-defer.c $(top_srcdir)/urcu-pointer.c $(COMPAT)
-URCU_SIGNAL_LIB=$(top_builddir)/liburcu.la
+URCU_LIB=$(top_builddir)/liburcu.la
+URCU_QSBR_LIB=$(top_builddir)/liburcu-qsbr.la
URCU_MB_LIB=$(top_builddir)/liburcu-mb.la
+URCU_SIGNAL_LIB=$(top_builddir)/liburcu-signal.la
URCU_BP_LIB=$(top_builddir)/liburcu-bp.la
-URCU_QSBR_LIB=$(top_builddir)/liburcu-qsbr.la
if GCC_API
APIHEADER=api_gcc.h
EXTRA_DIST = $(top_srcdir)/tests/api_*.h
-test_urcu_SOURCES = test_urcu.c $(URCU_SIGNAL)
+test_urcu_SOURCES = test_urcu.c $(URCU)
-test_urcu_dynamic_link_SOURCES = test_urcu.c $(URCU_SIGNAL)
+test_urcu_dynamic_link_SOURCES = test_urcu.c $(URCU)
test_urcu_dynamic_link_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
-test_urcu_timing_SOURCES = test_urcu_timing.c $(URCU_SIGNAL)
+test_urcu_timing_SOURCES = test_urcu_timing.c $(URCU)
-test_rwlock_timing_SOURCES = test_rwlock_timing.c $(URCU_SIGNAL)
+test_urcu_yield_SOURCES = test_urcu.c $(URCU)
+test_urcu_yield_CFLAGS = -DDEBUG_YIELD $(AM_CFLAGS)
-test_rwlock_SOURCES = test_rwlock.c $(URCU_SIGNAL)
-test_perthreadlock_timing_SOURCES = test_perthreadlock_timing.c $(URCU_SIGNAL)
+test_qsbr_SOURCES = test_qsbr.c $(URCU_QSBR)
-test_perthreadlock_SOURCES = test_perthreadlock.c $(URCU_SIGNAL)
+test_qsbr_timing_SOURCES = test_qsbr_timing.c $(URCU_QSBR)
-test_urcu_yield_SOURCES = test_urcu.c $(URCU_SIGNAL_YIELD)
-test_urcu_yield_CFLAGS = -DDEBUG_YIELD $(AM_CFLAGS)
test_urcu_mb_SOURCES = test_urcu.c $(URCU_MB)
test_urcu_mb_CFLAGS = -DRCU_MB $(AM_CFLAGS)
-test_qsbr_timing_SOURCES = test_qsbr_timing.c $(URCU_QSBR)
-test_qsbr_SOURCES = test_qsbr.c $(URCU_QSBR)
+test_urcu_signal_SOURCES = test_urcu.c $(URCU_SIGNAL)
+test_urcu_signal_CFLAGS = -DRCU_SIGNAL $(AM_CFLAGS)
+
+test_urcu_signal_dynamic_link_SOURCES = test_urcu.c $(URCU_SIGNAL)
+test_urcu_signal_dynamic_link_CFLAGS = -DRCU_SIGNAL -DDYNAMIC_LINK_TEST \
+ $(AM_CFLAGS)
+
+test_urcu_signal_timing_SOURCES = test_urcu_timing.c $(URCU_SIGNAL)
+test_urcu_signal_timing_CFLAGS= -DRCU_SIGNAL $(AM_CFLAGS)
+
+test_urcu_signal_yield_SOURCES = test_urcu.c $(URCU_SIGNAL)
+test_urcu_signal_yield_CFLAGS = -DRCU_SIGNAL -DDEBUG_YIELD $(AM_CFLAGS)
+
+
+test_rwlock_timing_SOURCES = test_rwlock_timing.c $(URCU_SIGNAL)
+
+test_rwlock_SOURCES = test_rwlock.c $(URCU_SIGNAL)
+
+test_perthreadlock_timing_SOURCES = test_perthreadlock_timing.c $(URCU_SIGNAL)
+
+test_perthreadlock_SOURCES = test_perthreadlock.c $(URCU_SIGNAL)
+
rcutorture_urcu_SOURCES = urcutorture.c
-rcutorture_urcu_CFLAGS = -DTORTURE_URCU_SIGNAL $(AM_CFLAGS)
-rcutorture_urcu_LDADD = $(URCU_SIGNAL_LIB)
+rcutorture_urcu_CFLAGS = -DTORTURE_URCU $(AM_CFLAGS)
+rcutorture_urcu_LDADD = $(URCU)
rcutorture_urcu_mb_SOURCES = urcutorture.c
rcutorture_urcu_mb_CFLAGS = -DTORTURE_URCU_MB $(AM_CFLAGS)
rcutorture_qsbr_CFLAGS = -DTORTURE_QSBR $(AM_CFLAGS)
rcutorture_qsbr_LDADD = $(URCU_QSBR_LIB)
+rcutorture_urcu_signal_SOURCES = urcutorture.c
+rcutorture_urcu_signal_CFLAGS = -DTORTURE_URCU_SIGNAL $(AM_CFLAGS)
+rcutorture_urcu_signal_LDADD = $(URCU_SIGNAL_LIB)
+
rcutorture_urcu_bp_SOURCES = urcutorture.c
rcutorture_urcu_bp_CFLAGS = -DTORTURE_URCU_BP $(AM_CFLAGS)
rcutorture_urcu_bp_LDADD = $(URCU_BP_LIB)
-test_mutex_SOURCES = test_mutex.c $(URCU_SIGNAL)
+test_mutex_SOURCES = test_mutex.c $(URCU)
test_looplen_SOURCES = test_looplen.c
-test_urcu_gc_SOURCES = test_urcu_gc.c $(URCU_SIGNAL)
+test_urcu_gc_SOURCES = test_urcu_gc.c $(URCU)
-test_urcu_gc_mb_SOURCES = test_urcu_gc.c $(URCU_MB)
-test_urcu_gc_mb_CFLAGS = -DRCU_MB $(AM_CFLAGS)
+test_urcu_signal_gc_SOURCES = test_urcu_gc.c $(URCU_SIGNAL)
+test_urcu_signal_gc_CFLAGS = -DRCU_SIGNAL $(AM_CFLAGS)
+
+test_urcu_mb_gc_SOURCES = test_urcu_gc.c $(URCU_MB)
+test_urcu_mb_gc_CFLAGS = -DRCU_MB $(AM_CFLAGS)
test_qsbr_gc_SOURCES = test_qsbr_gc.c $(URCU_QSBR)
test_qsbr_lgc_SOURCES = test_qsbr_gc.c $(URCU_QSBR)
test_qsbr_lgc_CFLAGS = -DTEST_LOCAL_GC $(AM_CFLAGS)
-test_urcu_lgc_SOURCES = test_urcu_gc.c $(URCU_SIGNAL)
+test_urcu_lgc_SOURCES = test_urcu_gc.c $(URCU)
test_urcu_lgc_CFLAGS = -DTEST_LOCAL_GC $(AM_CFLAGS)
-test_urcu_lgc_mb_SOURCES = test_urcu_gc.c $(URCU_MB)
-test_urcu_lgc_mb_CFLAGS = -DTEST_LOCAL_GC -DRCU_MB $(AM_CFLAGS)
+test_urcu_signal_lgc_SOURCES = test_urcu_gc.c $(URCU_SIGNAL)
+test_urcu_signal_lgc_CFLAGS = -DRCU_SIGNAL -DTEST_LOCAL_GC $(AM_CFLAGS)
+
+test_urcu_mb_lgc_SOURCES = test_urcu_gc.c $(URCU_MB)
+test_urcu_mb_lgc_CFLAGS = -DTEST_LOCAL_GC -DRCU_MB $(AM_CFLAGS)
test_qsbr_dynamic_link_SOURCES = test_qsbr.c $(URCU_QSBR)
test_qsbr_dynamic_link_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
-test_urcu_mb_defer_SOURCES = test_urcu_defer.c $(URCU_MB_DEFER)
-test_urcu_mb_defer_CFLAGS = -DRCU_MB $(AM_CFLAGS)
+test_urcu_defer_SOURCES = test_urcu_defer.c $(URCU_DEFER)
test_uatomic_SOURCES = test_uatomic.c $(COMPAT)
-test_urcu_assign_SOURCES = test_urcu_assign.c $(URCU_SIGNAL)
+test_urcu_assign_SOURCES = test_urcu_assign.c $(URCU)
-test_urcu_assign_dynamic_link_SOURCES = test_urcu_assign.c $(URCU_SIGNAL)
+test_urcu_assign_dynamic_link_SOURCES = test_urcu_assign.c $(URCU)
test_urcu_assign_dynamic_link_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
test_urcu_bp_SOURCES = test_urcu_bp.c $(URCU_BP)
* IBM's contributions to this file may be relicensed under LGPLv2 or later.
*/
+#define _BSD_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
#include "urcu.h"
-#ifndef RCU_MB
+#ifdef RCU_MEMBARRIER
static int init_done;
+int has_sys_membarrier;
void __attribute__((constructor)) rcu_init(void);
-void __attribute__((destructor)) rcu_exit(void);
-#else
+#endif
+
+#ifdef RCU_MB
void rcu_init(void)
{
}
#endif
+#ifdef RCU_SIGNAL
+static int init_done;
+
+void __attribute__((constructor)) rcu_init(void);
+void __attribute__((destructor)) rcu_exit(void);
+#endif
+
static pthread_mutex_t rcu_mutex = PTHREAD_MUTEX_INITIALIZER;
int gp_futex;
STORE_SHARED(rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR_PHASE);
}
+#ifdef RCU_MEMBARRIER
+static void smp_mb_heavy(void)
+{
+ if (likely(has_sys_membarrier))
+ membarrier(1);
+ else
+ smp_mb();
+}
+#endif
+
#ifdef RCU_MB
-static void smp_mb_heavy()
+static void smp_mb_heavy(void)
{
smp_mb();
}
-#else
+#endif
+
+#ifdef RCU_SIGNAL
static void force_mb_all_readers(void)
{
struct rcu_reader *index;
smp_mb(); /* read ->need_mb before ending the barrier */
}
-static void smp_mb_heavy()
+static void smp_mb_heavy(void)
{
force_mb_all_readers();
}
-#endif /* #else #ifdef RCU_MB */
+#endif /* #ifdef RCU_SIGNAL */
/*
* synchronize_rcu() waiting. Single thread.
internal_rcu_unlock();
}
-#ifndef RCU_MB
+#ifdef RCU_MEMBARRIER
+void rcu_init(void)
+{
+ if (init_done)
+ return;
+ init_done = 1;
+ if (!membarrier(1))
+ has_sys_membarrier = 1;
+}
+#endif
+
+#ifdef RCU_SIGNAL
static void sigrcu_handler(int signo, siginfo_t *siginfo, void *context)
{
/*
assert(act.sa_sigaction == sigrcu_handler);
assert(list_empty(®istry));
}
-#endif /* #ifndef RCU_MB */
+#endif /* #ifdef RCU_SIGNAL */