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 { \ 71 fprintf (stderr, "MPFR lock failure\n"); \ 72 abort (); \ 73 } \ 74 } while (0) 75 76 #define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(mtx_init(&(_lock), mtx_plain)) 77 #define MPFR_LOCK_CLEAR(_lock) do { mtx_destroy(&(_lock)); } while (0) 78 #define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(mtx_lock(&(_lock))) 79 #define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock))) 80 #define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(mtx_lock(&(_lock))) 81 #define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(mtx_unlock(&(_lock))) 82 83 #define MPFR_LOCK_READ2WRITE(_lock) do {} while (0) 84 #define MPFR_LOCK_WRITE2READ(_lock) do {} while (0) 85 86 #define MPFR_ONCE_DECL(_once) \ 87 once_flag _once; 88 89 #define MPFR_ONCE_INIT_VALUE ONCE_FLAG_INIT 90 91 #define MPFR_ONCE_CALL(_once, _func) do { \ 92 call_once(&(_once), (_func)); \ 93 } while (0) 94 95 #define MPFR_NEED_DEFERRED_INIT 1 96 97 98 /**************************************************************************/ 99 /**************************************************************************/ 100 /* POSIX version */ 101 /**************************************************************************/ 102 /**************************************************************************/ 103 104 #elif defined (HAVE_PTHREAD) 105 106 #define MPFR_THREAD_LOCK_METHOD "pthread" 107 108 #include <pthread.h> 109 110 #define MPFR_LOCK_DECL(_lock) \ 111 pthread_rwlock_t _lock; 112 113 #define MPFR_LOCK_C(E) \ 114 do { \ 115 if ((E) != 0) \ 116 { \ 117 fprintf (stderr, "MPFR lock failure\n"); \ 118 abort (); \ 119 } \ 120 } while (0) 121 122 #define MPFR_LOCK_INIT(_lock) MPFR_LOCK_C(pthread_rwlock_init(&(_lock), NULL)) 123 124 #define MPFR_LOCK_CLEAR(_lock) do { \ 125 pthread_rwlock_destroy(&(_lock)); \ 126 } while (0) 127 128 #define MPFR_LOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_rdlock(&(_lock))) 129 #define MPFR_UNLOCK_READ(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock))) 130 #define MPFR_LOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_wrlock(&(_lock))) 131 #define MPFR_UNLOCK_WRITE(_lock) MPFR_LOCK_C(pthread_rwlock_unlock(&(_lock))) 132 133 #define MPFR_LOCK_READ2WRITE(_lock) do { \ 134 MPFR_UNLOCK_READ(_lock); \ 135 MPFR_LOCK_WRITE(_lock); \ 136 } while (0) 137 138 #define MPFR_LOCK_WRITE2READ(_lock) do { \ 139 MPFR_UNLOCK_WRITE(_lock); \ 140 MPFR_LOCK_READ(_lock); \ 141 } while (0) 142 143 #define MPFR_ONCE_DECL(_once) \ 144 pthread_once_t _once ; 145 146 #define MPFR_ONCE_INIT_VALUE PTHREAD_ONCE_INIT 147 148 #define MPFR_ONCE_CALL(_once, _func) \ 149 MPFR_LOCK_C(pthread_once (&(_once), (_func))) 150 151 #define MPFR_NEED_DEFERRED_INIT 1 152 153 #else 154 155 /* TODO: Win32 */ 156 # error "No thread lock / unsupported OS." 157 158 #endif 159 160 #else 161 162 /**************************************************************************/ 163 /**************************************************************************/ 164 /* No lock thread version */ 165 /**************************************************************************/ 166 /**************************************************************************/ 167 168 #define MPFR_LOCK_DECL(_lock) 169 #define MPFR_LOCK_INIT(_lock) do {} while (0) 170 #define MPFR_LOCK_CLEAR(_lock) do {} while (0) 171 #define MPFR_LOCK_READ(_lock) do {} while (0) 172 #define MPFR_UNLOCK_READ(_lock) do {} while (0) 173 #define MPFR_LOCK_WRITE(_lock) do {} while (0) 174 #define MPFR_UNLOCK_WRITE(_lock) do {} while (0) 175 #define MPFR_LOCK_READ2WRITE(_lock) do {} while (0) 176 #define MPFR_LOCK_WRITE2READ(_lock) do {} while (0) 177 #define MPFR_ONCE_INIT_VALUE 178 #define MPFR_ONCE_DECL(_once) 179 #define MPFR_ONCE_CALL(_once,_func) do {} while (0) 180 181 #endif 182 183 184 185 /**************************************************************************/ 186 /**************************************************************************/ 187 188 /**************************************************************************/ 189 /**************************************************************************/ 190 191 /* If MPFR Needs a way to init data before using them */ 192 #if defined(MPFR_NEED_DEFERRED_INIT) 193 194 #if defined(MPFR_HAVE_CONSTRUCTOR_ATTR) 195 196 /*********************** Use constructor extension ************************/ 197 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id, _init, _clear) \ 198 __attribute__ ((constructor)) static void \ 199 mpfr_init_cache_ ## _id (void) { \ 200 _init ; \ 201 } \ 202 __attribute__ ((destructor)) static void \ 203 mpfr_clean_cache_ ## _id (void) { \ 204 _clear; \ 205 } 206 207 #define MPFR_DEFERRED_INIT_CALL(_master) do {} while (0) 208 #define MPFR_DEFERRED_INIT_SLAVE_DECL() 209 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) 210 211 #else 212 213 /**************************** Use once semantic ***************************/ 214 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id, _init, _clear) \ 215 static void mpfr_once_ ## _id ## _clear_func (void) { \ 216 _clear ; \ 217 } \ 218 static void mpfr_once_ ## _id ## _init_func (void) { \ 219 _init; \ 220 atexit(mpfr_once_ ## _id ## _clear_func); \ 221 } 222 223 #define MPFR_DEFERRED_INIT_CALL(_master) \ 224 MPFR_ONCE_CALL((_master)->once, (_master)->init_once) 225 226 #define MPFR_DEFERRED_INIT_SLAVE_DECL() \ 227 MPFR_ONCE_DECL(once) \ 228 void (*init_once)(void); 229 230 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) \ 231 , MPFR_ONCE_INIT_VALUE, mpfr_once_ ## _id ## _init_func 232 233 #endif 234 235 #else 236 237 /* No need */ 238 #define MPFR_DEFERRED_INIT_MASTER_DECL(_id_lock, _init, _clear) 239 #define MPFR_DEFERRED_INIT_CALL(_master) do {} while (0) 240 #define MPFR_DEFERRED_INIT_SLAVE_DECL() 241 #define MPFR_DEFERRED_INIT_SLAVE_VALUE(_id) 242 243 #endif 244 245 /**************************************************************************/ 246 247 #endif 248