mpfr-thread.h revision 1.1.1.5
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 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