Home | History | Annotate | Line # | Download | only in urcu
      1  1.1  christos // SPDX-FileCopyrightText: 2012 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      2  1.1  christos //
      3  1.1  christos // SPDX-License-Identifier: LGPL-2.1-or-later
      4  1.1  christos 
      5  1.1  christos #ifndef _URCU_TLS_COMPAT_H
      6  1.1  christos #define _URCU_TLS_COMPAT_H
      7  1.1  christos 
      8  1.1  christos /*
      9  1.1  christos  * Userspace RCU library - Thread-Local Storage Compatibility Header
     10  1.1  christos  */
     11  1.1  christos 
     12  1.1  christos #include <stdlib.h>
     13  1.1  christos #include <urcu/config.h>
     14  1.1  christos #include <urcu/compiler.h>
     15  1.1  christos #include <urcu/arch.h>
     16  1.1  christos 
     17  1.1  christos #ifdef __cplusplus
     18  1.1  christos extern "C" {
     19  1.1  christos #endif
     20  1.1  christos 
     21  1.1  christos #ifdef CONFIG_RCU_TLS
     22  1.1  christos 
     23  1.1  christos /*
     24  1.1  christos  * Default to '__thread' on all C and C++ compilers except MSVC. While C11 has
     25  1.1  christos  * '_Thread_local' and C++11 has 'thread_local', only '__thread' seems to have
     26  1.1  christos  * a compatible implementation when linking public extern symbols across
     27  1.1  christos  * language boundaries.
     28  1.1  christos  *
     29  1.1  christos  * For more details, see 'https://gcc.gnu.org/onlinedocs/gcc/Thread-Local.html'.
     30  1.1  christos  */
     31  1.1  christos #if defined(_MSC_VER)
     32  1.1  christos # define URCU_TLS_STORAGE_CLASS	__declspec(thread)
     33  1.1  christos #else
     34  1.1  christos # define URCU_TLS_STORAGE_CLASS	__thread
     35  1.1  christos #endif
     36  1.1  christos 
     37  1.1  christos /*
     38  1.1  christos  * Hint: How to define/declare TLS variables of compound types
     39  1.1  christos  *       such as array or function pointers?
     40  1.1  christos  *
     41  1.1  christos  * Answer: Use typedef to assign a type_name to the compound type.
     42  1.1  christos  * Example: Define a TLS variable which is an int array with len=4:
     43  1.1  christos  *
     44  1.1  christos  * 	typedef int my_int_array_type[4];
     45  1.1  christos  * 	DEFINE_URCU_TLS(my_int_array_type, var_name);
     46  1.1  christos  *
     47  1.1  christos  * Another example:
     48  1.1  christos  * 	typedef void (*call_rcu_flavor)(struct rcu_head *, XXXX);
     49  1.1  christos  * 	DECLARE_URCU_TLS(call_rcu_flavor, p_call_rcu);
     50  1.1  christos  *
     51  1.1  christos  * NOTE: URCU_TLS() is NOT async-signal-safe, you can't use it
     52  1.1  christos  * inside any function which can be called from signal handler.
     53  1.1  christos  *
     54  1.1  christos  * But if pthread_getspecific() is async-signal-safe in your
     55  1.1  christos  * platform, you can make URCU_TLS() async-signal-safe via:
     56  1.1  christos  * ensuring the first call to URCU_TLS() of a given TLS variable of
     57  1.1  christos  * all threads is called earliest from a non-signal handler function.
     58  1.1  christos  *
     59  1.1  christos  * Example: In any thread, the first call of URCU_TLS(rcu_reader)
     60  1.1  christos  * is called from rcu_register_thread(), so we can ensure all later
     61  1.1  christos  * URCU_TLS(rcu_reader) in any thread is async-signal-safe.
     62  1.1  christos  *
     63  1.1  christos  * Moreover, URCU_TLS variables should not be touched from signal
     64  1.1  christos  * handlers setup with with sigaltstack(2).
     65  1.1  christos  */
     66  1.1  christos 
     67  1.1  christos # define DECLARE_URCU_TLS(type, name)	\
     68  1.1  christos 	URCU_TLS_STORAGE_CLASS type name
     69  1.1  christos 
     70  1.1  christos # define DEFINE_URCU_TLS(type, name)	\
     71  1.1  christos 	URCU_TLS_STORAGE_CLASS type name
     72  1.1  christos 
     73  1.1  christos # define DEFINE_URCU_TLS_INIT(type, name, init)	\
     74  1.1  christos 	URCU_TLS_STORAGE_CLASS type name = (init)
     75  1.1  christos 
     76  1.1  christos # define URCU_TLS(name)		(name)
     77  1.1  christos 
     78  1.1  christos #else /* #ifndef CONFIG_RCU_TLS */
     79  1.1  christos 
     80  1.1  christos /*
     81  1.1  christos  * The *_1() macros ensure macro parameters are expanded.
     82  1.1  christos  */
     83  1.1  christos 
     84  1.1  christos # include <pthread.h>
     85  1.1  christos 
     86  1.1  christos struct urcu_tls {
     87  1.1  christos 	pthread_key_t key;
     88  1.1  christos 	pthread_mutex_t init_mutex;
     89  1.1  christos 	int init_done;
     90  1.1  christos };
     91  1.1  christos 
     92  1.1  christos # define DECLARE_URCU_TLS_1(type, name)				\
     93  1.1  christos 	type *__tls_access_ ## name(void)
     94  1.1  christos # define DECLARE_URCU_TLS(type, name)				\
     95  1.1  christos 	DECLARE_URCU_TLS_1(type, name)
     96  1.1  christos 
     97  1.1  christos /*
     98  1.1  christos  * Note: we don't free memory at process exit, since it will be dealt
     99  1.1  christos  * with by the OS.
    100  1.1  christos  */
    101  1.1  christos # define DEFINE_URCU_TLS_INIT_1(type, name, do_init)		\
    102  1.1  christos 	type *__tls_access_ ## name(void)			\
    103  1.1  christos 	{							\
    104  1.1  christos 		static struct urcu_tls __tls_ ## name = {	\
    105  1.1  christos 			.key = 0,				\
    106  1.1  christos 			.init_mutex = PTHREAD_MUTEX_INITIALIZER,\
    107  1.1  christos 			.init_done = 0,				\
    108  1.1  christos 		};						\
    109  1.1  christos 		__typeof__(type) *__tls_p;			\
    110  1.1  christos 		if (!__tls_ ## name.init_done) {		\
    111  1.1  christos 			/* Mutex to protect concurrent init */	\
    112  1.1  christos 			pthread_mutex_lock(&__tls_ ## name.init_mutex); \
    113  1.1  christos 			if (!__tls_ ## name.init_done) {	\
    114  1.1  christos 				(void) pthread_key_create(&__tls_ ## name.key, \
    115  1.1  christos 					free);			\
    116  1.1  christos 				cmm_smp_wmb();	/* create key before write init_done */ \
    117  1.1  christos 				__tls_ ## name.init_done = 1;	\
    118  1.1  christos 			}					\
    119  1.1  christos 			pthread_mutex_unlock(&__tls_ ## name.init_mutex); \
    120  1.1  christos 		}						\
    121  1.1  christos 		cmm_smp_rmb();	/* read init_done before getting key */ \
    122  1.1  christos 		__tls_p = (__typeof__(type) *) pthread_getspecific(__tls_ ## name.key); \
    123  1.1  christos 		if (caa_unlikely(__tls_p == NULL)) {		\
    124  1.1  christos 			__tls_p = (__typeof__(type) *) calloc(1, sizeof(type));	\
    125  1.1  christos 			do_init					\
    126  1.1  christos 			(void) pthread_setspecific(__tls_ ## name.key,	\
    127  1.1  christos 				__tls_p);			\
    128  1.1  christos 		}						\
    129  1.1  christos 		return __tls_p;					\
    130  1.1  christos 	}
    131  1.1  christos 
    132  1.1  christos # define _URCU_TLS_INIT(init)					\
    133  1.1  christos 	*__tls_p = (init);
    134  1.1  christos 
    135  1.1  christos # define DEFINE_URCU_TLS_INIT(type, name, init)			\
    136  1.1  christos 	DEFINE_URCU_TLS_INIT_1(type, name, _URCU_TLS_INIT(init))
    137  1.1  christos 
    138  1.1  christos # define DEFINE_URCU_TLS(type, name)				\
    139  1.1  christos 	DEFINE_URCU_TLS_INIT_1(type, name, /* empty */)
    140  1.1  christos 
    141  1.1  christos # define URCU_TLS_1(name)	(*__tls_access_ ## name())
    142  1.1  christos 
    143  1.1  christos # define URCU_TLS(name)		URCU_TLS_1(name)
    144  1.1  christos 
    145  1.1  christos #endif	/* #else #ifndef CONFIG_RCU_TLS */
    146  1.1  christos 
    147  1.1  christos #ifdef __cplusplus
    148  1.1  christos }
    149  1.1  christos #endif
    150  1.1  christos 
    151  1.1  christos #endif /* _URCU_TLS_COMPAT_H */
    152