X-Git-Url: https://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu.c;h=a5568bdbd075ed1edc4539dec460c7cce40ee590;hp=1aa00fec9278929996fed4183ebe2acf40d5b61f;hb=b83b3590caf8ddd0fb1393b0d8378f916c8bf831;hpb=a4922ed92bea8e5552a3e66b7dd7b4721b754c90 diff --git a/urcu.c b/urcu.c index 1aa00fe..a5568bd 100644 --- a/urcu.c +++ b/urcu.c @@ -37,6 +37,7 @@ #include #include +#include "urcu/arch.h" #include "urcu/wfcqueue.h" #include "urcu/map/urcu.h" #include "urcu/static/urcu.h" @@ -63,16 +64,9 @@ */ #define RCU_QS_ACTIVE_ATTEMPTS 100 -/* - * RCU_MEMBARRIER is only possibly available on Linux. - */ -#if defined(RCU_MEMBARRIER) && defined(__linux__) -#include -#endif - -/* If the headers do not support SYS_membarrier, fall back on RCU_MB */ -#ifdef SYS_membarrier -# define membarrier(...) syscall(SYS_membarrier, __VA_ARGS__) +/* If the headers do not support membarrier system call, fall back on RCU_MB */ +#ifdef __NR_membarrier +# define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__) #else # define membarrier(...) -ENOSYS #endif @@ -232,19 +226,27 @@ static void smp_mb_master(void) /* * synchronize_rcu() waiting. Single thread. + * Always called with rcu_registry lock held. Releases this lock and + * grabs it again. Holds the lock when it returns. */ static void wait_gp(void) { - /* Read reader_gp before read futex */ + /* + * Read reader_gp before read futex. smp_mb_master() needs to + * be called with the rcu registry lock held in RCU_SIGNAL + * flavor. + */ smp_mb_master(); + /* Temporarily unlock the registry lock. */ + mutex_unlock(&rcu_registry_lock); if (uatomic_read(&rcu_gp.futex) != -1) - return; + goto end; while (futex_async(&rcu_gp.futex, FUTEX_WAIT, -1, NULL, NULL, 0)) { switch (errno) { case EWOULDBLOCK: /* Value already changed. */ - return; + goto end; case EINTR: /* Retry if interrupted by signal. */ break; /* Get out of switch. */ @@ -253,6 +255,11 @@ static void wait_gp(void) urcu_die(errno); } } +end: + /* + * Re-lock the registry lock before the next loop. + */ + mutex_lock(&rcu_registry_lock); } /* @@ -315,14 +322,19 @@ static void wait_for_readers(struct cds_list_head *input_readers, } break; } else { - /* Temporarily unlock the registry lock. */ - mutex_unlock(&rcu_registry_lock); - if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { + /* wait_gp unlocks/locks registry lock. */ wait_gp(); - else + } else { + /* Temporarily unlock the registry lock. */ + mutex_unlock(&rcu_registry_lock); caa_cpu_relax(); - /* Re-lock the registry lock before the next loop. */ - mutex_lock(&rcu_registry_lock); + /* + * Re-lock the registry lock before the + * next loop. + */ + mutex_lock(&rcu_registry_lock); + } } #else /* #ifndef HAS_INCOHERENT_CACHES */ /* @@ -342,16 +354,20 @@ static void wait_for_readers(struct cds_list_head *input_readers, smp_mb_master(); wait_gp_loops = 0; } - /* Temporarily unlock the registry lock. */ - mutex_unlock(&rcu_registry_lock); if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { + /* wait_gp unlocks/locks registry lock. */ wait_gp(); wait_gp_loops++; } else { + /* Temporarily unlock the registry lock. */ + mutex_unlock(&rcu_registry_lock); caa_cpu_relax(); + /* + * Re-lock the registry lock before the + * next loop. + */ + mutex_lock(&rcu_registry_lock); } - /* Re-lock the registry lock before the next loop. */ - mutex_lock(&rcu_registry_lock); } #endif /* #else #ifndef HAS_INCOHERENT_CACHES */ }