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 | |||