Fix the Win32 implementation of the 'thread' module.
[gnulib.git] / lib / glthread / thread.h
1 /* Creating and controlling threads.
2    Copyright (C) 2005-2008 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
19    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
20    gthr-win32.h.  */
21
22 /* This file contains primitives for creating and controlling threads.
23
24    Thread data type: gl_thread_t.
25
26    Creating a thread:
27        thread = gl_thread_create (func, arg);
28    Or with control of error handling:
29        err = glthread_create (&thread, func, arg);
30        extern int glthread_create (gl_thread_t *result,
31                                    void *(*func) (void *), void *arg);
32
33    Querying and changing the signal mask of a thread (not supported on all
34    platforms):
35        gl_thread_sigmask (how, newmask, oldmask);
36    Or with control of error handling:
37        err = glthread_sigmask (how, newmask, oldmask);
38        extern int glthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask);
39
40    Waiting for termination of another thread:
41        gl_thread_join (thread, &return_value);
42    Or with control of error handling:
43        err = glthread_join (thread, &return_value);
44        extern int glthread_join (gl_thread_t thread, void **return_value_ptr);
45
46    Getting a reference to the current thread:
47        current = gl_thread_self ();
48        extern gl_thread_t gl_thread_self (void);
49
50    Terminating the current thread:
51        gl_thread_exit (return_value);
52        extern void gl_thread_exit (void *return_value) __attribute__ ((noreturn));
53
54    Requesting custom code to be executed at fork() time(not supported on all
55    platforms):
56        gl_thread_atfork (prepare_func, parent_func, child_func);
57    Or with control of error handling:
58        err = glthread_atfork (prepare_func, parent_func, child_func);
59        extern int glthread_atfork (void (*prepare_func) (void),
60                                    void (*parent_func) (void),
61                                    void (*child_func) (void));
62    Note that even on platforms where this is supported, use of fork() and
63    threads together is problematic, see
64      <http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html>
65  */
66
67
68 #ifndef _GLTHREAD_THREAD_H
69 #define _GLTHREAD_THREAD_H
70
71 #include <errno.h>
72 #include <stdlib.h>
73
74 /* ========================================================================= */
75
76 #if USE_POSIX_THREADS
77
78 /* Use the POSIX threads library.  */
79
80 # include <pthread.h>
81
82 # ifdef __cplusplus
83 extern "C" {
84 # endif
85
86 # if PTHREAD_IN_USE_DETECTION_HARD
87
88 /* The pthread_in_use() detection needs to be done at runtime.  */
89 #  define pthread_in_use() \
90      glthread_in_use ()
91 extern int glthread_in_use (void);
92
93 # endif
94
95 # if USE_POSIX_THREADS_WEAK
96
97 /* Use weak references to the POSIX threads library.  */
98
99 /* Weak references avoid dragging in external libraries if the other parts
100    of the program don't use them.  Here we use them, because we don't want
101    every program that uses libintl to depend on libpthread.  This assumes
102    that libpthread would not be loaded after libintl; i.e. if libintl is
103    loaded first, by an executable that does not depend on libpthread, and
104    then a module is dynamically loaded that depends on libpthread, libintl
105    will not be multithread-safe.  */
106
107 /* The way to test at runtime whether libpthread is present is to test
108    whether a function pointer's value, such as &pthread_mutex_init, is
109    non-NULL.  However, some versions of GCC have a bug through which, in
110    PIC mode, &foo != NULL always evaluates to true if there is a direct
111    call to foo(...) in the same function.  To avoid this, we test the
112    address of a function in libpthread that we don't use.  */
113
114 #  pragma weak pthread_create
115 #  pragma weak pthread_sigmask
116 #  pragma weak pthread_join
117 #  ifndef pthread_self
118 #   pragma weak pthread_self
119 #  endif
120 #  pragma weak pthread_exit
121 #  if HAVE_PTHREAD_ATFORK
122 #   pragma weak pthread_atfork
123 #  endif
124
125 #  if !PTHREAD_IN_USE_DETECTION_HARD
126 #   pragma weak pthread_cancel
127 #   define pthread_in_use() (pthread_cancel != NULL)
128 #  endif
129
130 # else
131
132 #  if !PTHREAD_IN_USE_DETECTION_HARD
133 #   define pthread_in_use() 1
134 #  endif
135
136 # endif
137
138 /* -------------------------- gl_thread_t datatype -------------------------- */
139
140 typedef pthread_t gl_thread_t;
141 # define glthread_create(THREADP, FUNC, ARG) \
142     (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
143 # define glthread_sigmask(HOW, SET, OSET) \
144     (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
145 # define glthread_join(THREAD, RETVALP) \
146     (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
147 # define gl_thread_self() \
148     (pthread_in_use () ? (void *) pthread_self () : NULL)
149 # define gl_thread_exit(RETVAL) \
150     (pthread_in_use () ? pthread_exit (RETVAL) : 0)
151
152 # if HAVE_PTHREAD_ATFORK
153 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \
154      (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0)
155 # else
156 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
157 # endif
158
159 # ifdef __cplusplus
160 }
161 # endif
162
163 #endif
164
165 /* ========================================================================= */
166
167 #if USE_PTH_THREADS
168
169 /* Use the GNU Pth threads library.  */
170
171 # include <pth.h>
172
173 # ifdef __cplusplus
174 extern "C" {
175 # endif
176
177 # if USE_PTH_THREADS_WEAK
178
179 /* Use weak references to the GNU Pth threads library.  */
180
181 #  pragma weak pth_spawn
182 #  pragma weak pth_sigmask
183 #  pragma weak pth_join
184 #  pragma weak pth_self
185 #  pragma weak pth_exit
186
187 #  pragma weak pth_cancel
188 #  define pth_in_use() (pth_cancel != NULL)
189
190 # else
191
192 #  define pth_in_use() 1
193
194 # endif
195 /* -------------------------- gl_thread_t datatype -------------------------- */
196
197 typedef pth_t gl_thread_t;
198 # define glthread_create(THREADP, FUNC, ARG) \
199     (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno) : 0)
200 # define glthread_sigmask(HOW, SET, OSET) \
201     (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0)
202 # define glthread_join(THREAD, RETVALP) \
203     (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0)
204 # define gl_thread_self() \
205     (pth_in_use () ? (void *) pth_self () : 0)
206 # define gl_thread_exit(RETVAL) \
207     (pth_in_use () ? pth_exit (RETVAL) : 0)
208 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
209
210 # ifdef __cplusplus
211 }
212 # endif
213
214 #endif
215
216 /* ========================================================================= */
217
218 #if USE_SOLARIS_THREADS
219
220 /* Use the old Solaris threads library.  */
221
222 # include <thread.h>
223 # include <synch.h>
224
225 # ifdef __cplusplus
226 extern "C" {
227 # endif
228
229 # if USE_SOLARIS_THREADS_WEAK
230
231 /* Use weak references to the old Solaris threads library.  */
232
233 #  pragma weak thr_create
234 #  pragma weak thr_join
235 #  pragma weak thr_self
236 #  pragma weak thr_exit
237
238 #  pragma weak thr_suspend
239 #  define thread_in_use() (thr_suspend != NULL)
240
241 # else
242
243 #  define thread_in_use() 1
244
245 # endif
246
247 /* -------------------------- gl_thread_t datatype -------------------------- */
248
249 typedef thread_t gl_thread_t;
250 # define glthread_create(THREADP, FUNC, ARG) \
251     (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0)
252 # define glthread_sigmask(HOW, SET, OSET) \
253     (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
254 # define glthread_join(THREAD, RETVALP) \
255     (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
256 # define gl_thread_self() \
257     (thread_in_use () ? (void *) thr_self () : 0)
258 # define gl_thread_exit(RETVAL) \
259     (thread_in_use () ? thr_exit (RETVAL) : 0)
260 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
261
262 # ifdef __cplusplus
263 }
264 # endif
265
266 #endif
267
268 /* ========================================================================= */
269
270 #if USE_WIN32_THREADS
271
272 # include <windows.h>
273
274 # ifdef __cplusplus
275 extern "C" {
276 # endif
277
278 /* -------------------------- gl_thread_t datatype -------------------------- */
279
280 /* The gl_thread_t is a pointer to a structure in memory.
281    Why not the thread handle?  If it were the thread handle, it would be hard
282    to implement gl_thread_self() (since GetCurrentThread () returns a pseudo-
283    handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be
284    closed afterwards, and there is no function for quickly retrieving a thread
285    handle from its id).
286    Why not the thread id?  I tried it.  It did not work: Sometimes ids appeared
287    that did not belong to running threads, and glthread_join failed with ESRCH.
288  */
289 typedef struct gl_thread_struct *gl_thread_t;
290 # define glthread_create(THREADP, FUNC, ARG) \
291     glthread_create_func (THREADP, FUNC, ARG)
292 # define glthread_sigmask(HOW, SET, OSET) \
293     /* unsupported */ 0
294 # define glthread_join(THREAD, RETVALP) \
295     glthread_join_func (THREAD, RETVALP)
296 # define gl_thread_self() \
297     gl_thread_self_func ()
298 # define gl_thread_exit(RETVAL) \
299     gl_thread_exit_func (RETVAL)
300 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
301 extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg);
302 extern int glthread_join_func (gl_thread_t thread, void **retvalp);
303 extern gl_thread_t gl_thread_self_func (void);
304 extern int gl_thread_exit_func (void *retval);
305
306 # ifdef __cplusplus
307 }
308 # endif
309
310 #endif
311
312 /* ========================================================================= */
313
314 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
315
316 /* Provide dummy implementation if threads are not supported.  */
317
318 typedef int gl_thread_t;
319 # define glthread_create(THREADP, FUNC, ARG) ENOSYS
320 # define glthread_sigmask(HOW, SET, OSET) 0
321 # define glthread_join(THREAD, RETVALP) 0
322 # define gl_thread_self() NULL
323 # define gl_thread_exit(RETVAL) 0
324 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
325
326 #endif
327
328 /* ========================================================================= */
329
330 /* Macros with built-in error handling.  */
331
332 #ifdef __cplusplus
333 extern "C" {
334 #endif
335
336 static inline gl_thread_t
337 gl_thread_create (void *(*func) (void *arg), void *arg)
338 {
339   gl_thread_t thread;
340   int ret;
341
342   ret = glthread_create (&thread, func, arg);
343   if (ret != 0)
344     abort ();
345   return thread;
346 }
347 #define gl_thread_sigmask(HOW, SET, OSET)     \
348    do                                         \
349      {                                        \
350        if (glthread_sigmask (HOW, SET, OSET)) \
351          abort ();                            \
352      }                                        \
353    while (0)
354 #define gl_thread_join(THREAD, RETVAL)     \
355    do                                      \
356      {                                     \
357        if (glthread_join (THREAD, RETVAL)) \
358          abort ();                         \
359      }                                     \
360    while (0)
361 #define gl_thread_atfork(PREPARE, PARENT, CHILD)     \
362    do                                                \
363      {                                               \
364        if (glthread_atfork (PREPARE, PARENT, CHILD)) \
365          abort ();                                   \
366      }                                               \
367    while (0)
368
369 #ifdef __cplusplus
370 }
371 #endif
372
373 #endif /* _GLTHREAD_THREAD_H */