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: 2020-07-22 17:53:13 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Creating and controlling threads.
       2             :    Copyright (C) 2005-2020 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 <https://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-win32.h.  */
      19             : 
      20             : /* This file contains primitives for creating and controlling threads.
      21             : 
      22             :    Thread data type: gl_thread_t.
      23             : 
      24             :    Creating a thread:
      25             :        thread = gl_thread_create (func, arg);
      26             :    Or with control of error handling:
      27             :        err = glthread_create (&thread, func, arg);
      28             :        extern int glthread_create (gl_thread_t *result,
      29             :                                    void *(*func) (void *), void *arg);
      30             : 
      31             :    Querying and changing the signal mask of a thread (not supported on all
      32             :    platforms):
      33             :        gl_thread_sigmask (how, newmask, oldmask);
      34             :    Or with control of error handling:
      35             :        err = glthread_sigmask (how, newmask, oldmask);
      36             :        extern int glthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask);
      37             : 
      38             :    Waiting for termination of another thread:
      39             :        gl_thread_join (thread, &return_value);
      40             :    Or with control of error handling:
      41             :        err = glthread_join (thread, &return_value);
      42             :        extern int glthread_join (gl_thread_t thread, void **return_value_ptr);
      43             : 
      44             :    Getting a reference to the current thread:
      45             :        current = gl_thread_self ();
      46             :        extern gl_thread_t gl_thread_self (void);
      47             : 
      48             :    Getting a reference to the current thread as a pointer, for debugging:
      49             :        ptr = gl_thread_self_pointer ();
      50             :        extern void * gl_thread_self_pointer (void);
      51             : 
      52             :    Terminating the current thread:
      53             :        gl_thread_exit (return_value);
      54             :        extern _Noreturn void gl_thread_exit (void *return_value);
      55             : 
      56             :    Requesting custom code to be executed at fork() time (not supported on all
      57             :    platforms):
      58             :        gl_thread_atfork (prepare_func, parent_func, child_func);
      59             :    Or with control of error handling:
      60             :        err = glthread_atfork (prepare_func, parent_func, child_func);
      61             :        extern int glthread_atfork (void (*prepare_func) (void),
      62             :                                    void (*parent_func) (void),
      63             :                                    void (*child_func) (void));
      64             :    Note that even on platforms where this is supported, use of fork() and
      65             :    threads together is problematic, see
      66             :      <https://lists.gnu.org/r/bug-gnulib/2008-08/msg00062.html>
      67             :  */
      68             : 
      69             : 
      70             : #ifndef _GLTHREAD_THREAD_H
      71             : #define _GLTHREAD_THREAD_H
      72             : 
      73             : #include <errno.h>
      74             : #include <stdlib.h>
      75             : 
      76             : #if !defined c11_threads_in_use
      77             : # if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
      78             : #  include <threads.h>
      79             : #  pragma weak thrd_exit
      80             : #  define c11_threads_in_use() (thrd_exit != NULL)
      81             : # else
      82             : #  define c11_threads_in_use() 0
      83             : # endif
      84             : #endif
      85             : 
      86             : #ifndef _GL_INLINE_HEADER_BEGIN
      87             :  #error "Please include config.h first."
      88             : #endif
      89             : _GL_INLINE_HEADER_BEGIN
      90             : #ifndef _GLTHREAD_THREAD_INLINE
      91             : # define _GLTHREAD_THREAD_INLINE _GL_INLINE
      92             : #endif
      93             : 
      94             : /* ========================================================================= */
      95             : 
      96             : #if USE_ISOC_THREADS
      97             : 
      98             : /* Use the ISO C threads library.  */
      99             : 
     100             : # include <threads.h>
     101             : 
     102             : # ifdef __cplusplus
     103             : extern "C" {
     104             : # endif
     105             : 
     106             : /* -------------------------- gl_thread_t datatype -------------------------- */
     107             : 
     108             : typedef struct thrd_with_exitvalue *gl_thread_t;
     109             : extern int glthread_create (gl_thread_t *threadp,
     110             :                             void *(*func) (void *), void *arg);
     111             : # define glthread_sigmask(HOW, SET, OSET) \
     112             :     pthread_sigmask (HOW, SET, OSET)
     113             : extern int glthread_join (gl_thread_t thread, void **return_value_ptr);
     114             : extern gl_thread_t gl_thread_self (void);
     115             : # define gl_thread_self_pointer() \
     116             :     (void *) gl_thread_self ()
     117             : extern _Noreturn void gl_thread_exit (void *return_value);
     118             : # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
     119             : 
     120             : # ifdef __cplusplus
     121             : }
     122             : # endif
     123             : 
     124             : #endif
     125             : 
     126             : /* ========================================================================= */
     127             : 
     128             : #if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
     129             : 
     130             : /* Use the POSIX threads library.  */
     131             : 
     132             : # include <pthread.h>
     133             : 
     134             : /* On IRIX, pthread_atfork is declared in <unistd.h>, not in <pthread.h>.  */
     135             : # if defined __sgi
     136             : #  include <unistd.h>
     137             : # endif
     138             : 
     139             : # if USE_POSIX_THREADS_WEAK
     140             : /* Compilers other than GCC need to see the declaration of pthread_sigmask
     141             :    before the "#pragma weak pthread_sigmask" below.  */
     142             : #  include <signal.h>
     143             : # endif
     144             : 
     145             : # ifdef __cplusplus
     146             : extern "C" {
     147             : # endif
     148             : 
     149             : # if PTHREAD_IN_USE_DETECTION_HARD
     150             : 
     151             : /* The pthread_in_use() detection needs to be done at runtime.  */
     152             : #  define pthread_in_use() \
     153             :      glthread_in_use ()
     154             : extern int glthread_in_use (void);
     155             : 
     156             : # endif
     157             : 
     158             : # if USE_POSIX_THREADS_WEAK
     159             : 
     160             : /* Use weak references to the POSIX threads library.  */
     161             : 
     162             : /* Weak references avoid dragging in external libraries if the other parts
     163             :    of the program don't use them.  Here we use them, because we don't want
     164             :    every program that uses libintl to depend on libpthread.  This assumes
     165             :    that libpthread would not be loaded after libintl; i.e. if libintl is
     166             :    loaded first, by an executable that does not depend on libpthread, and
     167             :    then a module is dynamically loaded that depends on libpthread, libintl
     168             :    will not be multithread-safe.  */
     169             : 
     170             : /* The way to test at runtime whether libpthread is present is to test
     171             :    whether a function pointer's value, such as &pthread_mutex_init, is
     172             :    non-NULL.  However, some versions of GCC have a bug through which, in
     173             :    PIC mode, &foo != NULL always evaluates to true if there is a direct
     174             :    call to foo(...) in the same function.  To avoid this, we test the
     175             :    address of a function in libpthread that we don't use.  */
     176             : 
     177             : #  ifndef pthread_sigmask /* Do not declare rpl_pthread_sigmask weak.  */
     178             : #   pragma weak pthread_sigmask
     179             : #  endif
     180             : 
     181             : #  pragma weak pthread_join
     182             : #  ifndef pthread_self
     183             : #   pragma weak pthread_self
     184             : #  endif
     185             : #  pragma weak pthread_exit
     186             : #  if HAVE_PTHREAD_ATFORK
     187             : #   pragma weak pthread_atfork
     188             : #  endif
     189             : 
     190             : #  if !PTHREAD_IN_USE_DETECTION_HARD
     191             : #   pragma weak pthread_mutexattr_gettype
     192             : #   define pthread_in_use() \
     193             :       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
     194             : #  endif
     195             : 
     196             : # else
     197             : 
     198             : #  if !PTHREAD_IN_USE_DETECTION_HARD
     199             : #   define pthread_in_use() 1
     200             : #  endif
     201             : 
     202             : # endif
     203             : 
     204             : /* -------------------------- gl_thread_t datatype -------------------------- */
     205             : 
     206             : /* This choice of gl_thread_t assumes that
     207             :      pthread_equal (a, b)  is equivalent to  ((a) == (b)).
     208             :    This is the case on all platforms in use in 2008.  */
     209             : typedef pthread_t gl_thread_t;
     210             : # define glthread_create(THREADP, FUNC, ARG) \
     211             :     (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
     212             : # define glthread_sigmask(HOW, SET, OSET) \
     213             :     (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
     214             : # define glthread_join(THREAD, RETVALP) \
     215             :     (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
     216             : # ifdef PTW32_VERSION
     217             :    /* In pthreads-win32, pthread_t is a struct with a pointer field 'p' and
     218             :       other fields.  */
     219             : #  define gl_thread_self() \
     220             :      (pthread_in_use () ? pthread_self () : gl_null_thread)
     221             : #  define gl_thread_self_pointer() \
     222             :      (pthread_in_use () ? pthread_self ().p : NULL)
     223             : extern const gl_thread_t gl_null_thread;
     224             : # elif defined __MVS__
     225             :    /* On IBM z/OS, pthread_t is a struct with an 8-byte '__' field.
     226             :       The first three bytes of this field appear to uniquely identify a
     227             :       pthread_t, though not necessarily representing a pointer.  */
     228             : #  define gl_thread_self() \
     229             :      (pthread_in_use () ? pthread_self () : gl_null_thread)
     230             : #  define gl_thread_self_pointer() \
     231             :      (pthread_in_use () ? *((void **) pthread_self ().__) : NULL)
     232             : extern const gl_thread_t gl_null_thread;
     233             : # else
     234             : #  define gl_thread_self() \
     235             :      (pthread_in_use () ? pthread_self () : (pthread_t) NULL)
     236             : #  define gl_thread_self_pointer() \
     237             :      (pthread_in_use () ? (void *) pthread_self () : NULL)
     238             : # endif
     239             : # define gl_thread_exit(RETVAL) \
     240             :     (void) (pthread_in_use () ? (pthread_exit (RETVAL), 0) : 0)
     241             : 
     242             : # if HAVE_PTHREAD_ATFORK
     243             : #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \
     244             :      (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0)
     245             : # else
     246             : #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
     247             : # endif
     248             : 
     249             : # ifdef __cplusplus
     250             : }
     251             : # endif
     252             : 
     253             : #endif
     254             : 
     255             : /* ========================================================================= */
     256             : 
     257             : #if USE_WINDOWS_THREADS
     258             : 
     259             : # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
     260             : # include <windows.h>
     261             : 
     262             : # include "windows-thread.h"
     263             : 
     264             : # ifdef __cplusplus
     265             : extern "C" {
     266             : # endif
     267             : 
     268             : /* -------------------------- gl_thread_t datatype -------------------------- */
     269             : 
     270             : typedef glwthread_thread_t gl_thread_t;
     271             : # define glthread_create(THREADP, FUNC, ARG) \
     272             :     glwthread_thread_create (THREADP, 0, FUNC, ARG)
     273             : # define glthread_sigmask(HOW, SET, OSET) \
     274             :     /* unsupported */ 0
     275             : # define glthread_join(THREAD, RETVALP) \
     276             :     glwthread_thread_join (THREAD, RETVALP)
     277             : # define gl_thread_self() \
     278             :     glwthread_thread_self ()
     279             : # define gl_thread_self_pointer() \
     280             :     gl_thread_self ()
     281             : # define gl_thread_exit(RETVAL) \
     282             :     glwthread_thread_exit (RETVAL)
     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_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
     294             : 
     295             : /* Provide dummy implementation if threads are not supported.  */
     296             : 
     297             : typedef int gl_thread_t;
     298             : # define glthread_create(THREADP, FUNC, ARG) ENOSYS
     299             : # define glthread_sigmask(HOW, SET, OSET) 0
     300             : # define glthread_join(THREAD, RETVALP) 0
     301             : # define gl_thread_self() 0
     302             : # define gl_thread_self_pointer() \
     303             :     ((void *) gl_thread_self ())
     304             : # define gl_thread_exit(RETVAL) (void)0
     305             : # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
     306             : 
     307             : #endif
     308             : 
     309             : /* ========================================================================= */
     310             : 
     311             : /* Macros with built-in error handling.  */
     312             : 
     313             : #ifdef __cplusplus
     314             : extern "C" {
     315             : #endif
     316             : 
     317             : _GLTHREAD_THREAD_INLINE gl_thread_t
     318          52 : gl_thread_create (void *(*func) (void *arg), void *arg)
     319             : {
     320             :   gl_thread_t thread;
     321             :   int ret;
     322             : 
     323          52 :   ret = glthread_create (&thread, func, arg);
     324          52 :   if (ret != 0)
     325           0 :     abort ();
     326          52 :   return thread;
     327             : }
     328             : #define gl_thread_sigmask(HOW, SET, OSET)     \
     329             :    do                                         \
     330             :      {                                        \
     331             :        if (glthread_sigmask (HOW, SET, OSET)) \
     332             :          abort ();                            \
     333             :      }                                        \
     334             :    while (0)
     335             : #define gl_thread_join(THREAD, RETVAL)     \
     336             :    do                                      \
     337             :      {                                     \
     338             :        if (glthread_join (THREAD, RETVAL)) \
     339             :          abort ();                         \
     340             :      }                                     \
     341             :    while (0)
     342             : #define gl_thread_atfork(PREPARE, PARENT, CHILD)     \
     343             :    do                                                \
     344             :      {                                               \
     345             :        if (glthread_atfork (PREPARE, PARENT, CHILD)) \
     346             :          abort ();                                   \
     347             :      }                                               \
     348             :    while (0)
     349             : 
     350             : #ifdef __cplusplus
     351             : }
     352             : #endif
     353             : 
     354             : _GL_INLINE_HEADER_END
     355             : 
     356             : #endif /* _GLTHREAD_THREAD_H */

Generated by: LCOV version 1.13