X-Git-Url: https://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu.c;h=ae3490f7cb2cdc1f7cdb1d26f77c0ee22620e9eb;hp=da6839f0c25b88b4262e9a615bd197220789c185;hb=5e81fed7cc48d0e14b7478ec1152c3ca2bd01f97;hpb=ed1b099ef8acd1396dbde7c7150d1a5eb16ce8a6 diff --git a/urcu.c b/urcu.c index da6839f..ae3490f 100644 --- a/urcu.c +++ b/urcu.c @@ -53,15 +53,33 @@ /* * If a reader is really non-cooperative and refuses to commit its * rcu_active_readers count to memory (there is no barrier in the reader - * per-se), kick it after a few loops waiting for it. + * per-se), kick it after 10 loops waiting for it. */ -#define KICK_READER_LOOPS 10000 +#define KICK_READER_LOOPS 10 /* * Active attempts to check for reader Q.S. before calling futex(). */ #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__) +#else +# define membarrier(...) -ENOSYS +#endif + +#define MEMBARRIER_EXPEDITED (1 << 0) +#define MEMBARRIER_DELAYED (1 << 1) +#define MEMBARRIER_QUERY (1 << 16) + #ifdef RCU_MEMBARRIER static int init_done; int rcu_has_sys_membarrier; @@ -83,7 +101,7 @@ void __attribute__((destructor)) rcu_exit(void); #endif static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER; -struct urcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; +struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; /* * Written to only by each individual reader. Read by both the reader and the @@ -91,11 +109,6 @@ struct urcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; */ DEFINE_URCU_TLS(struct rcu_reader, rcu_reader); -#ifdef DEBUG_YIELD -unsigned int rcu_yield_active; -DEFINE_URCU_TLS(unsigned int, rcu_rand_yield); -#endif - static CDS_LIST_HEAD(registry); /* @@ -139,7 +152,7 @@ static void mutex_unlock(pthread_mutex_t *mutex) static void smp_mb_master(int group) { if (caa_likely(rcu_has_sys_membarrier)) - membarrier(MEMBARRIER_EXPEDITED); + (void) membarrier(MEMBARRIER_EXPEDITED); else cmm_smp_mb(); } @@ -217,8 +230,11 @@ static void wait_for_readers(struct cds_list_head *input_readers, struct cds_list_head *cur_snap_readers, struct cds_list_head *qsreaders) { - int wait_loops = 0; + unsigned int wait_loops = 0; struct rcu_reader *index, *tmp; +#ifdef HAS_INCOHERENT_CACHES + unsigned int wait_gp_loops = 0; +#endif /* HAS_INCOHERENT_CACHES */ /* * Wait for each thread URCU_TLS(rcu_reader).ctr to either @@ -226,8 +242,9 @@ static void wait_for_readers(struct cds_list_head *input_readers, * rcu_gp.ctr value. */ for (;;) { - wait_loops++; - if (wait_loops == RCU_QS_ACTIVE_ATTEMPTS) { + if (wait_loops < RCU_QS_ACTIVE_ATTEMPTS) + wait_loops++; + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { uatomic_dec(&rcu_gp.futex); /* Write futex before read reader_gp */ smp_mb_master(RCU_MB_GROUP); @@ -258,14 +275,14 @@ static void wait_for_readers(struct cds_list_head *input_readers, #ifndef HAS_INCOHERENT_CACHES if (cds_list_empty(input_readers)) { - if (wait_loops == RCU_QS_ACTIVE_ATTEMPTS) { + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { /* Read reader_gp before write futex */ smp_mb_master(RCU_MB_GROUP); uatomic_set(&rcu_gp.futex, 0); } break; } else { - if (wait_loops == RCU_QS_ACTIVE_ATTEMPTS) + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) wait_gp(); else caa_cpu_relax(); @@ -277,22 +294,21 @@ static void wait_for_readers(struct cds_list_head *input_readers, * for too long. */ if (cds_list_empty(input_readers)) { - if (wait_loops == RCU_QS_ACTIVE_ATTEMPTS) { + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { /* Read reader_gp before write futex */ smp_mb_master(RCU_MB_GROUP); uatomic_set(&rcu_gp.futex, 0); } break; } else { - switch (wait_loops) { - case RCU_QS_ACTIVE_ATTEMPTS: - wait_gp(); - break; /* only escape switch */ - case KICK_READER_LOOPS: + if (wait_gp_loops == KICK_READER_LOOPS) { smp_mb_master(RCU_MB_GROUP); - wait_loops = 0; - break; /* only escape switch */ - default: + wait_gp_loops = 0; + } + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) { + wait_gp(); + wait_gp_loops++; + } else { caa_cpu_relax(); } } @@ -495,14 +511,14 @@ void rcu_init(void) void rcu_exit(void) { - struct sigaction act; - int ret; - - ret = sigaction(SIGRCU, NULL, &act); - if (ret) - urcu_die(errno); - assert(act.sa_sigaction == sigrcu_handler); - assert(cds_list_empty(®istry)); + /* + * Don't unregister the SIGRCU signal handler anymore, because + * call_rcu threads could still be using it shortly before the + * application exits. + * Assertion disabled because call_rcu threads are now rcu + * readers, and left running at exit. + * assert(cds_list_empty(®istry)); + */ } #endif /* #ifdef RCU_SIGNAL */