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