thread.h | thread.h | |||
---|---|---|---|---|
/* Creating and controlling threads. | /* Creating and controlling threads. | |||
Copyright (C) 2005-2010 Free Software Foundation, Inc. | Copyright (C) 2005-2014 Free Software Foundation, Inc. | |||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 3, or (at your option) | the Free Software Foundation; either version 3, or (at your option) | |||
any later version. | any later version. | |||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software Foundation, | along with this program; if not, see <http://www.gnu.org/licenses/>. */ | |||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||||
/* Written by Bruno Haible <bruno@clisp.org>, 2005. | /* Written by Bruno Haible <bruno@clisp.org>, 2005. | |||
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, | Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, | |||
gthr-win32.h. */ | gthr-win32.h. */ | |||
/* This file contains primitives for creating and controlling threads. | /* This file contains primitives for creating and controlling threads. | |||
Thread data type: gl_thread_t. | Thread data type: gl_thread_t. | |||
Creating a thread: | Creating a thread: | |||
skipping to change at line 50 | skipping to change at line 49 | |||
Waiting for termination of another thread: | Waiting for termination of another thread: | |||
gl_thread_join (thread, &return_value); | gl_thread_join (thread, &return_value); | |||
Or with control of error handling: | Or with control of error handling: | |||
err = glthread_join (thread, &return_value); | err = glthread_join (thread, &return_value); | |||
extern int glthread_join (gl_thread_t thread, void **return_value_pt r); | extern int glthread_join (gl_thread_t thread, void **return_value_pt r); | |||
Getting a reference to the current thread: | Getting a reference to the current thread: | |||
current = gl_thread_self (); | current = gl_thread_self (); | |||
extern gl_thread_t gl_thread_self (void); | extern gl_thread_t gl_thread_self (void); | |||
Getting a reference to the current thread as a pointer, for debugging: | ||||
ptr = gl_thread_self_pointer (); | ||||
extern void * gl_thread_self_pointer (void); | ||||
Terminating the current thread: | Terminating the current thread: | |||
gl_thread_exit (return_value); | gl_thread_exit (return_value); | |||
extern void gl_thread_exit (void *return_value) __attribute__ ((nore turn)); | extern _Noreturn void gl_thread_exit (void *return_value); | |||
Requesting custom code to be executed at fork() time(not supported on al l | Requesting custom code to be executed at fork() time(not supported on al l | |||
platforms): | platforms): | |||
gl_thread_atfork (prepare_func, parent_func, child_func); | gl_thread_atfork (prepare_func, parent_func, child_func); | |||
Or with control of error handling: | Or with control of error handling: | |||
err = glthread_atfork (prepare_func, parent_func, child_func); | err = glthread_atfork (prepare_func, parent_func, child_func); | |||
extern int glthread_atfork (void (*prepare_func) (void), | extern int glthread_atfork (void (*prepare_func) (void), | |||
void (*parent_func) (void), | void (*parent_func) (void), | |||
void (*child_func) (void)); | void (*child_func) (void)); | |||
Note that even on platforms where this is supported, use of fork() and | Note that even on platforms where this is supported, use of fork() and | |||
threads together is problematic, see | threads together is problematic, see | |||
<http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html> | <http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html> | |||
*/ | */ | |||
#ifndef _GLTHREAD_THREAD_H | #ifndef _GLTHREAD_THREAD_H | |||
#define _GLTHREAD_THREAD_H | #define _GLTHREAD_THREAD_H | |||
#include <errno.h> | #include <errno.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#ifndef _GL_INLINE_HEADER_BEGIN | ||||
#error "Please include config.h first." | ||||
#endif | ||||
_GL_INLINE_HEADER_BEGIN | ||||
#ifndef _GLTHREAD_THREAD_INLINE | ||||
# define _GLTHREAD_THREAD_INLINE _GL_INLINE | ||||
#endif | ||||
/* ======================================================================== = */ | /* ======================================================================== = */ | |||
#if USE_POSIX_THREADS | #if USE_POSIX_THREADS | |||
/* Use the POSIX threads library. */ | /* Use the POSIX threads library. */ | |||
# include <pthread.h> | # include <pthread.h> | |||
# ifdef __cplusplus | # ifdef __cplusplus | |||
extern "C" { | extern "C" { | |||
skipping to change at line 114 | skipping to change at line 125 | |||
will not be multithread-safe. */ | will not be multithread-safe. */ | |||
/* The way to test at runtime whether libpthread is present is to test | /* The way to test at runtime whether libpthread is present is to test | |||
whether a function pointer's value, such as &pthread_mutex_init, is | whether a function pointer's value, such as &pthread_mutex_init, is | |||
non-NULL. However, some versions of GCC have a bug through which, in | non-NULL. However, some versions of GCC have a bug through which, in | |||
PIC mode, &foo != NULL always evaluates to true if there is a direct | PIC mode, &foo != NULL always evaluates to true if there is a direct | |||
call to foo(...) in the same function. To avoid this, we test the | call to foo(...) in the same function. To avoid this, we test the | |||
address of a function in libpthread that we don't use. */ | address of a function in libpthread that we don't use. */ | |||
# pragma weak pthread_create | # pragma weak pthread_create | |||
# ifdef __clang__ | ||||
/* Without this, clang complains that pthread_sigmask is never declared. | ||||
*/ | ||||
# include <signal.h> | ||||
# endif | ||||
# pragma weak pthread_sigmask | # pragma weak pthread_sigmask | |||
# pragma weak pthread_join | # pragma weak pthread_join | |||
# ifndef pthread_self | # ifndef pthread_self | |||
# pragma weak pthread_self | # pragma weak pthread_self | |||
# endif | # endif | |||
# pragma weak pthread_exit | # pragma weak pthread_exit | |||
# if HAVE_PTHREAD_ATFORK | # if HAVE_PTHREAD_ATFORK | |||
# pragma weak pthread_atfork | # pragma weak pthread_atfork | |||
# endif | # endif | |||
# if !PTHREAD_IN_USE_DETECTION_HARD | # if !PTHREAD_IN_USE_DETECTION_HARD | |||
skipping to change at line 149 | skipping to change at line 166 | |||
/* This choice of gl_thread_t assumes that | /* This choice of gl_thread_t assumes that | |||
pthread_equal (a, b) is equivalent to ((a) == (b)). | pthread_equal (a, b) is equivalent to ((a) == (b)). | |||
This is the case on all platforms in use in 2008. */ | This is the case on all platforms in use in 2008. */ | |||
typedef pthread_t gl_thread_t; | typedef pthread_t gl_thread_t; | |||
# define glthread_create(THREADP, FUNC, ARG) \ | # define glthread_create(THREADP, FUNC, ARG) \ | |||
(pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS ) | (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS ) | |||
# define glthread_sigmask(HOW, SET, OSET) \ | # define glthread_sigmask(HOW, SET, OSET) \ | |||
(pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0) | (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0) | |||
# define glthread_join(THREAD, RETVALP) \ | # define glthread_join(THREAD, RETVALP) \ | |||
(pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0) | (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0) | |||
# define gl_thread_self() \ | # ifdef PTW32_VERSION | |||
(pthread_in_use () ? (void *) pthread_self () : NULL) | /* In pthreads-win32, pthread_t is a struct with a pointer field 'p' and | |||
other fields. */ | ||||
# define gl_thread_self() \ | ||||
(pthread_in_use () ? pthread_self () : gl_null_thread) | ||||
# define gl_thread_self_pointer() \ | ||||
(pthread_in_use () ? pthread_self ().p : NULL) | ||||
extern const gl_thread_t gl_null_thread; | ||||
# else | ||||
# define gl_thread_self() \ | ||||
(pthread_in_use () ? pthread_self () : (pthread_t) NULL) | ||||
# define gl_thread_self_pointer() \ | ||||
(pthread_in_use () ? (void *) pthread_self () : NULL) | ||||
# endif | ||||
# define gl_thread_exit(RETVAL) \ | # define gl_thread_exit(RETVAL) \ | |||
(pthread_in_use () ? pthread_exit (RETVAL) : 0) | (pthread_in_use () ? pthread_exit (RETVAL) : 0) | |||
# if HAVE_PTHREAD_ATFORK | # if HAVE_PTHREAD_ATFORK | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \ | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \ | |||
(pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_ FUNC) : 0) | (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_ FUNC) : 0) | |||
# else | # else | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | |||
# endif | # endif | |||
skipping to change at line 207 | skipping to change at line 236 | |||
/* -------------------------- gl_thread_t datatype ------------------------ -- */ | /* -------------------------- gl_thread_t datatype ------------------------ -- */ | |||
typedef pth_t gl_thread_t; | typedef pth_t gl_thread_t; | |||
# define glthread_create(THREADP, FUNC, ARG) \ | # define glthread_create(THREADP, FUNC, ARG) \ | |||
(pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errn o) : 0) | (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errn o) : 0) | |||
# define glthread_sigmask(HOW, SET, OSET) \ | # define glthread_sigmask(HOW, SET, OSET) \ | |||
(pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0) | (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0) | |||
# define glthread_join(THREAD, RETVALP) \ | # define glthread_join(THREAD, RETVALP) \ | |||
(pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0) | (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0) | |||
# define gl_thread_self() \ | # define gl_thread_self() \ | |||
(pth_in_use () ? (void *) pth_self () : 0) | (pth_in_use () ? (void *) pth_self () : NULL) | |||
# define gl_thread_self_pointer() \ | ||||
gl_thread_self () | ||||
# define gl_thread_exit(RETVAL) \ | # define gl_thread_exit(RETVAL) \ | |||
(pth_in_use () ? pth_exit (RETVAL) : 0) | (pth_in_use () ? pth_exit (RETVAL) : 0) | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | |||
# ifdef __cplusplus | # ifdef __cplusplus | |||
} | } | |||
# endif | # endif | |||
#endif | #endif | |||
skipping to change at line 259 | skipping to change at line 290 | |||
/* -------------------------- gl_thread_t datatype ------------------------ -- */ | /* -------------------------- gl_thread_t datatype ------------------------ -- */ | |||
typedef thread_t gl_thread_t; | typedef thread_t gl_thread_t; | |||
# define glthread_create(THREADP, FUNC, ARG) \ | # define glthread_create(THREADP, FUNC, ARG) \ | |||
(thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0) | (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0) | |||
# define glthread_sigmask(HOW, SET, OSET) \ | # define glthread_sigmask(HOW, SET, OSET) \ | |||
(thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0) | (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0) | |||
# define glthread_join(THREAD, RETVALP) \ | # define glthread_join(THREAD, RETVALP) \ | |||
(thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0) | (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0) | |||
# define gl_thread_self() \ | # define gl_thread_self() \ | |||
(thread_in_use () ? (void *) thr_self () : 0) | (thread_in_use () ? (void *) thr_self () : NULL) | |||
# define gl_thread_self_pointer() \ | ||||
gl_thread_self () | ||||
# define gl_thread_exit(RETVAL) \ | # define gl_thread_exit(RETVAL) \ | |||
(thread_in_use () ? thr_exit (RETVAL) : 0) | (thread_in_use () ? thr_exit (RETVAL) : 0) | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | |||
# ifdef __cplusplus | # ifdef __cplusplus | |||
} | } | |||
# endif | # endif | |||
#endif | #endif | |||
/* ======================================================================== = */ | /* ======================================================================== = */ | |||
#if USE_WIN32_THREADS | #if USE_WINDOWS_THREADS | |||
# define WIN32_LEAN_AND_MEAN /* avoid including junk */ | ||||
# include <windows.h> | # include <windows.h> | |||
# ifdef __cplusplus | # ifdef __cplusplus | |||
extern "C" { | extern "C" { | |||
# endif | # endif | |||
/* -------------------------- gl_thread_t datatype ------------------------ -- */ | /* -------------------------- gl_thread_t datatype ------------------------ -- */ | |||
/* The gl_thread_t is a pointer to a structure in memory. | /* The gl_thread_t is a pointer to a structure in memory. | |||
Why not the thread handle? If it were the thread handle, it would be ha rd | Why not the thread handle? If it were the thread handle, it would be ha rd | |||
skipping to change at line 300 | skipping to change at line 334 | |||
*/ | */ | |||
typedef struct gl_thread_struct *gl_thread_t; | typedef struct gl_thread_struct *gl_thread_t; | |||
# define glthread_create(THREADP, FUNC, ARG) \ | # define glthread_create(THREADP, FUNC, ARG) \ | |||
glthread_create_func (THREADP, FUNC, ARG) | glthread_create_func (THREADP, FUNC, ARG) | |||
# define glthread_sigmask(HOW, SET, OSET) \ | # define glthread_sigmask(HOW, SET, OSET) \ | |||
/* unsupported */ 0 | /* unsupported */ 0 | |||
# define glthread_join(THREAD, RETVALP) \ | # define glthread_join(THREAD, RETVALP) \ | |||
glthread_join_func (THREAD, RETVALP) | glthread_join_func (THREAD, RETVALP) | |||
# define gl_thread_self() \ | # define gl_thread_self() \ | |||
gl_thread_self_func () | gl_thread_self_func () | |||
# define gl_thread_self_pointer() \ | ||||
gl_thread_self () | ||||
# define gl_thread_exit(RETVAL) \ | # define gl_thread_exit(RETVAL) \ | |||
gl_thread_exit_func (RETVAL) | gl_thread_exit_func (RETVAL) | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | |||
extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg); | extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg); | |||
extern int glthread_join_func (gl_thread_t thread, void **retvalp); | extern int glthread_join_func (gl_thread_t thread, void **retvalp); | |||
extern gl_thread_t gl_thread_self_func (void); | extern gl_thread_t gl_thread_self_func (void); | |||
extern int gl_thread_exit_func (void *retval); | extern int gl_thread_exit_func (void *retval); | |||
# ifdef __cplusplus | # ifdef __cplusplus | |||
} | } | |||
# endif | # endif | |||
#endif | #endif | |||
/* ======================================================================== = */ | /* ======================================================================== = */ | |||
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WI N32_THREADS) | #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WI NDOWS_THREADS) | |||
/* Provide dummy implementation if threads are not supported. */ | /* Provide dummy implementation if threads are not supported. */ | |||
typedef int gl_thread_t; | typedef int gl_thread_t; | |||
# define glthread_create(THREADP, FUNC, ARG) ENOSYS | # define glthread_create(THREADP, FUNC, ARG) ENOSYS | |||
# define glthread_sigmask(HOW, SET, OSET) 0 | # define glthread_sigmask(HOW, SET, OSET) 0 | |||
# define glthread_join(THREAD, RETVALP) 0 | # define glthread_join(THREAD, RETVALP) 0 | |||
# define gl_thread_self() NULL | # define gl_thread_self() 0 | |||
# define gl_thread_self_pointer() \ | ||||
((void *) gl_thread_self ()) | ||||
# define gl_thread_exit(RETVAL) 0 | # define gl_thread_exit(RETVAL) 0 | |||
# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 | |||
#endif | #endif | |||
/* ======================================================================== = */ | /* ======================================================================== = */ | |||
/* Macros with built-in error handling. */ | /* Macros with built-in error handling. */ | |||
#ifdef __cplusplus | #ifdef __cplusplus | |||
extern "C" { | extern "C" { | |||
#endif | #endif | |||
static inline gl_thread_t | _GLTHREAD_THREAD_INLINE gl_thread_t | |||
gl_thread_create (void *(*func) (void *arg), void *arg) | gl_thread_create (void *(*func) (void *arg), void *arg) | |||
{ | { | |||
gl_thread_t thread; | gl_thread_t thread; | |||
int ret; | int ret; | |||
ret = glthread_create (&thread, func, arg); | ret = glthread_create (&thread, func, arg); | |||
if (ret != 0) | if (ret != 0) | |||
abort (); | abort (); | |||
return thread; | return thread; | |||
} | } | |||
skipping to change at line 375 | skipping to change at line 413 | |||
{ \ | { \ | |||
if (glthread_atfork (PREPARE, PARENT, CHILD)) \ | if (glthread_atfork (PREPARE, PARENT, CHILD)) \ | |||
abort (); \ | abort (); \ | |||
} \ | } \ | |||
while (0) | while (0) | |||
#ifdef __cplusplus | #ifdef __cplusplus | |||
} | } | |||
#endif | #endif | |||
_GL_INLINE_HEADER_END | ||||
#endif /* _GLTHREAD_THREAD_H */ | #endif /* _GLTHREAD_THREAD_H */ | |||
End of changes. 17 change blocks. | ||||
12 lines changed or deleted | 53 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |