set_affinity();
rcu_register_thread();
+ assert(!rcu_read_ongoing());
while (!test_go)
{
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
set_affinity();
rcu_register_thread();
+ assert(!rcu_read_ongoing());
while (!test_go)
{
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
rcu_register_thread();
+ assert(rcu_read_ongoing());
+ rcu_thread_offline();
+ assert(!rcu_read_ongoing());
+ rcu_thread_online();
+
while (!test_go)
{
}
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
_rcu_read_unlock();
}
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
/*
* only grow for now.
*/
*/
#define rcu_read_lock_bp _rcu_read_lock
#define rcu_read_unlock_bp _rcu_read_unlock
+#define rcu_read_ongoing_bp _rcu_read_ongoing
#define rcu_dereference_bp rcu_dereference
#define rcu_cmpxchg_pointer_bp rcu_cmpxchg_pointer
extern void rcu_read_lock(void);
extern void rcu_read_unlock(void);
+extern int rcu_read_ongoing(void);
extern void *rcu_dereference_sym_bp(void *p);
#define rcu_dereference_bp(p) \
struct rcu_flavor_struct {
void (*read_lock)(void);
void (*read_unlock)(void);
+ int (*read_ongoing)(void);
void (*read_quiescent_state)(void);
void (*update_call_rcu)(struct rcu_head *head,
void (*func)(struct rcu_head *head));
const struct rcu_flavor_struct x = { \
.read_lock = rcu_read_lock, \
.read_unlock = rcu_read_unlock, \
+ .read_ongoing = rcu_read_ongoing, \
.read_quiescent_state = rcu_quiescent_state, \
.update_call_rcu = call_rcu, \
.update_synchronize_rcu = synchronize_rcu, \
DEFINE_URCU_WAIT_NODE(wait, URCU_WAIT_WAITING);
struct urcu_waiters waiters;
- was_online = URCU_TLS(rcu_reader).ctr;
+ was_online = rcu_read_ongoing();
/* All threads should read qparity before accessing data structure
* where new ptr points to. In the "then" case, rcu_thread_offline
DEFINE_URCU_WAIT_NODE(wait, URCU_WAIT_WAITING);
struct urcu_waiters waiters;
- was_online = URCU_TLS(rcu_reader).ctr;
+ was_online = rcu_read_ongoing();
/*
* Mark the writer thread offline to make sure we don't wait for
_rcu_read_unlock();
}
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
void rcu_quiescent_state(void)
{
_rcu_quiescent_state();
*/
#define rcu_read_lock_qsbr _rcu_read_lock
#define rcu_read_unlock_qsbr _rcu_read_unlock
+#define rcu_read_ongoing_qsbr _rcu_read_ongoing
#define rcu_quiescent_state_qsbr _rcu_quiescent_state
#define rcu_thread_offline_qsbr _rcu_thread_offline
#endif /* !RCU_DEBUG */
+extern int rcu_read_ongoing(void);
extern void rcu_quiescent_state(void);
extern void rcu_thread_offline(void);
extern void rcu_thread_online(void);
_rcu_read_unlock();
}
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
void rcu_register_thread(void)
{
URCU_TLS(rcu_reader).tid = pthread_self();
#ifdef RCU_MEMBARRIER
#define rcu_read_lock_memb _rcu_read_lock
#define rcu_read_unlock_memb _rcu_read_unlock
+#define rcu_read_ongoing_memb _rcu_read_ongoing
#elif defined(RCU_SIGNAL)
#define rcu_read_lock_sig _rcu_read_lock
#define rcu_read_unlock_sig _rcu_read_unlock
+#define rcu_read_ongoing_sig _rcu_read_ongoing
#elif defined(RCU_MB)
#define rcu_read_lock_mb _rcu_read_lock
#define rcu_read_unlock_mb _rcu_read_unlock
+#define rcu_read_ongoing_mb _rcu_read_ongoing
#endif
#else /* !_LGPL_SOURCE */
extern void rcu_read_lock(void);
extern void rcu_read_unlock(void);
+extern int rcu_read_ongoing(void);
#endif /* !_LGPL_SOURCE */
#define _rcu_read_lock _rcu_read_lock_bp
#define rcu_read_unlock rcu_read_unlock_bp
#define _rcu_read_unlock _rcu_read_unlock_bp
+#define rcu_read_ongoing rcu_read_ongoing_bp
+#define _rcu_read_ongoing _rcu_read_ongoing_bp
#define rcu_register_thread rcu_register_thread_bp
#define rcu_unregister_thread rcu_unregister_thread_bp
#define rcu_init rcu_init_bp
#define _rcu_read_lock _rcu_read_lock_qsbr
#define rcu_read_unlock rcu_read_unlock_qsbr
#define _rcu_read_unlock _rcu_read_unlock_qsbr
+#define rcu_read_ongoing rcu_read_ongoing_qsbr
+#define _rcu_read_ongoing _rcu_read_ongoing_qsbr
#define rcu_quiescent_state rcu_quiescent_state_qsbr
#define _rcu_quiescent_state _rcu_quiescent_state_qsbr
#define rcu_thread_offline rcu_thread_offline_qsbr
#define _rcu_read_lock _rcu_read_lock_memb
#define rcu_read_unlock rcu_read_unlock_memb
#define _rcu_read_unlock _rcu_read_unlock_memb
+#define rcu_read_ongoing rcu_read_ongoing_memb
+#define _rcu_read_ongoing _rcu_read_ongoing_memb
#define rcu_register_thread rcu_register_thread_memb
#define rcu_unregister_thread rcu_unregister_thread_memb
#define rcu_init rcu_init_memb
#define _rcu_read_lock _rcu_read_lock_sig
#define rcu_read_unlock rcu_read_unlock_sig
#define _rcu_read_unlock _rcu_read_unlock_sig
+#define rcu_read_ongoing rcu_read_ongoing_sig
+#define _rcu_read_ongoing _rcu_read_ongoing_sig
#define rcu_register_thread rcu_register_thread_sig
#define rcu_unregister_thread rcu_unregister_thread_sig
#define rcu_init rcu_init_sig
#define _rcu_read_lock _rcu_read_lock_mb
#define rcu_read_unlock rcu_read_unlock_mb
#define _rcu_read_unlock _rcu_read_unlock_mb
+#define rcu_read_ongoing rcu_read_ongoing_mb
+#define _rcu_read_ongoing _rcu_read_ongoing_mb
#define rcu_register_thread rcu_register_thread_mb
#define rcu_unregister_thread rcu_unregister_thread_mb
#define rcu_init rcu_init_mb
cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
}
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long. The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _rcu_read_ongoing(void)
+{
+ if (caa_unlikely(!URCU_TLS(rcu_reader)))
+ rcu_bp_register(); /* If not yet registered. */
+ return URCU_TLS(rcu_reader)->ctr & RCU_GP_CTR_NEST_MASK;
+}
+
#ifdef __cplusplus
}
#endif
{
}
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long. The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _rcu_read_ongoing(void)
+{
+ return URCU_TLS(rcu_reader).ctr;
+}
+
/*
* This is a helper function for _rcu_quiescent_state().
* The first cmm_smp_mb() ensures memory accesses in the prior read-side
cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
}
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long. The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _rcu_read_ongoing(void)
+{
+ return URCU_TLS(rcu_reader).ctr & RCU_GP_CTR_NEST_MASK;
+}
+
#ifdef __cplusplus
}
#endif