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