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.
+read-side. Use the --disable-sys-membarrier-fallback configure option
+to disable the fall back, thus requiring `sys_membarrier()` to be
+available. This gives a small speedup when `sys_membarrier()` is
+supported by the kernel, and aborts in the library constructor if not
+supported.
### Usage of `liburcu-qsbr`
AH_TEMPLATE([CONFIG_RCU_ARM_HAVE_DMB], [Use the dmb instruction if available for use on ARM.])
AH_TEMPLATE([CONFIG_RCU_TLS], [TLS provided by the compiler.])
AH_TEMPLATE([CONFIG_RCU_HAVE_CLOCK_GETTIME], [clock_gettime() is detected.])
+AH_TEMPLATE([CONFIG_RCU_FORCE_SYS_MEMBARRIER], [Require the operating system to support the membarrier system call for default and bulletproof flavors.])
+
+# Allow requiring the operating system to support the membarrier system
+# call. Applies to default and bulletproof flavors.
+AC_ARG_ENABLE([sys-membarrier-fallback],
+ AS_HELP_STRING([--disable-sys-membarrier-fallback], [Abort if sys-membarrier is needed but not available rather than using a fallback.]),
+ [def_sys_membarrier_fallback=$enableval],
+ [def_sys_membarrier_fallback="yes"])
+AS_IF([test "x$def_sys_membarrier_fallback" != "xyes"], [AC_DEFINE([CONFIG_RCU_FORCE_SYS_MEMBARRIER], [1])])
# Allow overriding storage used for TLS variables.
AC_ARG_ENABLE([compiler-tls],
#define rcu_flavor rcu_flavor_memb
-/* Specific to MEMBARRIER flavor */
-#define rcu_has_sys_membarrier rcu_has_sys_membarrier_memb
-
#elif defined(RCU_SIGNAL)
#define rcu_read_lock rcu_read_lock_sig
#include <pthread.h>
#include <unistd.h>
+#include <urcu/config.h>
#include <urcu/compiler.h>
#include <urcu/arch.h>
#include <urcu/system.h>
*/
extern DECLARE_URCU_TLS(struct rcu_reader *, rcu_reader);
+#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+#define urcu_bp_has_sys_membarrier 1
+#else
extern int urcu_bp_has_sys_membarrier;
+#endif
static inline void urcu_bp_smp_mb_slave(void)
{
#include <unistd.h>
#include <stdint.h>
+#include <urcu/config.h>
#include <urcu/compiler.h>
#include <urcu/arch.h>
#include <urcu/system.h>
*/
#ifdef RCU_MEMBARRIER
-extern int rcu_has_sys_membarrier;
+#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+#define rcu_has_sys_membarrier_memb 1
+#else
+extern int rcu_has_sys_membarrier_memb;
+#endif
static inline void smp_mb_slave(void)
{
- if (caa_likely(rcu_has_sys_membarrier))
+ if (caa_likely(rcu_has_sys_membarrier_memb))
cmm_barrier();
else
cmm_smp_mb();
static
void __attribute__((destructor)) rcu_bp_exit(void);
+#ifndef CONFIG_RCU_FORCE_SYS_MEMBARRIER
int urcu_bp_has_sys_membarrier;
+#endif
/*
* rcu_gp_lock ensures mutual exclusion between threads calling
rcu_bp_unregister(rcu_key);
}
+#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+static
+void rcu_sys_membarrier_status(int available)
+{
+ if (!available)
+ abort();
+}
+#else
+static
+void rcu_sys_membarrier_status(int available)
+{
+ if (available)
+ urcu_bp_has_sys_membarrier = 1;
+}
+#endif
+
static
void rcu_bp_init(void)
{
if (ret)
abort();
ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
- if (ret >= 0 && (ret & MEMBARRIER_CMD_SHARED)) {
- urcu_bp_has_sys_membarrier = 1;
- }
+ rcu_sys_membarrier_status(ret >= 0
+ && (ret & MEMBARRIER_CMD_SHARED));
initialized = 1;
}
mutex_unlock(&init_lock);
#ifdef RCU_MEMBARRIER
static int init_done;
-int rcu_has_sys_membarrier;
+#ifndef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+int rcu_has_sys_membarrier_memb;
+#endif
void __attribute__((constructor)) rcu_init(void);
#endif
#ifdef RCU_MEMBARRIER
static void smp_mb_master(void)
{
- if (caa_likely(rcu_has_sys_membarrier))
+ if (caa_likely(rcu_has_sys_membarrier_memb))
(void) membarrier(MEMBARRIER_CMD_SHARED, 0);
else
cmm_smp_mb();
}
#ifdef RCU_MEMBARRIER
+
+#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+static
+void rcu_sys_membarrier_status(int available)
+{
+ if (!available)
+ abort();
+}
+#else
+static
+void rcu_sys_membarrier_status(int available)
+{
+ if (available)
+ rcu_has_sys_membarrier_memb = 1;
+}
+#endif
+
void rcu_init(void)
{
int ret;
return;
init_done = 1;
ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
- if (ret >= 0 && (ret & MEMBARRIER_CMD_SHARED)) {
- rcu_has_sys_membarrier = 1;
- }
+ rcu_sys_membarrier_status(ret >= 0 && (ret & MEMBARRIER_CMD_SHARED));
}
#endif