1 /* MPFR internal header related to thread-local variables. 2 3 Copyright 2005-2023 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #ifndef __MPFR_THREAD_H__ 24 #define __MPFR_THREAD_H__ 25 26 /* Note: MPFR_NEED_THREAD_LOCK shall be defined before including this 27 header */ 28 29 /* Note: Let's define MPFR_THREAD_ATTR even after a #error to make the 30 error message more visible (e.g. gcc doesn't immediately stop after 31 the #error line and outputs many error messages if MPFR_THREAD_ATTR 32 is not defined). But some compilers will just output a message and 33 may build MPFR "successfully" (without thread support). */ 34 #ifndef MPFR_THREAD_ATTR 35 # ifdef MPFR_USE_THREAD_SAFE 36 # if defined(_MSC_VER) 37 # define MPFR_THREAD_ATTR __declspec( thread ) 38 # elif defined(MPFR_USE_C11_THREAD_SAFE) 39 # define MPFR_THREAD_ATTR _Thread_local 40 # else 41 # define MPFR_THREAD_ATTR __thread 42 # endif 43 # else 44 # define MPFR_THREAD_ATTR 45 # endif 46 #endif 47 48 /* If MPFR needs a lock mechanism for thread synchro */ 49 #ifdef MPFR_NEED_THREAD_LOCK 50 51 /**************************************************************************/ 52 /**************************************************************************/ 53 /* ISO C11 version */ 54 /**************************************************************************/ 55 /**************************************************************************/ 56 57 #if defined (MPFR_HAVE_C11_LOCK) 58 /* NOTE: This version has not been completely tested */ 59 60 #define MPFR_THREAD_LOCK_METHOD "C11" 61 62 #include <threads.h> 63 64 #define MPFR_LOCK_DECL(_lock) \ 65 mtx_t _lock; 66 67 #define MPFR_LOCK_C(E) \ 68 do { \ 69 if ((E) != thrd_success) \ 70 abort (); \ 71 } while (0) 72 73 #define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(mtx_init(&(_lock), mtx_plain)) 74 #define MPFR_LOCK_CLEAR(_lock) do { mtx_destroy(&(_lock)); } while (0) 75 #define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(mtx_lock(&(_lock))) 76 #define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock))) 77 #define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(mtx_lock(&(_lock))) 78 #define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock))) 79 80 #define MPFR_LOCK_READ2WRITE(_lock) do {} while (0) 81 #define MPFR_LOCK_WRITE2READ(_lock) do {} while (0) 82 83 #define MPFR_ONCE_DECL(_once) \ 84 once_flag _once; 85 86 #define MPFR_ONCE_INIT_VALUE ONCE_FLAG_INIT 87 88 #define MPFR_ONCE_CALL(_once, _func) do { \ 89 call_once(&(_once), (_func)); \ 90 } while (0) 91 92 #define MPFR_NEED_DEFERRED_INIT 1 93 94 95 /**************************************************************************/ 96 /**************************************************************************/ 97 /* POSIX version */ 98 /**************************************************************************/ 99 /**************************************************************************/ 100 101 #elif defined (HAVE_PTHREAD) 102 103 #define MPFR_THREAD_LOCK_METHOD "pthread" 104 105 #include <pthread.h> 106 107 #define MPFR_LOCK_DECL(_lock) \ 108 pthread_rwlock_t _lock; 109 110 #define MPFR_LOCK_C(E) \ 111 do { \ 112 if ((E) != 0) \ 113 abort (); \ 114 } while (0) 115 116 #define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(pthread_rwlock_init(&(_lock), NULL)) 117 118 #define MPFR_LOCK_CLEAR(_lock) do { \ 119 pthread_rwlock_destroy(&(_lock)); \ 120 } while (0) 121 122 #define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_rdlock(&(_lock))) 123 #define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock))) 124 #define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_wrlock(&(_lock))) 125 #define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock))) 126 127 #define MPFR_LOCK_READ2WRITE(_lock) do { \ 128 MPFR_UNLOCK_READ(_lock); \ 129 MPFR_LOCK_WRITE(_lock); \ 130 } while (0) 131 132 #define MPFR_LOCK_WRITE2READ(_lock) do { \ 133 MPFR_UNLOCK_WRITE(_lock); \ 134 MPFR_LOCK_READ(_lock); \ 135 } while (0) 136 137 #define MPFR_ONCE_DECL(_once) \ 138 pthread_once_t _once ; 139 140 #define MPFR_ONCE_INIT_VALUE PTHREAD_ONCE_INIT 141 142 #define MPFR_ONCE_CALL(_once, _func) \ 143 MPFR_LOCK_C(pthread_once (&(_once), (_func))) 144 145 #define MPFR_NEED_DEFERRED_INIT 1 146 147 #else 148 149 /* TODO: Win32 */ 150 # error "No thread lock / unsupported OS." 151 152 #endif 153 154 #else 155 156 /**************************************************************************/ 157 /**************************************************************************/ 158 /* No lock thread version */ 159 /**************************************************************************/ 160 /**************************************************************************/ 161 162 #define MPFR_LOCK_DECL(_lock) 163 #define MPFR_LOCK_INIT(_lock) do {} while (0) 164 #define MPFR_LOCK_CLEAR(_lock) do {} while (0) 165 #define MPFR_LOCK_READ(_lock) do {} while (0) 166 #define MPFR_UNLOCK_READ(_lock) do {} while (0) 167 #define MPFR_LOCK_WRITE(_lock) do {} while (0) 168 #define MPFR_UNLOCK_WRITE(_lock) do {} while (0) 169 #define MPFR_LOCK_READ2WRITE(_lock) do {} while (0) 170 #define MPFR_LOCK_WRITE2READ(_lock) do {} while (0) 171 #define MPFR_ONCE_INIT_VALUE 172 #define MPFR_ONCE_DECL(_once) 173 #define MPFR_ONCE_CALL(_once,_func) do {} while (0) 174 175 #endif 176 177 178 179 /**************************************************************************/ 180 /**************************************************************************/ 181 182 /**************************************************************************/ 183 /**************************************************************************/ 184 185 /* If MPFR Needs a way to init data before using them */ 186 #if defined(MPFR_NEED_DEFERRED_INIT) 187 188 #if defined(MPFR_HAVE_CONSTRUCTOR_ATTR) 189 190 /*********************** Use constructor extension ************************/ 191 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id, _init, _clear) \ 192 __attribute__ ((constructor)) static void \ 193 mpfr_init_cache_ ## _id (void) { \ 194 _init ; \ 195 } \ 196 __attribute__ ((destructor)) static void \ 197 mpfr_clean_cache_ ## _id (void) { \ 198 _clear; \ 199 } 200 201 #define MPFR_DEFERRED_INIT_CALL(_master) do {} while (0) 202 #define MPFR_DEFERRED_INIT_SLAVE_DECL() 203 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) 204 205 #else 206 207 /**************************** Use once semantic ***************************/ 208 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id, _init, _clear) \ 209 static void mpfr_once_ ## _id ## _clear_func (void) { \ 210 _clear ; \ 211 } \ 212 static void mpfr_once_ ## _id ## _init_func (void) { \ 213 _init; \ 214 atexit(mpfr_once_ ## _id ## _clear_func); \ 215 } 216 217 #define MPFR_DEFERRED_INIT_CALL(_master) \ 218 MPFR_ONCE_CALL((_master)->once, (_master)->init_once) 219 220 #define MPFR_DEFERRED_INIT_SLAVE_DECL() \ 221 MPFR_ONCE_DECL(once) \ 222 void (*init_once)(void); 223 224 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) \ 225 , MPFR_ONCE_INIT_VALUE, mpfr_once_ ## _id ## _init_func 226 227 #endif 228 229 #else 230 231 /* No need */ 232 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id_lock, _init, _clear) 233 #define MPFR_DEFERRED_INIT_CALL(_master) do {} while (0) 234 #define MPFR_DEFERRED_INIT_SLAVE_DECL() 235 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) 236 237 #endif 238 239 /**************************************************************************/ 240 241 #endif 242