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: 2014-08-10 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 4 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* Creating and controlling threads.
       2                 :            :    Copyright (C) 2005-2014 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.9