X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=src%2Furcu.c;h=c4e2dde9ab798986111ff070741b18c9e2cd237f;hp=ccd9706dda6fe6a8b6bfcba2fced7893054cf3ae;hb=ce28e67a534dcf0b68ccad2218e5a2e552e6e469;hpb=6893800a4d1cc14dff0395ddcd660a5138db183d diff --git a/src/urcu.c b/src/urcu.c index ccd9706..c4e2dde 100644 --- a/src/urcu.c +++ b/src/urcu.c @@ -34,21 +34,24 @@ #include #include #include +#include #include -#include "urcu/arch.h" -#include "urcu/wfcqueue.h" -#include "urcu/map/urcu.h" -#include "urcu/static/urcu.h" -#include "urcu-pointer.h" -#include "urcu/tls-compat.h" +#include +#include +#include +#include +#include +#include #include "urcu-die.h" #include "urcu-wait.h" +#include "urcu-utils.h" +#define URCU_API_MAP /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */ #undef _LGPL_SOURCE -#include "urcu.h" +#include #define _LGPL_SOURCE /* @@ -71,13 +74,27 @@ #endif enum membarrier_cmd { - MEMBARRIER_CMD_QUERY = 0, - MEMBARRIER_CMD_SHARED = (1 << 0), + MEMBARRIER_CMD_QUERY = 0, + MEMBARRIER_CMD_SHARED = (1 << 0), + /* reserved for MEMBARRIER_CMD_SHARED_EXPEDITED (1 << 1) */ + /* reserved for MEMBARRIER_CMD_PRIVATE (1 << 2) */ + MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3), + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4), }; #ifdef RCU_MEMBARRIER static int init_done; -int rcu_has_sys_membarrier; +static int urcu_memb_has_sys_membarrier_private_expedited; + +#ifndef CONFIG_RCU_FORCE_SYS_MEMBARRIER +/* + * Explicitly initialize to zero because we can't alias a non-static + * uninitialized variable. + */ +int urcu_memb_has_sys_membarrier = 0; +URCU_ATTR_ALIAS("urcu_memb_has_sys_membarrier") +extern int rcu_has_sys_membarrier_memb; +#endif void __attribute__((constructor)) rcu_init(void); #endif @@ -86,6 +103,8 @@ void __attribute__((constructor)) rcu_init(void); void rcu_init(void) { } +URCU_ATTR_ALIAS(urcu_stringify(rcu_init)) +void alias_rcu_init(void); #endif #ifdef RCU_SIGNAL @@ -110,13 +129,17 @@ static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER; * rcu_registry_lock may nest inside rcu_gp_lock. */ static pthread_mutex_t rcu_registry_lock = PTHREAD_MUTEX_INITIALIZER; -struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; +struct urcu_gp rcu_gp = { .ctr = URCU_GP_COUNT }; +URCU_ATTR_ALIAS(urcu_stringify(rcu_gp)) +extern struct urcu_gp alias_rcu_gp; /* * Written to only by each individual reader. Read by both the reader and the * writers. */ -DEFINE_URCU_TLS(struct rcu_reader, rcu_reader); +DEFINE_URCU_TLS(struct urcu_reader, rcu_reader); +URCU_ATTR_ALIAS(urcu_stringify(rcu_reader)) +extern struct urcu_reader alias_rcu_reader; static CDS_LIST_HEAD(registry); @@ -160,10 +183,14 @@ static void mutex_unlock(pthread_mutex_t *mutex) #ifdef RCU_MEMBARRIER static void smp_mb_master(void) { - if (caa_likely(rcu_has_sys_membarrier)) - (void) membarrier(MEMBARRIER_CMD_SHARED, 0); - else + if (caa_likely(urcu_memb_has_sys_membarrier)) { + if (membarrier(urcu_memb_has_sys_membarrier_private_expedited ? + MEMBARRIER_CMD_PRIVATE_EXPEDITED : + MEMBARRIER_CMD_SHARED, 0)) + urcu_die(errno); + } else { cmm_smp_mb(); + } } #endif @@ -177,7 +204,7 @@ static void smp_mb_master(void) #ifdef RCU_SIGNAL static void force_mb_all_readers(void) { - struct rcu_reader *index; + struct urcu_reader *index; /* * Ask for each threads to execute a cmm_smp_mb() so we can consider the @@ -270,7 +297,7 @@ static void wait_for_readers(struct cds_list_head *input_readers, struct cds_list_head *qsreaders) { unsigned int wait_loops = 0; - struct rcu_reader *index, *tmp; + struct urcu_reader *index, *tmp; #ifdef HAS_INCOHERENT_CACHES unsigned int wait_gp_loops = 0; #endif /* HAS_INCOHERENT_CACHES */ @@ -290,18 +317,18 @@ static void wait_for_readers(struct cds_list_head *input_readers, } cds_list_for_each_entry_safe(index, tmp, input_readers, node) { - switch (rcu_reader_state(&index->ctr)) { - case RCU_READER_ACTIVE_CURRENT: + switch (urcu_common_reader_state(&rcu_gp, &index->ctr)) { + case URCU_READER_ACTIVE_CURRENT: if (cur_snap_readers) { cds_list_move(&index->node, cur_snap_readers); break; } /* Fall-through */ - case RCU_READER_INACTIVE: + case URCU_READER_INACTIVE: cds_list_move(&index->node, qsreaders); break; - case RCU_READER_ACTIVE_OLD: + case URCU_READER_ACTIVE_OLD: /* * Old snapshot. Leaving node in * input_readers will make us busy-loop @@ -441,7 +468,7 @@ void synchronize_rcu(void) cmm_smp_mb(); /* Switch parity: 0 -> 1, 1 -> 0 */ - CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ RCU_GP_CTR_PHASE); + CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ URCU_GP_CTR_PHASE); /* * Must commit rcu_gp.ctr update to memory before waiting for quiescent @@ -488,6 +515,8 @@ out: */ urcu_wake_all_waiters(&waiters); } +URCU_ATTR_ALIAS(urcu_stringify(synchronize_rcu)) +void alias_synchronize_rcu(); /* * library wrappers to be used by non-LGPL compatible source code. @@ -497,22 +526,28 @@ void rcu_read_lock(void) { _rcu_read_lock(); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_read_lock)) +void alias_rcu_read_lock(); void rcu_read_unlock(void) { _rcu_read_unlock(); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_read_unlock)) +void alias_rcu_read_unlock(); int rcu_read_ongoing(void) { return _rcu_read_ongoing(); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_read_ongoing)) +void alias_rcu_read_ongoing(); void rcu_register_thread(void) { URCU_TLS(rcu_reader).tid = pthread_self(); assert(URCU_TLS(rcu_reader).need_mb == 0); - assert(!(URCU_TLS(rcu_reader).ctr & RCU_GP_CTR_NEST_MASK)); + assert(!(URCU_TLS(rcu_reader).ctr & URCU_GP_CTR_NEST_MASK)); mutex_lock(&rcu_registry_lock); assert(!URCU_TLS(rcu_reader).registered); @@ -521,6 +556,8 @@ void rcu_register_thread(void) cds_list_add(&URCU_TLS(rcu_reader).node, ®istry); mutex_unlock(&rcu_registry_lock); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_register_thread)) +void alias_rcu_register_thread(); void rcu_unregister_thread(void) { @@ -530,20 +567,57 @@ void rcu_unregister_thread(void) cds_list_del(&URCU_TLS(rcu_reader).node); mutex_unlock(&rcu_registry_lock); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_unregister_thread)) +void alias_rcu_unregister_thread(); #ifdef RCU_MEMBARRIER -void rcu_init(void) + +#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER +static +void rcu_sys_membarrier_status(bool available) { - int ret; + if (!available) + abort(); +} +#else +static +void rcu_sys_membarrier_status(bool available) +{ + if (!available) + return; + urcu_memb_has_sys_membarrier = 1; +} +#endif +static +void rcu_sys_membarrier_init(void) +{ + bool available = false; + int mask; + + mask = membarrier(MEMBARRIER_CMD_QUERY, 0); + if (mask >= 0) { + if (mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED) { + if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0)) + urcu_die(errno); + urcu_memb_has_sys_membarrier_private_expedited = 1; + available = true; + } else if (mask & MEMBARRIER_CMD_SHARED) { + available = true; + } + } + rcu_sys_membarrier_status(available); +} + +void rcu_init(void) +{ if (init_done) return; init_done = 1; - ret = membarrier(MEMBARRIER_CMD_QUERY, 0); - if (ret >= 0 && (ret & MEMBARRIER_CMD_SHARED)) { - rcu_has_sys_membarrier = 1; - } + rcu_sys_membarrier_init(); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_init)) +void alias_rcu_init(void); #endif #ifdef RCU_SIGNAL @@ -583,6 +657,8 @@ void rcu_init(void) if (ret) urcu_die(errno); } +URCU_ATTR_ALIAS(urcu_stringify(rcu_init)) +void alias_rcu_init(void); void rcu_exit(void) { @@ -595,10 +671,13 @@ void rcu_exit(void) * assert(cds_list_empty(®istry)); */ } +URCU_ATTR_ALIAS(urcu_stringify(rcu_exit)) +void alias_rcu_exit(void); #endif /* #ifdef RCU_SIGNAL */ DEFINE_RCU_FLAVOR(rcu_flavor); +DEFINE_RCU_FLAVOR_ALIAS(rcu_flavor, alias_rcu_flavor); #include "urcu-call-rcu-impl.h" #include "urcu-defer-impl.h"