1/* Creating and controlling threads. 2 Copyright (C) 2005-2010 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 3, 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 83extern "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 () 91extern 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/* This choice of gl_thread_t assumes that 141 pthread_equal (a, b) is equivalent to ((a) == (b)). 142 This is the case on all platforms in use in 2008. */ 143typedef pthread_t gl_thread_t; 144# define glthread_create(THREADP, FUNC, ARG) \ 145 (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS) 146# define glthread_sigmask(HOW, SET, OSET) \ 147 (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0) 148# define glthread_join(THREAD, RETVALP) \ 149 (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0) 150# define gl_thread_self() \ 151 (pthread_in_use () ? (void *) pthread_self () : NULL) 152# define gl_thread_exit(RETVAL) \ 153 (pthread_in_use () ? pthread_exit (RETVAL) : 0) 154 155# if HAVE_PTHREAD_ATFORK 156# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \ 157 (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0) 158# else 159# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 160# endif 161 162# ifdef __cplusplus 163} 164# endif 165 166#endif 167 168/* ========================================================================= */ 169 170#if USE_PTH_THREADS 171 172/* Use the GNU Pth threads library. */ 173 174# include <pth.h> 175 176# ifdef __cplusplus 177extern "C" { 178# endif 179 180# if USE_PTH_THREADS_WEAK 181 182/* Use weak references to the GNU Pth threads library. */ 183 184# pragma weak pth_spawn 185# pragma weak pth_sigmask 186# pragma weak pth_join 187# pragma weak pth_self 188# pragma weak pth_exit 189 190# pragma weak pth_cancel 191# define pth_in_use() (pth_cancel != NULL) 192 193# else 194 195# define pth_in_use() 1 196 197# endif 198/* -------------------------- gl_thread_t datatype -------------------------- */ 199 200typedef pth_t gl_thread_t; 201# define glthread_create(THREADP, FUNC, ARG) \ 202 (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno) : 0) 203# define glthread_sigmask(HOW, SET, OSET) \ 204 (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0) 205# define glthread_join(THREAD, RETVALP) \ 206 (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0) 207# define gl_thread_self() \ 208 (pth_in_use () ? (void *) pth_self () : 0) 209# define gl_thread_exit(RETVAL) \ 210 (pth_in_use () ? pth_exit (RETVAL) : 0) 211# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 212 213# ifdef __cplusplus 214} 215# endif 216 217#endif 218 219/* ========================================================================= */ 220 221#if USE_SOLARIS_THREADS 222 223/* Use the old Solaris threads library. */ 224 225# include <thread.h> 226# include <synch.h> 227 228# ifdef __cplusplus 229extern "C" { 230# endif 231 232# if USE_SOLARIS_THREADS_WEAK 233 234/* Use weak references to the old Solaris threads library. */ 235 236# pragma weak thr_create 237# pragma weak thr_join 238# pragma weak thr_self 239# pragma weak thr_exit 240 241# pragma weak thr_suspend 242# define thread_in_use() (thr_suspend != NULL) 243 244# else 245 246# define thread_in_use() 1 247 248# endif 249 250/* -------------------------- gl_thread_t datatype -------------------------- */ 251 252typedef thread_t gl_thread_t; 253# define glthread_create(THREADP, FUNC, ARG) \ 254 (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0) 255# define glthread_sigmask(HOW, SET, OSET) \ 256 (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0) 257# define glthread_join(THREAD, RETVALP) \ 258 (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0) 259# define gl_thread_self() \ 260 (thread_in_use () ? (void *) thr_self () : 0) 261# define gl_thread_exit(RETVAL) \ 262 (thread_in_use () ? thr_exit (RETVAL) : 0) 263# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 264 265# ifdef __cplusplus 266} 267# endif 268 269#endif 270 271/* ========================================================================= */ 272 273#if USE_WIN32_THREADS 274 275# include <windows.h> 276 277# ifdef __cplusplus 278extern "C" { 279# endif 280 281/* -------------------------- gl_thread_t datatype -------------------------- */ 282 283/* The gl_thread_t is a pointer to a structure in memory. 284 Why not the thread handle? If it were the thread handle, it would be hard 285 to implement gl_thread_self() (since GetCurrentThread () returns a pseudo- 286 handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be 287 closed afterwards, and there is no function for quickly retrieving a thread 288 handle from its id). 289 Why not the thread id? I tried it. It did not work: Sometimes ids appeared 290 that did not belong to running threads, and glthread_join failed with ESRCH. 291 */ 292typedef struct gl_thread_struct *gl_thread_t; 293# define glthread_create(THREADP, FUNC, ARG) \ 294 glthread_create_func (THREADP, FUNC, ARG) 295# define glthread_sigmask(HOW, SET, OSET) \ 296 /* unsupported */ 0 297# define glthread_join(THREAD, RETVALP) \ 298 glthread_join_func (THREAD, RETVALP) 299# define gl_thread_self() \ 300 gl_thread_self_func () 301# define gl_thread_exit(RETVAL) \ 302 gl_thread_exit_func (RETVAL) 303# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 304extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg); 305extern int glthread_join_func (gl_thread_t thread, void **retvalp); 306extern gl_thread_t gl_thread_self_func (void); 307extern int gl_thread_exit_func (void *retval); 308 309# ifdef __cplusplus 310} 311# endif 312 313#endif 314 315/* ========================================================================= */ 316 317#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS) 318 319/* Provide dummy implementation if threads are not supported. */ 320 321typedef int gl_thread_t; 322# define glthread_create(THREADP, FUNC, ARG) ENOSYS 323# define glthread_sigmask(HOW, SET, OSET) 0 324# define glthread_join(THREAD, RETVALP) 0 325# define gl_thread_self() NULL 326# define gl_thread_exit(RETVAL) 0 327# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 328 329#endif 330 331/* ========================================================================= */ 332 333/* Macros with built-in error handling. */ 334 335#ifdef __cplusplus 336extern "C" { 337#endif 338 339static inline gl_thread_t 340gl_thread_create (void *(*func) (void *arg), void *arg) 341{ 342 gl_thread_t thread; 343 int ret; 344 345 ret = glthread_create (&thread, func, arg); 346 if (ret != 0) 347 abort (); 348 return thread; 349} 350#define gl_thread_sigmask(HOW, SET, OSET) \ 351 do \ 352 { \ 353 if (glthread_sigmask (HOW, SET, OSET)) \ 354 abort (); \ 355 } \ 356 while (0) 357#define gl_thread_join(THREAD, RETVAL) \ 358 do \ 359 { \ 360 if (glthread_join (THREAD, RETVAL)) \ 361 abort (); \ 362 } \ 363 while (0) 364#define gl_thread_atfork(PREPARE, PARENT, CHILD) \ 365 do \ 366 { \ 367 if (glthread_atfork (PREPARE, PARENT, CHILD)) \ 368 abort (); \ 369 } \ 370 while (0) 371 372#ifdef __cplusplus 373} 374#endif 375 376#endif /* _GLTHREAD_THREAD_H */ 377