urcu-qsbr-static.h   urcu-qsbr-static.h 
skipping to change at line 159 skipping to change at line 159
static inline void wake_up_gp(void) static inline void wake_up_gp(void)
{ {
if (unlikely(uatomic_read(&gp_futex) == -1)) { if (unlikely(uatomic_read(&gp_futex) == -1)) {
uatomic_set(&gp_futex, 0); uatomic_set(&gp_futex, 0);
futex_noasync(&gp_futex, FUTEX_WAKE, 1, futex_noasync(&gp_futex, FUTEX_WAKE, 1,
NULL, NULL, 0); NULL, NULL, 0);
} }
} }
#if (BITS_PER_LONG < 64) #if (BITS_PER_LONG < 64)
static inline int rcu_gp_ongoing(unsigned long *value) static inline int rcu_gp_ongoing(unsigned long *ctr)
{ {
unsigned long reader_gp; unsigned long v;
if (value == NULL) v = LOAD_SHARED(*ctr);
return 0; return v && ((v ^ rcu_gp_ctr) & RCU_GP_CTR);
reader_gp = LOAD_SHARED(*value);
return reader_gp && ((reader_gp ^ rcu_gp_ctr) & RCU_GP_CTR);
} }
#else /* !(BITS_PER_LONG < 64) */ #else /* !(BITS_PER_LONG < 64) */
static inline int rcu_gp_ongoing(unsigned long *value) static inline int rcu_gp_ongoing(unsigned long *ctr)
{ {
unsigned long reader_gp; unsigned long v;
if (value == NULL) v = LOAD_SHARED(*ctr);
return 0; return v && (v - rcu_gp_ctr > ULONG_MAX / 2);
reader_gp = LOAD_SHARED(*value);
return reader_gp && (reader_gp - rcu_gp_ctr > ULONG_MAX / 2);
} }
#endif /* !(BITS_PER_LONG < 64) */ #endif /* !(BITS_PER_LONG < 64) */
static inline void _rcu_read_lock(void) static inline void _rcu_read_lock(void)
{ {
rcu_assert(rcu_reader.ctr); rcu_assert(rcu_reader.ctr);
} }
static inline void _rcu_read_unlock(void) static inline void _rcu_read_unlock(void)
{ {
 End of changes. 6 change blocks. 
12 lines changed or deleted 8 lines changed or added


 urcu-static.h   urcu-static.h 
skipping to change at line 62 skipping to change at line 62
#ifdef RCU_MEMBARRIER #ifdef RCU_MEMBARRIER
#include <unistd.h> #include <unistd.h>
#include <sys/syscall.h> #include <sys/syscall.h>
/* If the headers do not support SYS_membarrier, statically use RCU_MB */ /* If the headers do not support SYS_membarrier, statically use RCU_MB */
#ifdef SYS_membarrier #ifdef SYS_membarrier
# define MEMBARRIER_EXPEDITED (1 << 0) # define MEMBARRIER_EXPEDITED (1 << 0)
# define MEMBARRIER_DELAYED (1 << 1) # define MEMBARRIER_DELAYED (1 << 1)
# define MEMBARRIER_QUERY (1 << 16) # define MEMBARRIER_QUERY (1 << 16)
# define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__ ) # define membarrier(...) syscall(SYS_membarrier, __VA_ARGS__)
#else #else
# undef RCU_MEMBARRIER # undef RCU_MEMBARRIER
# define RCU_MB # define RCU_MB
#endif #endif
#endif #endif
/* /*
* This code section can only be included in LGPL 2.1 compatible source cod e. * This code section can only be included in LGPL 2.1 compatible source cod e.
* See below for the function call wrappers which can be used in code meant to * See below for the function call wrappers which can be used in code meant to
* be only linked with the Userspace RCU library. This comes with a small * be only linked with the Userspace RCU library. This comes with a small
skipping to change at line 210 skipping to change at line 210
barrier(); barrier();
} }
#endif #endif
/* /*
* The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we ca n use * The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we ca n use
* a full 8-bits, 16-bits or 32-bits bitmask for the lower order bits. * a full 8-bits, 16-bits or 32-bits bitmask for the lower order bits.
*/ */
#define RCU_GP_COUNT (1UL << 0) #define RCU_GP_COUNT (1UL << 0)
/* Use the amount of bits equal to half of the architecture long size */ /* Use the amount of bits equal to half of the architecture long size */
#define RCU_GP_CTR_PHASE (1UL << (sizeof(long) << 2)) #define RCU_GP_CTR_PHASE (1UL << (sizeof(unsigned long) << 2))
#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_PHASE - 1) #define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_PHASE - 1)
/* /*
* Global quiescent period counter with low-order bits unused. * Global quiescent period counter with low-order bits unused.
* Using a int rather than a char to eliminate false register dependencies * Using a int rather than a char to eliminate false register dependencies
* causing stalls on some architectures. * causing stalls on some architectures.
*/ */
extern long rcu_gp_ctr; extern unsigned long rcu_gp_ctr;
struct rcu_reader { struct rcu_reader {
/* Data used by both reader and synchronize_rcu() */ /* Data used by both reader and synchronize_rcu() */
long ctr; unsigned long ctr;
char need_mb; char need_mb;
/* Data used for registry */ /* Data used for registry */
struct list_head head __attribute__((aligned(CACHE_LINE_SIZE))); struct list_head head __attribute__((aligned(CACHE_LINE_SIZE)));
pthread_t tid; pthread_t tid;
}; };
extern struct rcu_reader __thread rcu_reader; extern struct rcu_reader __thread rcu_reader;
extern int gp_futex; extern int gp_futex;
skipping to change at line 245 skipping to change at line 245
*/ */
static inline void wake_up_gp(void) static inline void wake_up_gp(void)
{ {
if (unlikely(uatomic_read(&gp_futex) == -1)) { if (unlikely(uatomic_read(&gp_futex) == -1)) {
uatomic_set(&gp_futex, 0); uatomic_set(&gp_futex, 0);
futex_async(&gp_futex, FUTEX_WAKE, 1, futex_async(&gp_futex, FUTEX_WAKE, 1,
NULL, NULL, 0); NULL, NULL, 0);
} }
} }
static inline int rcu_old_gp_ongoing(long *value) static inline int rcu_gp_ongoing(unsigned long *ctr)
{ {
long v; unsigned long v;
if (value == NULL)
return 0;
/* /*
* Make sure both tests below are done on the same version of *value * Make sure both tests below are done on the same version of *value
* to insure consistency. * to insure consistency.
*/ */
v = LOAD_SHARED(*value); v = LOAD_SHARED(*ctr);
return (v & RCU_GP_CTR_NEST_MASK) && return (v & RCU_GP_CTR_NEST_MASK) &&
((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE); ((v ^ rcu_gp_ctr) & RCU_GP_CTR_PHASE);
} }
static inline void _rcu_read_lock(void) static inline void _rcu_read_lock(void)
{ {
long tmp; unsigned long tmp;
tmp = rcu_reader.ctr; tmp = rcu_reader.ctr;
/* /*
* rcu_gp_ctr is * rcu_gp_ctr is
* RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE) * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
*/ */
if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) { if (likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
_STORE_SHARED(rcu_reader.ctr, _LOAD_SHARED(rcu_gp_ctr)); _STORE_SHARED(rcu_reader.ctr, _LOAD_SHARED(rcu_gp_ctr));
/* /*
* Set active readers count for outermost nesting level befo re * Set active readers count for outermost nesting level befo re
* accessing the pointer. See smp_mb_master(). * accessing the pointer. See smp_mb_master().
*/ */
smp_mb_slave(RCU_MB_GROUP); smp_mb_slave(RCU_MB_GROUP);
} else { } else {
_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT); _STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT);
} }
} }
static inline void _rcu_read_unlock(void) static inline void _rcu_read_unlock(void)
{ {
long tmp; unsigned long tmp;
tmp = rcu_reader.ctr; tmp = rcu_reader.ctr;
/* /*
* Finish using rcu before decrementing the pointer. * Finish using rcu before decrementing the pointer.
* See smp_mb_master(). * See smp_mb_master().
*/ */
if (likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) { if (likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
smp_mb_slave(RCU_MB_GROUP); smp_mb_slave(RCU_MB_GROUP);
_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT) ; _STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT) ;
/* write rcu_reader.ctr before read futex */ /* write rcu_reader.ctr before read futex */
 End of changes. 10 change blocks. 
11 lines changed or deleted 9 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/