LCOV - code coverage report
Current view: top level - lib/gltests/glthread/glthread/glthread - thread.h (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 4 5 80.0 %
Date: 2015-08-01 15:30:48 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Creating and controlling threads.
       2             :    Copyright (C) 2005-2015 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, 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          52 : gl_thread_create (void *(*func) (void *arg), void *arg)
     379             : {
     380             :   gl_thread_t thread;
     381             :   int ret;
     382             : 
     383          52 :   ret = glthread_create (&thread, func, arg);
     384          52 :   if (ret != 0)
     385           0 :     abort ();
     386          52 :   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 */

Generated by: LCOV version 1.11