#include <stdlib.h>
#include <pthread.h>
-#include <syscall.h>
#include <unistd.h>
+#include <stdint.h>
#include <urcu/compiler.h>
#include <urcu/arch.h>
#include <urcu/uatomic.h>
#include <urcu/list.h>
#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
#ifdef __cplusplus
extern "C" {
#define RCU_MEMBARRIER
#endif
+/*
+ * RCU_MEMBARRIER is only possibly available on Linux. Fallback to RCU_MB
+ * otherwise.
+ */
+#if !defined(__linux__) && defined(RCU_MEMBARRIER)
+#undef RCU_MEMBARRIER
+#define RCU_MB
+#endif
+
#ifdef RCU_MEMBARRIER
-#include <unistd.h>
-#include <sys/syscall.h>
+#include <syscall.h>
/* If the headers do not support SYS_membarrier, statically use RCU_MB */
#ifdef SYS_membarrier
#define SIGRCU SIGUSR1
#endif
-/*
- * If a reader is really non-cooperative and refuses to commit its
- * rcu_active_readers count to memory (there is no barrier in the reader
- * per-se), kick it after a few loops waiting for it.
- */
-#define KICK_READER_LOOPS 10000
-
-/*
- * Active attempts to check for reader Q.S. before calling futex().
- */
-#define RCU_QS_ACTIVE_ATTEMPTS 100
-
#ifdef DEBUG_RCU
#define rcu_assert(args...) assert(args)
#else
#endif
extern unsigned int yield_active;
-extern unsigned int __thread rand_yield;
+extern DECLARE_URCU_TLS(unsigned int, rand_yield);
static inline void debug_yield_read(void)
{
if (yield_active & YIELD_READ)
- if (rand_r(&rand_yield) & 0x1)
- usleep(rand_r(&rand_yield) % MAX_SLEEP);
+ if (rand_r(&URCU_TLS(rand_yield)) & 0x1)
+ usleep(rand_r(&URCU_TLS(rand_yield)) % MAX_SLEEP);
}
static inline void debug_yield_write(void)
{
if (yield_active & YIELD_WRITE)
- if (rand_r(&rand_yield) & 0x1)
- usleep(rand_r(&rand_yield) % MAX_SLEEP);
+ if (rand_r(&URCU_TLS(rand_yield)) & 0x1)
+ usleep(rand_r(&URCU_TLS(rand_yield)) % MAX_SLEEP);
}
static inline void debug_yield_init(void)
{
- rand_yield = time(NULL) ^ pthread_self();
+ URCU_TLS(rand_yield) = time(NULL) ^ (unsigned long) pthread_self();
}
#else
static inline void debug_yield_read(void)
static inline void smp_mb_slave(int group)
{
- if (likely(has_sys_membarrier))
+ if (caa_likely(has_sys_membarrier))
cmm_barrier();
else
cmm_smp_mb();
pthread_t tid;
};
-extern struct rcu_reader __thread rcu_reader;
+extern DECLARE_URCU_TLS(struct rcu_reader, rcu_reader);
-extern int gp_futex;
+extern int32_t gp_futex;
/*
* Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
*/
static inline void wake_up_gp(void)
{
- if (unlikely(uatomic_read(&gp_futex) == -1)) {
+ if (caa_unlikely(uatomic_read(&gp_futex) == -1)) {
uatomic_set(&gp_futex, 0);
futex_async(&gp_futex, FUTEX_WAKE, 1,
NULL, NULL, 0);
unsigned long tmp;
cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
- tmp = rcu_reader.ctr;
+ tmp = URCU_TLS(rcu_reader).ctr;
/*
* rcu_gp_ctr is
* RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
*/
- if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
- _CMM_STORE_SHARED(rcu_reader.ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
+ if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
+ _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
/*
* Set active readers count for outermost nesting level before
* accessing the pointer. See smp_mb_master().
*/
smp_mb_slave(RCU_MB_GROUP);
} else {
- _CMM_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT);
+ _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, tmp + RCU_GP_COUNT);
}
}
{
unsigned long tmp;
- tmp = rcu_reader.ctr;
+ tmp = URCU_TLS(rcu_reader).ctr;
/*
* Finish using rcu before decrementing the pointer.
* See smp_mb_master().
*/
- if (likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
+ if (caa_likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
smp_mb_slave(RCU_MB_GROUP);
- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
- /* write rcu_reader.ctr before read futex */
+ _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, URCU_TLS(rcu_reader).ctr - RCU_GP_COUNT);
+ /* write URCU_TLS(rcu_reader).ctr before read futex */
smp_mb_slave(RCU_MB_GROUP);
wake_up_gp();
} else {
- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
+ _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, URCU_TLS(rcu_reader).ctr - RCU_GP_COUNT);
}
cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
}