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