| tls-compat.h | | tls-compat.h | |
| | | | |
| skipping to change at line 73 | | skipping to change at line 73 | |
| * Moreover, URCU_TLS variables should not be touched from signal | | * Moreover, URCU_TLS variables should not be touched from signal | |
| * handlers setup with with sigaltstack(2). | | * handlers setup with with sigaltstack(2). | |
| */ | | */ | |
| | | | |
| # define DECLARE_URCU_TLS(type, name) \ | | # define DECLARE_URCU_TLS(type, name) \ | |
| CONFIG_RCU_TLS type name | | CONFIG_RCU_TLS type name | |
| | | | |
| # define DEFINE_URCU_TLS(type, name) \ | | # define DEFINE_URCU_TLS(type, name) \ | |
| CONFIG_RCU_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) | | # define URCU_TLS(name) (name) | |
| | | | |
| #else /* #ifndef CONFIG_RCU_TLS */ | | #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> | | # include <pthread.h> | |
| | | | |
| struct urcu_tls { | | struct urcu_tls { | |
| pthread_key_t key; | | pthread_key_t key; | |
| pthread_mutex_t init_mutex; | | pthread_mutex_t init_mutex; | |
| int init_done; | | int init_done; | |
| }; | | }; | |
| | | | |
|
| | | # define DECLARE_URCU_TLS_1(type, name) \ | |
| | | type *__tls_access2_ ## name(void) | |
| | | | |
| # define DECLARE_URCU_TLS(type, name) \ | | # define DECLARE_URCU_TLS(type, name) \ | |
|
| type *__tls_access_ ## name(void) | | DECLARE_URCU_TLS_1(type, name) | |
| | | | |
| /* | | /* | |
| * Note: we don't free memory at process exit, since it will be dealt | | * Note: we don't free memory at process exit, since it will be dealt | |
| * with by the OS. | | * with by the OS. | |
| */ | | */ | |
|
| # define DEFINE_URCU_TLS(type, name) \ | | # define __URCU_TLS_CALL_1(name) \ | |
| type *__tls_access_ ## name(void) \ | | __tls_access2_ ## name | |
| | | | |
| | | # define __URCU_TLS_CALL(name) \ | |
| | | __URCU_TLS_CALL_1(name) | |
| | | | |
| | | # define DEFINE_URCU_TLS_1(type, name) \ | |
| | | type *__tls_access2_ ## name(void) \ | |
| { \ | | { \ | |
| static struct urcu_tls __tls_ ## name = { \ | | static struct urcu_tls __tls_ ## name = { \ | |
| .init_mutex = PTHREAD_MUTEX_INITIALIZER,\ | | .init_mutex = PTHREAD_MUTEX_INITIALIZER,\ | |
| .init_done = 0, \ | | .init_done = 0, \ | |
| }; \ | | }; \ | |
| void *__tls_p; \ | | void *__tls_p; \ | |
| if (!__tls_ ## name.init_done) { \ | | if (!__tls_ ## name.init_done) { \ | |
| /* Mutex to protect concurrent init */ \ | | /* Mutex to protect concurrent init */ \ | |
| pthread_mutex_lock(&__tls_ ## name.init_mutex); \ | | pthread_mutex_lock(&__tls_ ## name.init_mutex); \ | |
| if (!__tls_ ## name.init_done) { \ | | if (!__tls_ ## name.init_done) { \ | |
| | | | |
| skipping to change at line 121 | | skipping to change at line 142 | |
| cmm_smp_rmb(); /* read init_done before getting key */ \ | | cmm_smp_rmb(); /* read init_done before getting key */ \ | |
| __tls_p = pthread_getspecific(__tls_ ## name.key); \ | | __tls_p = pthread_getspecific(__tls_ ## name.key); \ | |
| if (caa_unlikely(__tls_p == NULL)) { \ | | if (caa_unlikely(__tls_p == NULL)) { \ | |
| __tls_p = calloc(1, sizeof(type)); \ | | __tls_p = calloc(1, sizeof(type)); \ | |
| (void) pthread_setspecific(__tls_ ## name.key, \ | | (void) pthread_setspecific(__tls_ ## name.key, \ | |
| __tls_p); \ | | __tls_p); \ | |
| } \ | | } \ | |
| return __tls_p; \ | | return __tls_p; \ | |
| } | | } | |
| | | | |
|
| # define URCU_TLS(name) (*__tls_access_ ## name()) | | /* | |
| | | * Define with and 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 f | |
| | | or multiple concurrent flavors. Please upgrade liburcu libraries and header | |
| | | s, 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_access2_ ## name()) | |
| | | | |
| | | # define URCU_TLS(name) URCU_TLS_1(name) | |
| | | | |
| #endif /* #else #ifndef CONFIG_RCU_TLS */ | | #endif /* #else #ifndef CONFIG_RCU_TLS */ | |
| | | | |
| #ifdef __cplusplus | | #ifdef __cplusplus | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| #endif /* _URCU_TLS_COMPAT_H */ | | #endif /* _URCU_TLS_COMPAT_H */ | |
| | | | |
End of changes. 6 change blocks. |
| 4 lines changed or deleted | | 54 lines changed or added | |
|
| urcu-qsbr.h | | urcu-qsbr.h | |
| | | | |
| skipping to change at line 93 | | skipping to change at line 93 | |
| | | | |
| /* | | /* | |
| * QSBR read lock/unlock are guaranteed to be no-ops. Therefore, we expose
them | | * QSBR read lock/unlock are guaranteed to be no-ops. Therefore, we expose
them | |
| * in the LGPL header for any code to use. However, the debug version is no
t | | * in the LGPL header for any code to use. However, the debug version is no
t | |
| * nops and may contain sanity checks. To activate it, applications must be | | * nops and may contain sanity checks. To activate it, applications must be | |
| * recompiled with -DRCU_DEBUG (even non-LGPL/GPL applications). This is th
e | | * recompiled with -DRCU_DEBUG (even non-LGPL/GPL applications). This is th
e | |
| * best trade-off between license/performance/code triviality and | | * best trade-off between license/performance/code triviality and | |
| * library debugging & tracing features we could come up with. | | * library debugging & tracing features we could come up with. | |
| */ | | */ | |
| | | | |
|
| #if (!defined(BUILD_QSBR_LIB) && defined(RCU_DEBUG)) | | #if (!defined(BUILD_QSBR_LIB) && !defined(RCU_DEBUG)) | |
| | | | |
| static inline void rcu_read_lock(void) | | static inline void rcu_read_lock(void) | |
| { | | { | |
| } | | } | |
| | | | |
| static inline void rcu_read_unlock(void) | | static inline void rcu_read_unlock(void) | |
| { | | { | |
| } | | } | |
| | | | |
| #else /* !RCU_DEBUG */ | | #else /* !RCU_DEBUG */ | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|