X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;ds=sidebyside;f=urcu.c;h=08fb75dd0feae13421647f7d84615bee6d88654f;hb=c265818b951224bcde407b1efa14f9daf44949b3;hp=d0d61385385d713bf221e078767295bd3ecfb2d6;hpb=cdcb92bbb9e54201e0982844e3ca9cb4fd9b31e5;p=urcu.git diff --git a/urcu.c b/urcu.c index d0d6138..08fb75d 100644 --- a/urcu.c +++ b/urcu.c @@ -36,7 +36,7 @@ static struct reader_data *reader_data; static int num_readers, alloc_readers; static int sig_done; -void rcu_write_lock(void) +void internal_urcu_lock(void) { int ret; ret = pthread_mutex_lock(&urcu_mutex); @@ -46,7 +46,7 @@ void rcu_write_lock(void) } } -void rcu_write_unlock(void) +void internal_urcu_unlock(void) { int ret; @@ -113,15 +113,38 @@ void wait_for_quiescent_state(int parity) force_mb_all_threads(); } +static void switch_qparity(void) +{ + int prev_parity; + + /* All threads should read qparity before accessing data structure. */ + /* Write ptr before changing the qparity */ + force_mb_all_threads(); + prev_parity = switch_next_urcu_qparity(); + + /* + * Wait for previous parity to be empty of readers. + */ + wait_for_quiescent_state(prev_parity); +} + +void synchronize_rcu(void) +{ + internal_urcu_lock(); + switch_qparity(); + switch_qparity(); + internal_urcu_lock(); +} + /* * Return old pointer, OK to free, no more reference exist. * Called under rcu_write_lock. */ void *urcu_publish_content(void **ptr, void *new) { - int prev_parity; void *oldptr; + internal_urcu_lock(); /* * We can publish the new pointer before we change the current qparity. * Readers seeing the new pointer while being in the previous qparity @@ -134,19 +157,11 @@ void *urcu_publish_content(void **ptr, void *new) */ oldptr = *ptr; *ptr = new; - /* All threads should read qparity before ptr */ - /* Write ptr before changing the qparity */ - force_mb_all_threads(); - prev_parity = switch_next_urcu_qparity(); - /* - * Wait for previous parity to be empty of readers. - */ - wait_for_quiescent_state(prev_parity); - /* - * Deleting old data is ok ! - */ - + switch_qparity(); + switch_qparity(); + internal_urcu_unlock(); + return oldptr; } @@ -185,7 +200,7 @@ void urcu_remove_reader(pthread_t id) assert(reader_data != NULL); for (index = reader_data; index < reader_data + num_readers; index++) { - if (index->tid == id) { + if (pthread_equal(index->tid, id)) { memcpy(index, &reader_data[num_readers - 1], sizeof(struct reader_data)); reader_data[num_readers - 1].tid = 0; @@ -200,16 +215,16 @@ void urcu_remove_reader(pthread_t id) void urcu_register_thread(void) { - rcu_write_lock(); + internal_urcu_lock(); urcu_add_reader(pthread_self()); - rcu_write_unlock(); + internal_urcu_unlock(); } void urcu_unregister_thread(void) { - rcu_write_lock(); + internal_urcu_lock(); urcu_remove_reader(pthread_self()); - rcu_write_unlock(); + internal_urcu_unlock(); } void sigurcu_handler(int signo, siginfo_t *siginfo, void *context)