X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu%2Fstatic%2Furcu-qsbr.h;fp=urcu%2Fstatic%2Furcu-qsbr.h;h=f3149569b2a2e2573df57936673d82eaadf0e1d7;hp=c8a87b8d777a7ce0bcae127a5d1bd1545bfee561;hb=f864c15d3148f14019e837544213314db0198ccb;hpb=75478b32ffe53b0d8b5e687d9cf7ebdd77a085de diff --git a/urcu/static/urcu-qsbr.h b/urcu/static/urcu-qsbr.h index c8a87b8..f314956 100644 --- a/urcu/static/urcu-qsbr.h +++ b/urcu/static/urcu-qsbr.h @@ -180,20 +180,43 @@ static inline void _rcu_read_unlock(void) { } +/* + * This is a helper function for _rcu_quiescent_state(). + * The first cmm_smp_mb() ensures memory accesses in the prior read-side + * critical sections are not reordered with store to + * URCU_TLS(rcu_reader).ctr, and ensures that mutexes held within an + * offline section that would happen to end with this + * rcu_quiescent_state() call are not reordered with + * store to URCU_TLS(rcu_reader).ctr. + */ +static inline void _rcu_quiescent_state_update_and_wakeup(unsigned long gp_ctr) +{ + cmm_smp_mb(); + _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, gp_ctr); + cmm_smp_mb(); /* write URCU_TLS(rcu_reader).ctr before read futex */ + wake_up_gp(); + cmm_smp_mb(); +} + /* * Inform RCU of a quiescent state. * * 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. + * + * We skip the memory barriers and gp store if our local ctr already + * matches the global rcu_gp_ctr value: this is OK because a prior + * _rcu_quiescent_state() or _rcu_thread_online() already updated it + * within our thread, so we have no quiescent state to report. */ static inline void _rcu_quiescent_state(void) { - cmm_smp_mb(); - _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, _CMM_LOAD_SHARED(rcu_gp_ctr)); - cmm_smp_mb(); /* write URCU_TLS(rcu_reader).ctr before read futex */ - wake_up_gp(); - cmm_smp_mb(); + unsigned long gp_ctr; + + if ((gp_ctr = CMM_LOAD_SHARED(rcu_gp_ctr)) == URCU_TLS(rcu_reader).ctr) + return; + _rcu_quiescent_state_update_and_wakeup(gp_ctr); } /*