Add rcu_read_ongoing() API to each urcu flavor
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 30 Apr 2013 00:17:22 +0000 (20:17 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 30 Apr 2013 00:17:22 +0000 (20:17 -0400)
This will allow checking whether:

- thread is online (QSBR),
- thread is nested within read-side critical section (other flavors),

This is useful for libraries that need to know if QSBR is online in
order to save the original state temporarily so it can be restored
before returning to the caller.

Eventually, this API can be called by a "debugging" implementation of
rcu_dereference() and other urcu-pointer.h API members to check that no
RCU pointer is read outside of RCU read-side critical sections.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
16 files changed:
tests/test_urcu.c
tests/test_urcu_bp.c
tests/test_urcu_qsbr.c
urcu-bp.c
urcu-bp.h
urcu-flavor.h
urcu-qsbr.c
urcu-qsbr.h
urcu.c
urcu.h
urcu/map/urcu-bp.h
urcu/map/urcu-qsbr.h
urcu/map/urcu.h
urcu/static/urcu-bp.h
urcu/static/urcu-qsbr.h
urcu/static/urcu.h

index 3c5c49256b757a244296dddc6053857c441a15b8..5059ddeac51648b5f901cdb5c3a1483aac7a1480 100644 (file)
@@ -187,6 +187,7 @@ void *thr_reader(void *_count)
        set_affinity();
 
        rcu_register_thread();
+       assert(!rcu_read_ongoing());
 
        while (!test_go)
        {
@@ -195,6 +196,7 @@ void *thr_reader(void *_count)
 
        for (;;) {
                rcu_read_lock();
+               assert(rcu_read_ongoing());
                local_ptr = rcu_dereference(test_rcu_pointer);
                rcu_debug_yield_read();
                if (local_ptr)
index 8cb74ff560d7d6e40e452e6b0a3b3a097640db9d..1926fbb2de9e81bfcc53dc62aa5be8375fe6d5e1 100644 (file)
@@ -187,6 +187,7 @@ void *thr_reader(void *_count)
        set_affinity();
 
        rcu_register_thread();
+       assert(!rcu_read_ongoing());
 
        while (!test_go)
        {
@@ -195,6 +196,7 @@ void *thr_reader(void *_count)
 
        for (;;) {
                rcu_read_lock();
+               assert(rcu_read_ongoing());
                local_ptr = rcu_dereference(test_rcu_pointer);
                rcu_debug_yield_read();
                if (local_ptr)
index 065557a1307d8f3cfe22a6c8ea6b6a39a0b3603e..f98e2735ef2004b911a78b1def6da07c694ca028 100644 (file)
@@ -187,6 +187,11 @@ void *thr_reader(void *_count)
 
        rcu_register_thread();
 
+       assert(rcu_read_ongoing());
+       rcu_thread_offline();
+       assert(!rcu_read_ongoing());
+       rcu_thread_online();
+
        while (!test_go)
        {
        }
@@ -194,6 +199,7 @@ void *thr_reader(void *_count)
 
        for (;;) {
                rcu_read_lock();
+               assert(rcu_read_ongoing());
                local_ptr = rcu_dereference(test_rcu_pointer);
                rcu_debug_yield_read();
                if (local_ptr)
index f99c0e502ee20f197b5f225a2b6a49088d3b138a..8207a4120ffd6b0790939e0ee176e064198704fe 100644 (file)
--- a/urcu-bp.c
+++ b/urcu-bp.c
@@ -301,6 +301,11 @@ void rcu_read_unlock(void)
        _rcu_read_unlock();
 }
 
+int rcu_read_ongoing(void)
+{
+       return _rcu_read_ongoing();
+}
+
 /*
  * only grow for now.
  */
index 833688f7b553089deb21e7a32187bb83d5b5fdf3..4718f3b38e93aac09c2e670925e7247a72d04684 100644 (file)
--- a/urcu-bp.h
+++ b/urcu-bp.h
@@ -74,6 +74,7 @@ extern "C" {
  */
 #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
@@ -89,6 +90,7 @@ extern "C" {
 
 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)                                               \
index 9af4d0e632b291799a49a747d7f6bcb1f05efc60..c04f1db78ba1e113a7ff85e9d8552cfe08b342c8 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 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));
@@ -46,6 +47,7 @@ struct rcu_flavor_struct {
 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,      \
index 3c2c65da4aa14e5b6cbf4a7c8b259ab6d86adf3c..786a80d6b16b1936dc62b71b43db18850854dd41 100644 (file)
@@ -208,7 +208,7 @@ void synchronize_rcu(void)
        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
@@ -317,7 +317,7 @@ void synchronize_rcu(void)
        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
@@ -405,6 +405,11 @@ void rcu_read_unlock(void)
        _rcu_read_unlock();
 }
 
+int rcu_read_ongoing(void)
+{
+       return _rcu_read_ongoing();
+}
+
 void rcu_quiescent_state(void)
 {
        _rcu_quiescent_state();
index a2f6575986bf7976811ae6db3150f81f457609c4..bb0523c904916062ae1ee4843c8ee5085dd8ee8f 100644 (file)
@@ -70,6 +70,7 @@ extern "C" {
  */
 #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
@@ -107,6 +108,7 @@ extern void rcu_read_unlock(void);
 
 #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);
diff --git a/urcu.c b/urcu.c
index 15def09adb7e7feeeaba49f2d1d2a1c33a90bf59..a78c02bdca6a71f9e7f66c76295fc8f1f33cdd37 100644 (file)
--- a/urcu.c
+++ b/urcu.c
@@ -429,6 +429,11 @@ void rcu_read_unlock(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();
diff --git a/urcu.h b/urcu.h
index cd4fcbbfd0a871878e006faa561b74a15c91ab57..b8ca700ddcdb750270c5e39bd86080b559102363 100644 (file)
--- a/urcu.h
+++ b/urcu.h
@@ -74,12 +74,15 @@ extern "C" {
 #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 */
@@ -91,6 +94,7 @@ extern "C" {
 
 extern void rcu_read_lock(void);
 extern void rcu_read_unlock(void);
+extern int rcu_read_ongoing(void);
 
 #endif /* !_LGPL_SOURCE */
 
index 63582fd3fe5b6c9f34c66991c14355650c1ba73b..8c819a68afaf3902a71c83f20d6a972c6899305a 100644 (file)
@@ -38,6 +38,8 @@
 #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
index f0aecc992da5de97e391b2378ae24489985f194f..c40af35c2230d55483d4785165f40bb7766d9a73 100644 (file)
@@ -38,6 +38,8 @@
 #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
index 759cb4108a8c8cb2787813a518e4362e19acc274..becc6a0f438a4eda367e3f779885a633534bdc71 100644 (file)
@@ -69,6 +69,8 @@
 #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
index c7f532640e3c0feab165cb5a699c4c3760df011d..2f365206afad6db4c561654109def617ef559ce5 100644 (file)
@@ -223,6 +223,20 @@ static inline void _rcu_read_unlock(void)
        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
index f6e55807db267ba66227f1d7046511f56589aa76..ea5e13adebd5fae0374a5ad81693dd6cf46436c2 100644 (file)
@@ -190,6 +190,18 @@ static inline void _rcu_read_unlock(void)
 {
 }
 
+/*
+ * 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
index 973826a52bfa021423bbb8cce12545357d2df48b..6c8b92602234b97d27a4cb462ec0ec06c56a62c7 100644 (file)
@@ -329,6 +329,18 @@ static inline void _rcu_read_unlock(void)
        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
This page took 0.03251 seconds and 4 git commands to generate.