summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
171ff3a)
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:
set_affinity();
rcu_register_thread();
set_affinity();
rcu_register_thread();
+ assert(!rcu_read_ongoing());
for (;;) {
rcu_read_lock();
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
set_affinity();
rcu_register_thread();
set_affinity();
rcu_register_thread();
+ assert(!rcu_read_ongoing());
for (;;) {
rcu_read_lock();
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
+ assert(rcu_read_ongoing());
+ rcu_thread_offline();
+ assert(!rcu_read_ongoing());
+ rcu_thread_online();
+
for (;;) {
rcu_read_lock();
for (;;) {
rcu_read_lock();
+ assert(rcu_read_ongoing());
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
local_ptr = rcu_dereference(test_rcu_pointer);
rcu_debug_yield_read();
if (local_ptr)
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
/*
* only grow for now.
*/
/*
* only grow for now.
*/
*/
#define rcu_read_lock_bp _rcu_read_lock
#define rcu_read_unlock_bp _rcu_read_unlock
*/
#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
#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 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) \
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);
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));
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, \
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, \
.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;
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
/* 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;
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
/*
* Mark the writer thread offline to make sure we don't wait for
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
void rcu_quiescent_state(void)
{
_rcu_quiescent_state();
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_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
#define rcu_quiescent_state_qsbr _rcu_quiescent_state
#define rcu_thread_offline_qsbr _rcu_thread_offline
+extern int rcu_read_ongoing(void);
extern void rcu_quiescent_state(void);
extern void rcu_thread_offline(void);
extern void rcu_thread_online(void);
extern void rcu_quiescent_state(void);
extern void rcu_thread_offline(void);
extern void rcu_thread_online(void);
+int rcu_read_ongoing(void)
+{
+ return _rcu_read_ongoing();
+}
+
void rcu_register_thread(void)
{
URCU_TLS(rcu_reader).tid = pthread_self();
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
#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
#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
#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 */
#endif
#else /* !_LGPL_SOURCE */
extern void rcu_read_lock(void);
extern void rcu_read_unlock(void);
extern void rcu_read_lock(void);
extern void rcu_read_unlock(void);
+extern int rcu_read_ongoing(void);
#endif /* !_LGPL_SOURCE */
#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_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_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_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_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_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_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_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_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_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
#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 */
}
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
#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
/*
* 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 */
}
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
#ifdef __cplusplus
}
#endif