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