Keep ABI compatible with already compiled LGPL applications
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 1 Nov 2013 19:53:51 +0000 (15:53 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 1 Nov 2013 20:19:54 +0000 (16:19 -0400)
Applications with _LGPL_SOURCE defined that were compiled against bogus
tls-compat.h header *and* which are using multiple urcu flavors
concurrently need to be told that they need to be recompiled against a
fixed tls-compat.h header. Detect these usage, and abort() with a
message error on stderr.

This is needed for stable-0.7 and stable-0.8 branches of userspace RCU
only. The upcoming 0.9 will bump the soname version, and therefore does
not have to care about this aspect of ABI compatibility.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
tests/benchmark/test_urcu_hash.c
urcu-bp.c
urcu-qsbr.c
urcu.c
urcu/tls-compat.h

index f862adbf92c58d827dfaf0fc1601ebe5a1c4b212..6cfb01e371da2ca5b12f52cd76ac88cc10cad89d 100644 (file)
@@ -82,13 +82,13 @@ int (*get_populate_hash_cb(void))(void)
        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;
 
index 387a52bf892df54cfcac0f14868ad70b2e8d1959..fb5ca6ccf4317a7ebb710d2d664e115b267e4515 100644 (file)
--- a/urcu-bp.c
+++ b/urcu-bp.c
@@ -105,7 +105,7 @@ static pthread_key_t urcu_bp_key;
 
 #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 };
@@ -114,7 +114,7 @@ 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);
 
index d6adc5bfaafa9d4d851842bad7d398967b081eec..2cd6c126d8dd8d78ebd7877a88f324ea64cab0c7 100644 (file)
@@ -64,11 +64,11 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_ONLINE };
  * 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);
diff --git a/urcu.c b/urcu.c
index 759b94bdb9e9550e178caa04904e6048c7810b2c..e391e6295b5c04511bec857c4792287559be3e19 100644 (file)
--- a/urcu.c
+++ b/urcu.c
@@ -107,11 +107,11 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT };
  * 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);
index 8ac1ea0615ddc2eb91ee51e9e15b89bd094d4c81..81b5f0c659b7a69b620fb3772566ecfb684703fc 100644 (file)
@@ -70,12 +70,20 @@ extern "C" {
 # 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>
@@ -87,7 +95,8 @@ struct urcu_tls {
 };
 
 # 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)
 
@@ -95,8 +104,14 @@ struct urcu_tls {
  * 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,\
@@ -124,10 +139,32 @@ struct urcu_tls {
                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)
 
This page took 0.029211 seconds and 4 git commands to generate.