X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu-qsbr.c;h=f681c05bf0c05d96860e06cbb8771b11c9e3e829;hp=a86f6e94d5ae13eb24e5d34610a3d9c5954373b4;hb=b55487c706982c8190e42545f7f74dfadad59548;hpb=47d2f29ead2c92123069ebf7b84c6e48cf91612a diff --git a/urcu-qsbr.c b/urcu-qsbr.c index a86f6e9..f681c05 100644 --- a/urcu-qsbr.c +++ b/urcu-qsbr.c @@ -37,7 +37,7 @@ /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */ #include "urcu-qsbr.h" -pthread_mutex_t urcu_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t urcu_mutex = PTHREAD_MUTEX_INITIALIZER; /* * Global grace period counter. @@ -135,12 +135,24 @@ static void switch_next_urcu_qparity(void) void synchronize_rcu(void) { + unsigned long was_online; + + was_online = rcu_reader_qs_gp; + /* All threads should read qparity before accessing data structure * where new ptr points to. */ /* Write new ptr before changing the qparity */ smp_mb(); + /* + * Mark the writer thread offline to make sure we don't wait for + * our own quiescent state. This allows using synchronize_rcu() in + * threads registered as readers. + */ + if (was_online) + STORE_SHARED(rcu_reader_qs_gp, 0); + internal_urcu_lock(); switch_next_urcu_qparity(); /* 0 -> 1 */ @@ -183,9 +195,12 @@ void synchronize_rcu(void) internal_urcu_unlock(); - /* Finish waiting for reader threads before letting the old ptr being + /* + * Finish waiting for reader threads before letting the old ptr being * freed. */ + if (was_online) + _STORE_SHARED(rcu_reader_qs_gp, LOAD_SHARED(urcu_gp_ctr)); smp_mb(); } #else /* !(BITS_PER_LONG < 64) */