return test_hash_cb[test_choice].populate_hash;
}
-DEFINE_URCU_TLS(unsigned int, rand_lookup);
-DEFINE_URCU_TLS(unsigned long, nr_add);
-DEFINE_URCU_TLS(unsigned long, nr_addexist);
-DEFINE_URCU_TLS(unsigned long, nr_del);
-DEFINE_URCU_TLS(unsigned long, nr_delnoent);
-DEFINE_URCU_TLS(unsigned long, lookup_fail);
-DEFINE_URCU_TLS(unsigned long, lookup_ok);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rand_lookup);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_add);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_addexist);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_del);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, nr_delnoent);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, lookup_fail);
+__DEFINE_URCU_TLS_GLOBAL(unsigned long, lookup_ok);
struct cds_lfht *test_ht;
#ifdef DEBUG_YIELD
unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
#endif
struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT };
* Pointer to registry elements. 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_GLOBAL(struct rcu_reader *, rcu_reader);
static CDS_LIST_HEAD(registry);
* 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_GLOBAL(struct rcu_reader, rcu_reader);
#ifdef DEBUG_YIELD
unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
#endif
static CDS_LIST_HEAD(registry);
* 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_GLOBAL(struct rcu_reader, rcu_reader);
#ifdef DEBUG_YIELD
unsigned int rcu_yield_active;
-DEFINE_URCU_TLS(unsigned int, rcu_rand_yield);
+__DEFINE_URCU_TLS_GLOBAL(unsigned int, rcu_rand_yield);
#endif
static CDS_LIST_HEAD(registry);
# define DEFINE_URCU_TLS(type, name) \
CONFIG_RCU_TLS type name
+# define __DEFINE_URCU_TLS_GLOBAL(type, name) \
+ CONFIG_RCU_TLS type name
+
# define URCU_TLS(name) (name)
#else /* #ifndef CONFIG_RCU_TLS */
/*
* The *_1() macros ensure macro parameters are expanded.
+ *
+ * __DEFINE_URCU_TLS_GLOBAL and __URCU_TLS_CALL exist for the sole
+ * purpose of notifying applications compiled against non-fixed 0.7 and
+ * 0.8 userspace RCU headers and using multiple flavors concurrently to
+ * recompile against fixed userspace RCU headers.
*/
# include <pthread.h>
};
# define DECLARE_URCU_TLS_1(type, name) \
- type *__tls_access_ ## name(void)
+ type *__tls_access2_ ## name(void)
+
# define DECLARE_URCU_TLS(type, name) \
DECLARE_URCU_TLS_1(type, name)
* Note: we don't free memory at process exit, since it will be dealt
* with by the OS.
*/
+# define __URCU_TLS_CALL_1(name) \
+ __tls_access2_ ## name
+
+# define __URCU_TLS_CALL(name) \
+ __URCU_TLS_CALL_1(name)
+
# define DEFINE_URCU_TLS_1(type, name) \
- type *__tls_access_ ## name(void) \
+ type *__tls_access2_ ## name(void) \
{ \
static struct urcu_tls __tls_ ## name = { \
.init_mutex = PTHREAD_MUTEX_INITIALIZER,\
return __tls_p; \
}
+/*
+ * Define with an without macro expansion to handle erroneous callers.
+ * Trigger an abort() if the caller application uses the clashing symbol
+ * if a weak symbol is overridden.
+ */
+# define __DEFINE_URCU_TLS_GLOBAL(type, name) \
+ DEFINE_URCU_TLS_1(type, name) \
+ int __urcu_tls_symbol_refcount_ ## name __attribute__((weak)); \
+ static __attribute__((constructor)) \
+ void __urcu_tls_inc_refcount_ ## name(void) \
+ { \
+ __urcu_tls_symbol_refcount_ ## name++; \
+ } \
+ type *__tls_access_ ## name(void) \
+ { \
+ if (__urcu_tls_symbol_refcount_ ## name > 1) { \
+ fprintf(stderr, "Error: Userspace RCU symbol clash for multiple concurrent flavors. Please upgrade liburcu libraries and headers, then recompile your application.\n"); \
+ abort(); \
+ } \
+ return __URCU_TLS_CALL(name)(); \
+ }
+
# define DEFINE_URCU_TLS(type, name) \
DEFINE_URCU_TLS_1(type, name)
-# define URCU_TLS_1(name) (*__tls_access_ ## name())
+# define URCU_TLS_1(name) (*__tls_access2_ ## name())
# define URCU_TLS(name) URCU_TLS_1(name)