X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu-bp.c;h=1856d3fc76fa1ec31a644ea9fa326a4ab48182f8;hp=387a52bf892df54cfcac0f14868ad70b2e8d1959;hb=48a8832be16833b1a9f2625799ac3d0ea4dafc91;hpb=c1be8fb947a1d56a0f0b2fd82eca6f23c467b0ee diff --git a/urcu-bp.c b/urcu-bp.c index 387a52b..1856d3f 100644 --- a/urcu-bp.c +++ b/urcu-bp.c @@ -79,8 +79,8 @@ void *mremap_wrapper(void *old_address, size_t old_size, } #endif -/* Sleep delay in us */ -#define RCU_SLEEP_DELAY 1000 +/* Sleep delay in ms */ +#define RCU_SLEEP_DELAY_MS 10 #define INIT_NR_THREADS 8 #define ARENA_INIT_ALLOC \ sizeof(struct registry_chunk) \ @@ -91,6 +91,9 @@ void *mremap_wrapper(void *old_address, size_t old_size, */ #define RCU_QS_ACTIVE_ATTEMPTS 100 +static +int rcu_bp_refcount; + static void __attribute__((constructor)) rcu_bp_init(void); static @@ -166,7 +169,7 @@ 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; /* @@ -175,7 +178,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) + wait_loops++; + cds_list_for_each_entry_safe(index, tmp, input_readers, node) { switch (rcu_reader_state(&index->ctr)) { case RCU_READER_ACTIVE_CURRENT: @@ -202,8 +207,8 @@ static void wait_for_readers(struct cds_list_head *input_readers, if (cds_list_empty(input_readers)) { break; } else { - if (wait_loops == RCU_QS_ACTIVE_ATTEMPTS) - usleep(RCU_SLEEP_DELAY); + if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) + (void) poll(NULL, 0, RCU_SLEEP_DELAY_MS); else caa_cpu_relax(); } @@ -454,11 +459,8 @@ struct registry_chunk *find_chunk(struct rcu_reader *rcu_reader_reg) /* Called with signals off and mutex locked */ static -void remove_thread(void) +void remove_thread(struct rcu_reader *rcu_reader_reg) { - struct rcu_reader *rcu_reader_reg; - - rcu_reader_reg = URCU_TLS(rcu_reader); cleanup_thread(find_chunk(rcu_reader_reg), rcu_reader_reg); URCU_TLS(rcu_reader) = NULL; } @@ -499,7 +501,7 @@ end: /* Disable signals, take mutex, remove from registry */ static -void rcu_bp_unregister(void) +void rcu_bp_unregister(struct rcu_reader *rcu_reader_reg) { sigset_t newmask, oldmask; int ret; @@ -512,11 +514,12 @@ void rcu_bp_unregister(void) abort(); mutex_lock(&rcu_gp_lock); - remove_thread(); + remove_thread(rcu_reader_reg); mutex_unlock(&rcu_gp_lock); ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL); if (ret) abort(); + rcu_bp_exit(); } /* @@ -526,15 +529,14 @@ void rcu_bp_unregister(void) static void urcu_bp_thread_exit_notifier(void *rcu_key) { - assert(rcu_key == URCU_TLS(rcu_reader)); - rcu_bp_unregister(); + rcu_bp_unregister(rcu_key); } static void rcu_bp_init(void) { mutex_lock(&init_lock); - if (!initialized) { + if (!rcu_bp_refcount++) { int ret; ret = pthread_key_create(&urcu_bp_key, @@ -549,16 +551,21 @@ void rcu_bp_init(void) static void rcu_bp_exit(void) { - struct registry_chunk *chunk, *tmp; - int ret; + mutex_lock(&init_lock); + if (!--rcu_bp_refcount) { + struct registry_chunk *chunk, *tmp; + int ret; - cds_list_for_each_entry_safe(chunk, tmp, - ®istry_arena.chunk_list, node) { - munmap(chunk, chunk->data_len + sizeof(struct registry_chunk)); + cds_list_for_each_entry_safe(chunk, tmp, + ®istry_arena.chunk_list, node) { + munmap(chunk, chunk->data_len + + sizeof(struct registry_chunk)); + } + ret = pthread_key_delete(urcu_bp_key); + if (ret) + abort(); } - ret = pthread_key_delete(urcu_bp_key); - if (ret) - abort(); + mutex_unlock(&init_lock); } /*