xref: /netbsd-src/external/lgpl3/mpfr/dist/src/mpfr-thread.h (revision 901e7e84758515fbf39dfc064cb0b45ab146d8b0)
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       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