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