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