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