-/*
- * The trick here is that RCU_GP_CTR_BIT must be a multiple of 8 so we can use a
- * full 8-bits, 16-bits or 32-bits bitmask for the lower order bits.
- */
-#define RCU_GP_COUNT (1UL << 0)
-/* Use the amount of bits equal to half of the architecture long size */
-#define RCU_GP_CTR_BIT (1UL << (sizeof(long) << 2))
-#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1)
-
-/*
- * Global quiescent period counter with low-order bits unused.
- * Using a int rather than a char to eliminate false register dependencies
- * causing stalls on some architectures.
- */
-extern long urcu_gp_ctr;
-
-extern long __thread urcu_active_readers;
-
-static inline int rcu_old_gp_ongoing(long *value)
-{
- long v;
-
- if (value == NULL)
- return 0;
- /*
- * Make sure both tests below are done on the same version of *value
- * to insure consistency.
- */
- v = LOAD_SHARED(*value);
- return (v & RCU_GP_CTR_NEST_MASK) &&
- ((v ^ urcu_gp_ctr) & RCU_GP_CTR_BIT);
-}
-
-static inline void rcu_read_lock(void)
-{
- long tmp;
-
- tmp = urcu_active_readers;
- /* urcu_gp_ctr = RCU_GP_COUNT | (~RCU_GP_CTR_BIT or RCU_GP_CTR_BIT) */
- /*
- * The data dependency "read urcu_gp_ctr, write urcu_active_readers",
- * serializes those two memory operations. The memory barrier in the
- * signal handler ensures we receive the proper memory commit barriers
- * required by _STORE_SHARED and _LOAD_SHARED whenever communication
- * with the writer is needed.
- */
- if (likely(!(tmp & RCU_GP_CTR_NEST_MASK)))
- _STORE_SHARED(urcu_active_readers, _LOAD_SHARED(urcu_gp_ctr));
- else
- _STORE_SHARED(urcu_active_readers, tmp + RCU_GP_COUNT);
- /*
- * Increment active readers count before accessing the pointer.
- * See force_mb_all_threads().
- */
- reader_barrier();
-}
-
-static inline void rcu_read_unlock(void)
-{
- reader_barrier();
- /*
- * Finish using rcu before decrementing the pointer.
- * See force_mb_all_threads().
- */
- _STORE_SHARED(urcu_active_readers, urcu_active_readers - RCU_GP_COUNT);
-}
-
-/**
- * rcu_assign_pointer - assign (publicize) a pointer to a newly
- * initialized structure that will be dereferenced by RCU read-side
- * critical sections. Returns the value assigned.
- *
- * Inserts memory barriers on architectures that require them
- * (pretty much all of them other than x86), and also prevents
- * the compiler from reordering the code that initializes the
- * structure after the pointer assignment. More importantly, this
- * call documents which pointers will be dereferenced by RCU read-side
- * code.
- */
-
-#define rcu_assign_pointer(p, v) \
- ({ \
- if (!__builtin_constant_p(v) || \
- ((v) != NULL)) \
- wmb(); \
- STORE_SHARED(p, v); \
- })
-
-#define rcu_xchg_pointer(p, v) \
- ({ \
- if (!__builtin_constant_p(v) || \
- ((v) != NULL)) \
- wmb(); \
- xchg(p, v); \
- })
-
-extern void synchronize_rcu(void);
-
-/*
- * Exchanges the pointer and waits for quiescent state.
- * The pointer returned can be freed.
- */
-#define urcu_publish_content(p, v) \
- ({ \
- void *oldptr; \
- oldptr = rcu_xchg_pointer(p, v); \
- synchronize_rcu(); \
- oldptr; \
- })
-
-/*
- * Reader thread registration.
- */
-extern void urcu_register_thread(void);
-extern void urcu_unregister_thread(void);