mpfr-thread.h revision 1.1.1.6
1/* MPFR internal header related to thread-local variables. 2 3Copyright 2005-2023 Free Software Foundation, Inc. 4Contributed by the AriC and Caramba projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 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