"Fossies" - the Fresh Open Source Software Archive

Member "gnuastro-0.8/bootstrapped/tests/glthread/thread.h" (28 Dec 2018, 13936 Bytes) of package /linux/privat/gnuastro-0.8.tar.lz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "thread.h": 0.5_vs_0.6.

    1 /* Creating and controlling threads.
    2    Copyright (C) 2005-2018 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-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      <https://lists.gnu.org/r/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 /* On IRIX, pthread_atfork is declared in <unistd.h>, not in <pthread.h>.  */
   94 # if defined __sgi
   95 #  include <unistd.h>
   96 # endif
   97 
   98 # if USE_POSIX_THREADS_WEAK
   99 /* Compilers other than GCC need to see the declaration of pthread_sigmask
  100    before the "#pragma weak pthread_sigmask" below.  */
  101 #  include <signal.h>
  102 # endif
  103 
  104 # ifdef __cplusplus
  105 extern "C" {
  106 # endif
  107 
  108 # if PTHREAD_IN_USE_DETECTION_HARD
  109 
  110 /* The pthread_in_use() detection needs to be done at runtime.  */
  111 #  define pthread_in_use() \
  112      glthread_in_use ()
  113 extern int glthread_in_use (void);
  114 
  115 # endif
  116 
  117 # if USE_POSIX_THREADS_WEAK
  118 
  119 /* Use weak references to the POSIX threads library.  */
  120 
  121 /* Weak references avoid dragging in external libraries if the other parts
  122    of the program don't use them.  Here we use them, because we don't want
  123    every program that uses libintl to depend on libpthread.  This assumes
  124    that libpthread would not be loaded after libintl; i.e. if libintl is
  125    loaded first, by an executable that does not depend on libpthread, and
  126    then a module is dynamically loaded that depends on libpthread, libintl
  127    will not be multithread-safe.  */
  128 
  129 /* The way to test at runtime whether libpthread is present is to test
  130    whether a function pointer's value, such as &pthread_mutex_init, is
  131    non-NULL.  However, some versions of GCC have a bug through which, in
  132    PIC mode, &foo != NULL always evaluates to true if there is a direct
  133    call to foo(...) in the same function.  To avoid this, we test the
  134    address of a function in libpthread that we don't use.  */
  135 
  136 #  pragma weak pthread_create
  137 
  138 #  ifndef pthread_sigmask /* Do not declare rpl_pthread_sigmask weak.  */
  139 #   pragma weak pthread_sigmask
  140 #  endif
  141 
  142 #  pragma weak pthread_join
  143 #  ifndef pthread_self
  144 #   pragma weak pthread_self
  145 #  endif
  146 #  pragma weak pthread_exit
  147 #  if HAVE_PTHREAD_ATFORK
  148 #   pragma weak pthread_atfork
  149 #  endif
  150 
  151 #  if !PTHREAD_IN_USE_DETECTION_HARD
  152 #   pragma weak pthread_mutexattr_gettype
  153 #   define pthread_in_use() (pthread_mutexattr_gettype != NULL)
  154 #  endif
  155 
  156 # else
  157 
  158 #  if !PTHREAD_IN_USE_DETECTION_HARD
  159 #   define pthread_in_use() 1
  160 #  endif
  161 
  162 # endif
  163 
  164 /* -------------------------- gl_thread_t datatype -------------------------- */
  165 
  166 /* This choice of gl_thread_t assumes that
  167      pthread_equal (a, b)  is equivalent to  ((a) == (b)).
  168    This is the case on all platforms in use in 2008.  */
  169 typedef pthread_t gl_thread_t;
  170 # define glthread_create(THREADP, FUNC, ARG) \
  171     (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
  172 # define glthread_sigmask(HOW, SET, OSET) \
  173     (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
  174 # define glthread_join(THREAD, RETVALP) \
  175     (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
  176 # ifdef PTW32_VERSION
  177    /* In pthreads-win32, pthread_t is a struct with a pointer field 'p' and
  178       other fields.  */
  179 #  define gl_thread_self() \
  180      (pthread_in_use () ? pthread_self () : gl_null_thread)
  181 #  define gl_thread_self_pointer() \
  182      (pthread_in_use () ? pthread_self ().p : NULL)
  183 extern const gl_thread_t gl_null_thread;
  184 # elif defined __MVS__
  185    /* On IBM z/OS, pthread_t is a struct with an 8-byte '__' field.
  186       The first three bytes of this field appear to uniquely identify a
  187       pthread_t, though not necessarily representing a pointer.  */
  188 #  define gl_thread_self() \
  189      (pthread_in_use () ? pthread_self () : gl_null_thread)
  190 #  define gl_thread_self_pointer() \
  191      (pthread_in_use () ? *((void **) pthread_self ().__) : NULL)
  192 extern const gl_thread_t gl_null_thread;
  193 # else
  194 #  define gl_thread_self() \
  195      (pthread_in_use () ? pthread_self () : (pthread_t) NULL)
  196 #  define gl_thread_self_pointer() \
  197      (pthread_in_use () ? (void *) pthread_self () : NULL)
  198 # endif
  199 # define gl_thread_exit(RETVAL) \
  200     (pthread_in_use () ? pthread_exit (RETVAL) : 0)
  201 
  202 # if HAVE_PTHREAD_ATFORK
  203 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \
  204      (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0)
  205 # else
  206 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
  207 # endif
  208 
  209 # ifdef __cplusplus
  210 }
  211 # endif
  212 
  213 #endif
  214 
  215 /* ========================================================================= */
  216 
  217 #if USE_PTH_THREADS
  218 
  219 /* Use the GNU Pth threads library.  */
  220 
  221 # include <pth.h>
  222 
  223 # ifdef __cplusplus
  224 extern "C" {
  225 # endif
  226 
  227 # if USE_PTH_THREADS_WEAK
  228 
  229 /* Use weak references to the GNU Pth threads library.  */
  230 
  231 #  pragma weak pth_init
  232 #  pragma weak pth_spawn
  233 #  pragma weak pth_sigmask
  234 #  pragma weak pth_join
  235 #  pragma weak pth_self
  236 #  pragma weak pth_exit
  237 
  238 #  pragma weak pth_cancel
  239 #  define pth_in_use() (pth_cancel != NULL)
  240 
  241 # else
  242 
  243 #  define pth_in_use() 1
  244 
  245 # endif
  246 /* -------------------------- gl_thread_t datatype -------------------------- */
  247 
  248 typedef pth_t gl_thread_t;
  249 # define glthread_create(THREADP, FUNC, ARG) \
  250     (pth_in_use () ? (pth_init (), ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno)) : 0)
  251 # define glthread_sigmask(HOW, SET, OSET) \
  252     (pth_in_use () ? (pth_init (), (pth_sigmask (HOW, SET, OSET) ? 0 : errno)) : 0)
  253 # define glthread_join(THREAD, RETVALP) \
  254     (pth_in_use () ? (pth_init (), (pth_join (THREAD, RETVALP) ? 0 : errno)) : 0)
  255 # define gl_thread_self() \
  256     (pth_in_use () ? (pth_init (), (void *) pth_self ()) : NULL)
  257 # define gl_thread_self_pointer() \
  258     gl_thread_self ()
  259 # define gl_thread_exit(RETVAL) \
  260     (pth_in_use () ? (pth_init (), pth_exit (RETVAL)) : 0)
  261 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
  262 
  263 # ifdef __cplusplus
  264 }
  265 # endif
  266 
  267 #endif
  268 
  269 /* ========================================================================= */
  270 
  271 #if USE_SOLARIS_THREADS
  272 
  273 /* Use the old Solaris threads library.  */
  274 
  275 # include <thread.h>
  276 # include <synch.h>
  277 
  278 # ifdef __cplusplus
  279 extern "C" {
  280 # endif
  281 
  282 # if USE_SOLARIS_THREADS_WEAK
  283 
  284 /* Use weak references to the old Solaris threads library.  */
  285 
  286 #  pragma weak thr_create
  287 #  pragma weak thr_join
  288 #  pragma weak thr_self
  289 #  pragma weak thr_exit
  290 
  291 #  pragma weak thr_suspend
  292 #  define thread_in_use() (thr_suspend != NULL)
  293 
  294 # else
  295 
  296 #  define thread_in_use() 1
  297 
  298 # endif
  299 
  300 /* -------------------------- gl_thread_t datatype -------------------------- */
  301 
  302 typedef thread_t gl_thread_t;
  303 # define glthread_create(THREADP, FUNC, ARG) \
  304     (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0)
  305 # define glthread_sigmask(HOW, SET, OSET) \
  306     (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
  307 # define glthread_join(THREAD, RETVALP) \
  308     (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
  309 # define gl_thread_self() \
  310     (thread_in_use () ? (void *) thr_self () : NULL)
  311 # define gl_thread_self_pointer() \
  312     gl_thread_self ()
  313 # define gl_thread_exit(RETVAL) \
  314     (thread_in_use () ? thr_exit (RETVAL) : 0)
  315 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
  316 
  317 # ifdef __cplusplus
  318 }
  319 # endif
  320 
  321 #endif
  322 
  323 /* ========================================================================= */
  324 
  325 #if USE_WINDOWS_THREADS
  326 
  327 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
  328 # include <windows.h>
  329 
  330 # ifdef __cplusplus
  331 extern "C" {
  332 # endif
  333 
  334 /* -------------------------- gl_thread_t datatype -------------------------- */
  335 
  336 /* The gl_thread_t is a pointer to a structure in memory.
  337    Why not the thread handle?  If it were the thread handle, it would be hard
  338    to implement gl_thread_self() (since GetCurrentThread () returns a pseudo-
  339    handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be
  340    closed afterwards, and there is no function for quickly retrieving a thread
  341    handle from its id).
  342    Why not the thread id?  I tried it.  It did not work: Sometimes ids appeared
  343    that did not belong to running threads, and glthread_join failed with ESRCH.
  344  */
  345 typedef struct gl_thread_struct *gl_thread_t;
  346 # define glthread_create(THREADP, FUNC, ARG) \
  347     glthread_create_func (THREADP, FUNC, ARG)
  348 # define glthread_sigmask(HOW, SET, OSET) \
  349     /* unsupported */ 0
  350 # define glthread_join(THREAD, RETVALP) \
  351     glthread_join_func (THREAD, RETVALP)
  352 # define gl_thread_self() \
  353     gl_thread_self_func ()
  354 # define gl_thread_self_pointer() \
  355     gl_thread_self ()
  356 # define gl_thread_exit(RETVAL) \
  357     gl_thread_exit_func (RETVAL)
  358 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
  359 extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg);
  360 extern int glthread_join_func (gl_thread_t thread, void **retvalp);
  361 extern gl_thread_t gl_thread_self_func (void);
  362 extern int gl_thread_exit_func (void *retval);
  363 
  364 # ifdef __cplusplus
  365 }
  366 # endif
  367 
  368 #endif
  369 
  370 /* ========================================================================= */
  371 
  372 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
  373 
  374 /* Provide dummy implementation if threads are not supported.  */
  375 
  376 typedef int gl_thread_t;
  377 # define glthread_create(THREADP, FUNC, ARG) ENOSYS
  378 # define glthread_sigmask(HOW, SET, OSET) 0
  379 # define glthread_join(THREAD, RETVALP) 0
  380 # define gl_thread_self() 0
  381 # define gl_thread_self_pointer() \
  382     ((void *) gl_thread_self ())
  383 # define gl_thread_exit(RETVAL) 0
  384 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
  385 
  386 #endif
  387 
  388 /* ========================================================================= */
  389 
  390 /* Macros with built-in error handling.  */
  391 
  392 #ifdef __cplusplus
  393 extern "C" {
  394 #endif
  395 
  396 _GLTHREAD_THREAD_INLINE gl_thread_t
  397 gl_thread_create (void *(*func) (void *arg), void *arg)
  398 {
  399   gl_thread_t thread;
  400   int ret;
  401 
  402   ret = glthread_create (&thread, func, arg);
  403   if (ret != 0)
  404     abort ();
  405   return thread;
  406 }
  407 #define gl_thread_sigmask(HOW, SET, OSET)     \
  408    do                                         \
  409      {                                        \
  410        if (glthread_sigmask (HOW, SET, OSET)) \
  411          abort ();                            \
  412      }                                        \
  413    while (0)
  414 #define gl_thread_join(THREAD, RETVAL)     \
  415    do                                      \
  416      {                                     \
  417        if (glthread_join (THREAD, RETVAL)) \
  418          abort ();                         \
  419      }                                     \
  420    while (0)
  421 #define gl_thread_atfork(PREPARE, PARENT, CHILD)     \
  422    do                                                \
  423      {                                               \
  424        if (glthread_atfork (PREPARE, PARENT, CHILD)) \
  425          abort ();                                   \
  426      }                                               \
  427    while (0)
  428 
  429 #ifdef __cplusplus
  430 }
  431 #endif
  432 
  433 _GL_INLINE_HEADER_END
  434 
  435 #endif /* _GLTHREAD_THREAD_H */