Blame lib/glthread/lock.h

Packit 8f70b4
/* Locking in multithreaded situations.
Packit 8f70b4
   Copyright (C) 2005-2018 Free Software Foundation, Inc.
Packit 8f70b4
Packit 8f70b4
   This program is free software; you can redistribute it and/or modify
Packit 8f70b4
   it under the terms of the GNU General Public License as published by
Packit 8f70b4
   the Free Software Foundation; either version 3, or (at your option)
Packit 8f70b4
   any later version.
Packit 8f70b4
Packit 8f70b4
   This program is distributed in the hope that it will be useful,
Packit 8f70b4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
   GNU General Public License for more details.
Packit 8f70b4
Packit 8f70b4
   You should have received a copy of the GNU General Public License
Packit 8f70b4
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 8f70b4
Packit 8f70b4
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
Packit 8f70b4
   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
Packit 8f70b4
   gthr-win32.h.  */
Packit 8f70b4
Packit 8f70b4
/* This file contains locking primitives for use with a given thread library.
Packit 8f70b4
   It does not contain primitives for creating threads or for other
Packit 8f70b4
   synchronization primitives.
Packit 8f70b4
Packit 8f70b4
   Normal (non-recursive) locks:
Packit 8f70b4
     Type:                gl_lock_t
Packit 8f70b4
     Declaration:         gl_lock_define(extern, name)
Packit 8f70b4
     Initializer:         gl_lock_define_initialized(, name)
Packit 8f70b4
     Initialization:      gl_lock_init (name);
Packit 8f70b4
     Taking the lock:     gl_lock_lock (name);
Packit 8f70b4
     Releasing the lock:  gl_lock_unlock (name);
Packit 8f70b4
     De-initialization:   gl_lock_destroy (name);
Packit 8f70b4
   Equivalent functions with control of error handling:
Packit 8f70b4
     Initialization:      err = glthread_lock_init (&name);
Packit 8f70b4
     Taking the lock:     err = glthread_lock_lock (&name);
Packit 8f70b4
     Releasing the lock:  err = glthread_lock_unlock (&name);
Packit 8f70b4
     De-initialization:   err = glthread_lock_destroy (&name);
Packit 8f70b4
Packit 8f70b4
   Read-Write (non-recursive) locks:
Packit 8f70b4
     Type:                gl_rwlock_t
Packit 8f70b4
     Declaration:         gl_rwlock_define(extern, name)
Packit 8f70b4
     Initializer:         gl_rwlock_define_initialized(, name)
Packit 8f70b4
     Initialization:      gl_rwlock_init (name);
Packit 8f70b4
     Taking the lock:     gl_rwlock_rdlock (name);
Packit 8f70b4
                          gl_rwlock_wrlock (name);
Packit 8f70b4
     Releasing the lock:  gl_rwlock_unlock (name);
Packit 8f70b4
     De-initialization:   gl_rwlock_destroy (name);
Packit 8f70b4
   Equivalent functions with control of error handling:
Packit 8f70b4
     Initialization:      err = glthread_rwlock_init (&name);
Packit 8f70b4
     Taking the lock:     err = glthread_rwlock_rdlock (&name);
Packit 8f70b4
                          err = glthread_rwlock_wrlock (&name);
Packit 8f70b4
     Releasing the lock:  err = glthread_rwlock_unlock (&name);
Packit 8f70b4
     De-initialization:   err = glthread_rwlock_destroy (&name);
Packit 8f70b4
Packit 8f70b4
   Recursive locks:
Packit 8f70b4
     Type:                gl_recursive_lock_t
Packit 8f70b4
     Declaration:         gl_recursive_lock_define(extern, name)
Packit 8f70b4
     Initializer:         gl_recursive_lock_define_initialized(, name)
Packit 8f70b4
     Initialization:      gl_recursive_lock_init (name);
Packit 8f70b4
     Taking the lock:     gl_recursive_lock_lock (name);
Packit 8f70b4
     Releasing the lock:  gl_recursive_lock_unlock (name);
Packit 8f70b4
     De-initialization:   gl_recursive_lock_destroy (name);
Packit 8f70b4
   Equivalent functions with control of error handling:
Packit 8f70b4
     Initialization:      err = glthread_recursive_lock_init (&name);
Packit 8f70b4
     Taking the lock:     err = glthread_recursive_lock_lock (&name);
Packit 8f70b4
     Releasing the lock:  err = glthread_recursive_lock_unlock (&name);
Packit 8f70b4
     De-initialization:   err = glthread_recursive_lock_destroy (&name);
Packit 8f70b4
Packit 8f70b4
  Once-only execution:
Packit 8f70b4
     Type:                gl_once_t
Packit 8f70b4
     Initializer:         gl_once_define(extern, name)
Packit 8f70b4
     Execution:           gl_once (name, initfunction);
Packit 8f70b4
   Equivalent functions with control of error handling:
Packit 8f70b4
     Execution:           err = glthread_once (&name, initfunction);
Packit 8f70b4
*/
Packit 8f70b4
Packit 8f70b4
Packit 8f70b4
#ifndef _LOCK_H
Packit 8f70b4
#define _LOCK_H
Packit 8f70b4
Packit 8f70b4
#include <errno.h>
Packit 8f70b4
#include <stdlib.h>
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#if USE_POSIX_THREADS
Packit 8f70b4
Packit 8f70b4
/* Use the POSIX threads library.  */
Packit 8f70b4
Packit 8f70b4
# include <pthread.h>
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
extern "C" {
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
# if PTHREAD_IN_USE_DETECTION_HARD
Packit 8f70b4
Packit 8f70b4
/* The pthread_in_use() detection needs to be done at runtime.  */
Packit 8f70b4
#  define pthread_in_use() \
Packit 8f70b4
     glthread_in_use ()
Packit 8f70b4
extern int glthread_in_use (void);
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
# if USE_POSIX_THREADS_WEAK
Packit 8f70b4
Packit 8f70b4
/* Use weak references to the POSIX threads library.  */
Packit 8f70b4
Packit 8f70b4
/* Weak references avoid dragging in external libraries if the other parts
Packit 8f70b4
   of the program don't use them.  Here we use them, because we don't want
Packit 8f70b4
   every program that uses libintl to depend on libpthread.  This assumes
Packit 8f70b4
   that libpthread would not be loaded after libintl; i.e. if libintl is
Packit 8f70b4
   loaded first, by an executable that does not depend on libpthread, and
Packit 8f70b4
   then a module is dynamically loaded that depends on libpthread, libintl
Packit 8f70b4
   will not be multithread-safe.  */
Packit 8f70b4
Packit 8f70b4
/* The way to test at runtime whether libpthread is present is to test
Packit 8f70b4
   whether a function pointer's value, such as &pthread_mutex_init, is
Packit 8f70b4
   non-NULL.  However, some versions of GCC have a bug through which, in
Packit 8f70b4
   PIC mode, &foo != NULL always evaluates to true if there is a direct
Packit 8f70b4
   call to foo(...) in the same function.  To avoid this, we test the
Packit 8f70b4
   address of a function in libpthread that we don't use.  */
Packit 8f70b4
Packit 8f70b4
#  pragma weak pthread_mutex_init
Packit 8f70b4
#  pragma weak pthread_mutex_lock
Packit 8f70b4
#  pragma weak pthread_mutex_unlock
Packit 8f70b4
#  pragma weak pthread_mutex_destroy
Packit 8f70b4
#  pragma weak pthread_rwlock_init
Packit 8f70b4
#  pragma weak pthread_rwlock_rdlock
Packit 8f70b4
#  pragma weak pthread_rwlock_wrlock
Packit 8f70b4
#  pragma weak pthread_rwlock_unlock
Packit 8f70b4
#  pragma weak pthread_rwlock_destroy
Packit 8f70b4
#  pragma weak pthread_once
Packit 8f70b4
#  pragma weak pthread_cond_init
Packit 8f70b4
#  pragma weak pthread_cond_wait
Packit 8f70b4
#  pragma weak pthread_cond_signal
Packit 8f70b4
#  pragma weak pthread_cond_broadcast
Packit 8f70b4
#  pragma weak pthread_cond_destroy
Packit 8f70b4
#  pragma weak pthread_mutexattr_init
Packit 8f70b4
#  pragma weak pthread_mutexattr_settype
Packit 8f70b4
#  pragma weak pthread_mutexattr_destroy
Packit 8f70b4
#  pragma weak pthread_rwlockattr_init
Packit 8f70b4
#  if __GNU_LIBRARY__ > 1
Packit 8f70b4
#   pragma weak pthread_rwlockattr_setkind_np
Packit 8f70b4
#  endif
Packit 8f70b4
#  pragma weak pthread_rwlockattr_destroy
Packit 8f70b4
#  ifndef pthread_self
Packit 8f70b4
#   pragma weak pthread_self
Packit 8f70b4
#  endif
Packit 8f70b4
Packit 8f70b4
#  if !PTHREAD_IN_USE_DETECTION_HARD
Packit 8f70b4
    /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
Packit 8f70b4
       can be used to determine whether libpthread is in use.  These are:
Packit 8f70b4
         pthread_mutexattr_gettype
Packit 8f70b4
         pthread_rwlockattr_destroy
Packit 8f70b4
         pthread_rwlockattr_init
Packit 8f70b4
     */
Packit 8f70b4
#   pragma weak pthread_mutexattr_gettype
Packit 8f70b4
#   define pthread_in_use() (pthread_mutexattr_gettype != NULL)
Packit 8f70b4
#  endif
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
#  if !PTHREAD_IN_USE_DETECTION_HARD
Packit 8f70b4
#   define pthread_in_use() 1
Packit 8f70b4
#  endif
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef pthread_mutex_t gl_lock_t;
Packit 8f70b4
# define gl_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pthread_mutex_t NAME;
Packit 8f70b4
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
Packit 8f70b4
# define gl_lock_initializer \
Packit 8f70b4
    PTHREAD_MUTEX_INITIALIZER
Packit 8f70b4
# define glthread_lock_init(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
Packit 8f70b4
# define glthread_lock_lock(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
Packit 8f70b4
# define glthread_lock_unlock(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
Packit 8f70b4
# define glthread_lock_destroy(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
Packit 8f70b4
Packit 8f70b4
#  ifdef PTHREAD_RWLOCK_INITIALIZER
Packit 8f70b4
Packit 8f70b4
typedef pthread_rwlock_t gl_rwlock_t;
Packit 8f70b4
#   define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS pthread_rwlock_t NAME;
Packit 8f70b4
#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
#   if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
Packit 8f70b4
#    define gl_rwlock_initializer \
Packit 8f70b4
       PTHREAD_RWLOCK_INITIALIZER
Packit 8f70b4
#    define glthread_rwlock_init(LOCK) \
Packit 8f70b4
       (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
Packit 8f70b4
#   else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
Packit 8f70b4
#    define gl_rwlock_initializer \
Packit 8f70b4
       PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
Packit 8f70b4
#    define glthread_rwlock_init(LOCK) \
Packit 8f70b4
       (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
Packit 8f70b4
extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
Packit 8f70b4
#   endif
Packit 8f70b4
#   define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
Packit 8f70b4
Packit 8f70b4
#  else
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          int initialized;
Packit 8f70b4
          pthread_mutex_t guard;   /* protects the initialization */
Packit 8f70b4
          pthread_rwlock_t rwlock; /* read-write lock */
Packit 8f70b4
        }
Packit 8f70b4
        gl_rwlock_t;
Packit 8f70b4
#   define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS gl_rwlock_t NAME;
Packit 8f70b4
#   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
#   define gl_rwlock_initializer \
Packit 8f70b4
      { 0, PTHREAD_MUTEX_INITIALIZER }
Packit 8f70b4
#   define glthread_rwlock_init(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
Packit 8f70b4
#  endif
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          pthread_mutex_t lock; /* protects the remaining fields */
Packit 8f70b4
          pthread_cond_t waiting_readers; /* waiting readers */
Packit 8f70b4
          pthread_cond_t waiting_writers; /* waiting writers */
Packit 8f70b4
          unsigned int waiting_writers_count; /* number of waiting writers */
Packit 8f70b4
          int runcount; /* number of readers running, or -1 when a writer runs */
Packit 8f70b4
        }
Packit 8f70b4
        gl_rwlock_t;
Packit 8f70b4
# define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_rwlock_t NAME;
Packit 8f70b4
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
# define gl_rwlock_initializer \
Packit 8f70b4
    { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
Packit 8f70b4
# define glthread_rwlock_init(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
    (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
# if HAVE_PTHREAD_MUTEX_RECURSIVE
Packit 8f70b4
Packit 8f70b4
#  if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
Packit 8f70b4
Packit 8f70b4
typedef pthread_mutex_t gl_recursive_lock_t;
Packit 8f70b4
#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS pthread_mutex_t NAME;
Packit 8f70b4
#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
#   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
Packit 8f70b4
#    define gl_recursive_lock_initializer \
Packit 8f70b4
       PTHREAD_RECURSIVE_MUTEX_INITIALIZER
Packit 8f70b4
#   else
Packit 8f70b4
#    define gl_recursive_lock_initializer \
Packit 8f70b4
       PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
Packit 8f70b4
#   endif
Packit 8f70b4
#   define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
Packit 8f70b4
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
#  else
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          pthread_mutex_t recmutex; /* recursive mutex */
Packit 8f70b4
          pthread_mutex_t guard;    /* protects the initialization */
Packit 8f70b4
          int initialized;
Packit 8f70b4
        }
Packit 8f70b4
        gl_recursive_lock_t;
Packit 8f70b4
#   define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS gl_recursive_lock_t NAME;
Packit 8f70b4
#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
#   define gl_recursive_lock_initializer \
Packit 8f70b4
      { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
Packit 8f70b4
#   define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#   define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
      (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
#  endif
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
/* Old versions of POSIX threads on Solaris did not have recursive locks.
Packit 8f70b4
   We have to implement them ourselves.  */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          pthread_mutex_t mutex;
Packit 8f70b4
          pthread_t owner;
Packit 8f70b4
          unsigned long depth;
Packit 8f70b4
        }
Packit 8f70b4
        gl_recursive_lock_t;
Packit 8f70b4
#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS gl_recursive_lock_t NAME;
Packit 8f70b4
#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
#  define gl_recursive_lock_initializer \
Packit 8f70b4
     { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
Packit 8f70b4
#  define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
     (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
     (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
     (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
     (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef pthread_once_t gl_once_t;
Packit 8f70b4
# define gl_once_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
Packit 8f70b4
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
Packit 8f70b4
    (pthread_in_use ()                                                         \
Packit 8f70b4
     ? pthread_once (ONCE_CONTROL, INITFUNCTION)                               \
Packit 8f70b4
     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
Packit 8f70b4
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
}
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#if USE_PTH_THREADS
Packit 8f70b4
Packit 8f70b4
/* Use the GNU Pth threads library.  */
Packit 8f70b4
Packit 8f70b4
# include <pth.h>
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
extern "C" {
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
# if USE_PTH_THREADS_WEAK
Packit 8f70b4
Packit 8f70b4
/* Use weak references to the GNU Pth threads library.  */
Packit 8f70b4
Packit 8f70b4
#  pragma weak pth_mutex_init
Packit 8f70b4
#  pragma weak pth_mutex_acquire
Packit 8f70b4
#  pragma weak pth_mutex_release
Packit 8f70b4
#  pragma weak pth_rwlock_init
Packit 8f70b4
#  pragma weak pth_rwlock_acquire
Packit 8f70b4
#  pragma weak pth_rwlock_release
Packit 8f70b4
#  pragma weak pth_once
Packit 8f70b4
Packit 8f70b4
#  pragma weak pth_cancel
Packit 8f70b4
#  define pth_in_use() (pth_cancel != NULL)
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
#  define pth_in_use() 1
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef pth_mutex_t gl_lock_t;
Packit 8f70b4
# define gl_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pth_mutex_t NAME;
Packit 8f70b4
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
Packit 8f70b4
# define gl_lock_initializer \
Packit 8f70b4
    PTH_MUTEX_INIT
Packit 8f70b4
# define glthread_lock_init(LOCK) \
Packit 8f70b4
    (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
Packit 8f70b4
# define glthread_lock_lock(LOCK) \
Packit 8f70b4
    (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
Packit 8f70b4
# define glthread_lock_unlock(LOCK) \
Packit 8f70b4
    (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
Packit 8f70b4
# define glthread_lock_destroy(LOCK) \
Packit 8f70b4
    ((void)(LOCK), 0)
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
/* Pth pth_rwlock_acquire always prefers readers.  No autoconf test so far.  */
Packit 8f70b4
# if HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER
Packit 8f70b4
Packit 8f70b4
typedef pth_rwlock_t gl_rwlock_t;
Packit 8f70b4
#  define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS pth_rwlock_t NAME;
Packit 8f70b4
#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
#  define gl_rwlock_initializer \
Packit 8f70b4
     PTH_RWLOCK_INIT
Packit 8f70b4
#  define glthread_rwlock_init(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
Packit 8f70b4
#  define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
Packit 8f70b4
#  define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
Packit 8f70b4
#  define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
Packit 8f70b4
#  define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
     ((void)(LOCK), 0)
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          int initialized;
Packit 8f70b4
          pth_mutex_t lock; /* protects the remaining fields */
Packit 8f70b4
          pth_cond_t waiting_readers; /* waiting readers */
Packit 8f70b4
          pth_cond_t waiting_writers; /* waiting writers */
Packit 8f70b4
          unsigned int waiting_writers_count; /* number of waiting writers */
Packit 8f70b4
          int runcount; /* number of readers running, or -1 when a writer runs */
Packit 8f70b4
        }
Packit 8f70b4
        gl_rwlock_t;
Packit 8f70b4
#  define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS gl_rwlock_t NAME;
Packit 8f70b4
#  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
#  define gl_rwlock_initializer \
Packit 8f70b4
     { 0 }
Packit 8f70b4
#  define glthread_rwlock_init(LOCK) \
Packit 8f70b4
     (pth_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
     (pth_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
     (pth_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
     (pth_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
#  define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
     (pth_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
/* In Pth, mutexes are recursive by default.  */
Packit 8f70b4
typedef pth_mutex_t gl_recursive_lock_t;
Packit 8f70b4
#  define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS pth_mutex_t NAME;
Packit 8f70b4
#  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
     STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
#  define gl_recursive_lock_initializer \
Packit 8f70b4
     PTH_MUTEX_INIT
Packit 8f70b4
#  define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
Packit 8f70b4
#  define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
Packit 8f70b4
#  define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
     (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
Packit 8f70b4
#  define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
     ((void)(LOCK), 0)
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef pth_once_t gl_once_t;
Packit 8f70b4
# define gl_once_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
Packit 8f70b4
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
Packit 8f70b4
    (pth_in_use ()                                                             \
Packit 8f70b4
     ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)                \
Packit 8f70b4
     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
Packit 8f70b4
extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
Packit 8f70b4
extern int glthread_once_singlethreaded (pth_once_t *once_control);
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
}
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#if USE_SOLARIS_THREADS
Packit 8f70b4
Packit 8f70b4
/* Use the old Solaris threads library.  */
Packit 8f70b4
Packit 8f70b4
# include <thread.h>
Packit 8f70b4
# include <synch.h>
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
extern "C" {
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
# if USE_SOLARIS_THREADS_WEAK
Packit 8f70b4
Packit 8f70b4
/* Use weak references to the old Solaris threads library.  */
Packit 8f70b4
Packit 8f70b4
#  pragma weak mutex_init
Packit 8f70b4
#  pragma weak mutex_lock
Packit 8f70b4
#  pragma weak mutex_unlock
Packit 8f70b4
#  pragma weak mutex_destroy
Packit 8f70b4
#  pragma weak rwlock_init
Packit 8f70b4
#  pragma weak rw_rdlock
Packit 8f70b4
#  pragma weak rw_wrlock
Packit 8f70b4
#  pragma weak rw_unlock
Packit 8f70b4
#  pragma weak rwlock_destroy
Packit 8f70b4
#  pragma weak thr_self
Packit 8f70b4
Packit 8f70b4
#  pragma weak thr_suspend
Packit 8f70b4
#  define thread_in_use() (thr_suspend != NULL)
Packit 8f70b4
Packit 8f70b4
# else
Packit 8f70b4
Packit 8f70b4
#  define thread_in_use() 1
Packit 8f70b4
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef mutex_t gl_lock_t;
Packit 8f70b4
# define gl_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS mutex_t NAME;
Packit 8f70b4
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS mutex_t NAME = gl_lock_initializer;
Packit 8f70b4
# define gl_lock_initializer \
Packit 8f70b4
    DEFAULTMUTEX
Packit 8f70b4
# define glthread_lock_init(LOCK) \
Packit 8f70b4
    (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
Packit 8f70b4
# define glthread_lock_lock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? mutex_lock (LOCK) : 0)
Packit 8f70b4
# define glthread_lock_unlock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? mutex_unlock (LOCK) : 0)
Packit 8f70b4
# define glthread_lock_destroy(LOCK) \
Packit 8f70b4
    (thread_in_use () ? mutex_destroy (LOCK) : 0)
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef rwlock_t gl_rwlock_t;
Packit 8f70b4
# define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS rwlock_t NAME;
Packit 8f70b4
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
# define gl_rwlock_initializer \
Packit 8f70b4
    DEFAULTRWLOCK
Packit 8f70b4
# define glthread_rwlock_init(LOCK) \
Packit 8f70b4
    (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
Packit 8f70b4
# define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? rw_rdlock (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? rw_wrlock (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? rw_unlock (LOCK) : 0)
Packit 8f70b4
# define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
    (thread_in_use () ? rwlock_destroy (LOCK) : 0)
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
/* Old Solaris threads did not have recursive locks.
Packit 8f70b4
   We have to implement them ourselves.  */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          mutex_t mutex;
Packit 8f70b4
          thread_t owner;
Packit 8f70b4
          unsigned long depth;
Packit 8f70b4
        }
Packit 8f70b4
        gl_recursive_lock_t;
Packit 8f70b4
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_recursive_lock_t NAME;
Packit 8f70b4
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
# define gl_recursive_lock_initializer \
Packit 8f70b4
    { DEFAULTMUTEX, (thread_t) 0, 0 }
Packit 8f70b4
# define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
    (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
    (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
Packit 8f70b4
# define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
    (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
Packit 8f70b4
extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          volatile int inited;
Packit 8f70b4
          mutex_t mutex;
Packit 8f70b4
        }
Packit 8f70b4
        gl_once_t;
Packit 8f70b4
# define gl_once_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
Packit 8f70b4
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
Packit 8f70b4
    (thread_in_use ()                                                          \
Packit 8f70b4
     ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)                \
Packit 8f70b4
     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
Packit 8f70b4
extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
Packit 8f70b4
extern int glthread_once_singlethreaded (gl_once_t *once_control);
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
}
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#if USE_WINDOWS_THREADS
Packit 8f70b4
Packit 8f70b4
# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
Packit 8f70b4
# include <windows.h>
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
extern "C" {
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
/* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
Packit 8f70b4
   Mutex, Semaphore types, because
Packit 8f70b4
     - we need only to synchronize inside a single process (address space),
Packit 8f70b4
       not inter-process locking,
Packit 8f70b4
     - we don't need to support trylock operations.  (TryEnterCriticalSection
Packit 8f70b4
       does not work on Windows 95/98/ME.  Packages that need trylock usually
Packit 8f70b4
       define their own mutex type.)  */
Packit 8f70b4
Packit 8f70b4
/* There is no way to statically initialize a CRITICAL_SECTION.  It needs
Packit 8f70b4
   to be done lazily, once only.  For this we need spinlocks.  */
Packit 8f70b4
Packit 8f70b4
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          gl_spinlock_t guard; /* protects the initialization */
Packit 8f70b4
          CRITICAL_SECTION lock;
Packit 8f70b4
        }
Packit 8f70b4
        gl_lock_t;
Packit 8f70b4
# define gl_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_lock_t NAME;
Packit 8f70b4
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
Packit 8f70b4
# define gl_lock_initializer \
Packit 8f70b4
    { { 0, -1 } }
Packit 8f70b4
# define glthread_lock_init(LOCK) \
Packit 8f70b4
    (glthread_lock_init_func (LOCK), 0)
Packit 8f70b4
# define glthread_lock_lock(LOCK) \
Packit 8f70b4
    glthread_lock_lock_func (LOCK)
Packit 8f70b4
# define glthread_lock_unlock(LOCK) \
Packit 8f70b4
    glthread_lock_unlock_func (LOCK)
Packit 8f70b4
# define glthread_lock_destroy(LOCK) \
Packit 8f70b4
    glthread_lock_destroy_func (LOCK)
Packit 8f70b4
extern void glthread_lock_init_func (gl_lock_t *lock);
Packit 8f70b4
extern int glthread_lock_lock_func (gl_lock_t *lock);
Packit 8f70b4
extern int glthread_lock_unlock_func (gl_lock_t *lock);
Packit 8f70b4
extern int glthread_lock_destroy_func (gl_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
/* It is impossible to implement read-write locks using plain locks, without
Packit 8f70b4
   introducing an extra thread dedicated to managing read-write locks.
Packit 8f70b4
   Therefore here we need to use the low-level Event type.  */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          HANDLE *array; /* array of waiting threads, each represented by an event */
Packit 8f70b4
          unsigned int count; /* number of waiting threads */
Packit 8f70b4
          unsigned int alloc; /* length of allocated array */
Packit 8f70b4
          unsigned int offset; /* index of first waiting thread in array */
Packit 8f70b4
        }
Packit 8f70b4
        gl_carray_waitqueue_t;
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          gl_spinlock_t guard; /* protects the initialization */
Packit 8f70b4
          CRITICAL_SECTION lock; /* protects the remaining fields */
Packit 8f70b4
          gl_carray_waitqueue_t waiting_readers; /* waiting readers */
Packit 8f70b4
          gl_carray_waitqueue_t waiting_writers; /* waiting writers */
Packit 8f70b4
          int runcount; /* number of readers running, or -1 when a writer runs */
Packit 8f70b4
        }
Packit 8f70b4
        gl_rwlock_t;
Packit 8f70b4
# define gl_rwlock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_rwlock_t NAME;
Packit 8f70b4
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
Packit 8f70b4
# define gl_rwlock_initializer \
Packit 8f70b4
    { { 0, -1 } }
Packit 8f70b4
# define glthread_rwlock_init(LOCK) \
Packit 8f70b4
    (glthread_rwlock_init_func (LOCK), 0)
Packit 8f70b4
# define glthread_rwlock_rdlock(LOCK) \
Packit 8f70b4
    glthread_rwlock_rdlock_func (LOCK)
Packit 8f70b4
# define glthread_rwlock_wrlock(LOCK) \
Packit 8f70b4
    glthread_rwlock_wrlock_func (LOCK)
Packit 8f70b4
# define glthread_rwlock_unlock(LOCK) \
Packit 8f70b4
    glthread_rwlock_unlock_func (LOCK)
Packit 8f70b4
# define glthread_rwlock_destroy(LOCK) \
Packit 8f70b4
    glthread_rwlock_destroy_func (LOCK)
Packit 8f70b4
extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
Packit 8f70b4
extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
/* The native Windows documentation says that CRITICAL_SECTION already
Packit 8f70b4
   implements a recursive lock.  But we need not rely on it: It's easy to
Packit 8f70b4
   implement a recursive lock without this assumption.  */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          gl_spinlock_t guard; /* protects the initialization */
Packit 8f70b4
          DWORD owner;
Packit 8f70b4
          unsigned long depth;
Packit 8f70b4
          CRITICAL_SECTION lock;
Packit 8f70b4
        }
Packit 8f70b4
        gl_recursive_lock_t;
Packit 8f70b4
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_recursive_lock_t NAME;
Packit 8f70b4
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
Packit 8f70b4
# define gl_recursive_lock_initializer \
Packit 8f70b4
    { { 0, -1 }, 0, 0 }
Packit 8f70b4
# define glthread_recursive_lock_init(LOCK) \
Packit 8f70b4
    (glthread_recursive_lock_init_func (LOCK), 0)
Packit 8f70b4
# define glthread_recursive_lock_lock(LOCK) \
Packit 8f70b4
    glthread_recursive_lock_lock_func (LOCK)
Packit 8f70b4
# define glthread_recursive_lock_unlock(LOCK) \
Packit 8f70b4
    glthread_recursive_lock_unlock_func (LOCK)
Packit 8f70b4
# define glthread_recursive_lock_destroy(LOCK) \
Packit 8f70b4
    glthread_recursive_lock_destroy_func (LOCK)
Packit 8f70b4
extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
Packit 8f70b4
extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef struct
Packit 8f70b4
        {
Packit 8f70b4
          volatile int inited;
Packit 8f70b4
          volatile long started;
Packit 8f70b4
          CRITICAL_SECTION lock;
Packit 8f70b4
        }
Packit 8f70b4
        gl_once_t;
Packit 8f70b4
# define gl_once_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_once_t NAME = { -1, -1 };
Packit 8f70b4
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
Packit 8f70b4
    (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0)
Packit 8f70b4
extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
Packit 8f70b4
Packit 8f70b4
# ifdef __cplusplus
Packit 8f70b4
}
Packit 8f70b4
# endif
Packit 8f70b4
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
Packit 8f70b4
Packit 8f70b4
/* Provide dummy implementation if threads are not supported.  */
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef int gl_lock_t;
Packit 8f70b4
# define gl_lock_define(STORAGECLASS, NAME)
Packit 8f70b4
# define gl_lock_define_initialized(STORAGECLASS, NAME)
Packit 8f70b4
# define glthread_lock_init(NAME) 0
Packit 8f70b4
# define glthread_lock_lock(NAME) 0
Packit 8f70b4
# define glthread_lock_unlock(NAME) 0
Packit 8f70b4
# define glthread_lock_destroy(NAME) 0
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef int gl_rwlock_t;
Packit 8f70b4
# define gl_rwlock_define(STORAGECLASS, NAME)
Packit 8f70b4
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
Packit 8f70b4
# define glthread_rwlock_init(NAME) 0
Packit 8f70b4
# define glthread_rwlock_rdlock(NAME) 0
Packit 8f70b4
# define glthread_rwlock_wrlock(NAME) 0
Packit 8f70b4
# define glthread_rwlock_unlock(NAME) 0
Packit 8f70b4
# define glthread_rwlock_destroy(NAME) 0
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
typedef int gl_recursive_lock_t;
Packit 8f70b4
# define gl_recursive_lock_define(STORAGECLASS, NAME)
Packit 8f70b4
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
Packit 8f70b4
# define glthread_recursive_lock_init(NAME) 0
Packit 8f70b4
# define glthread_recursive_lock_lock(NAME) 0
Packit 8f70b4
# define glthread_recursive_lock_unlock(NAME) 0
Packit 8f70b4
# define glthread_recursive_lock_destroy(NAME) 0
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
typedef int gl_once_t;
Packit 8f70b4
# define gl_once_define(STORAGECLASS, NAME) \
Packit 8f70b4
    STORAGECLASS gl_once_t NAME = 0;
Packit 8f70b4
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
Packit 8f70b4
    (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
Packit 8f70b4
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
/* Macros with built-in error handling.  */
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_lock_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
#define gl_lock_init(NAME) \
Packit 8f70b4
   do                                  \
Packit 8f70b4
     {                                 \
Packit 8f70b4
       if (glthread_lock_init (&NAME)) \
Packit 8f70b4
         abort ();                     \
Packit 8f70b4
     }                                 \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_lock_lock(NAME) \
Packit 8f70b4
   do                                  \
Packit 8f70b4
     {                                 \
Packit 8f70b4
       if (glthread_lock_lock (&NAME)) \
Packit 8f70b4
         abort ();                     \
Packit 8f70b4
     }                                 \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_lock_unlock(NAME) \
Packit 8f70b4
   do                                    \
Packit 8f70b4
     {                                   \
Packit 8f70b4
       if (glthread_lock_unlock (&NAME)) \
Packit 8f70b4
         abort ();                       \
Packit 8f70b4
     }                                   \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_lock_destroy(NAME) \
Packit 8f70b4
   do                                     \
Packit 8f70b4
     {                                    \
Packit 8f70b4
       if (glthread_lock_destroy (&NAME)) \
Packit 8f70b4
         abort ();                        \
Packit 8f70b4
     }                                    \
Packit 8f70b4
   while (0)
Packit 8f70b4
Packit 8f70b4
/* ------------------------- gl_rwlock_t datatype ------------------------- */
Packit 8f70b4
Packit 8f70b4
#define gl_rwlock_init(NAME) \
Packit 8f70b4
   do                                    \
Packit 8f70b4
     {                                   \
Packit 8f70b4
       if (glthread_rwlock_init (&NAME)) \
Packit 8f70b4
         abort ();                       \
Packit 8f70b4
     }                                   \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_rwlock_rdlock(NAME) \
Packit 8f70b4
   do                                      \
Packit 8f70b4
     {                                     \
Packit 8f70b4
       if (glthread_rwlock_rdlock (&NAME)) \
Packit 8f70b4
         abort ();                         \
Packit 8f70b4
     }                                     \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_rwlock_wrlock(NAME) \
Packit 8f70b4
   do                                      \
Packit 8f70b4
     {                                     \
Packit 8f70b4
       if (glthread_rwlock_wrlock (&NAME)) \
Packit 8f70b4
         abort ();                         \
Packit 8f70b4
     }                                     \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_rwlock_unlock(NAME) \
Packit 8f70b4
   do                                      \
Packit 8f70b4
     {                                     \
Packit 8f70b4
       if (glthread_rwlock_unlock (&NAME)) \
Packit 8f70b4
         abort ();                         \
Packit 8f70b4
     }                                     \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_rwlock_destroy(NAME) \
Packit 8f70b4
   do                                       \
Packit 8f70b4
     {                                      \
Packit 8f70b4
       if (glthread_rwlock_destroy (&NAME)) \
Packit 8f70b4
         abort ();                          \
Packit 8f70b4
     }                                      \
Packit 8f70b4
   while (0)
Packit 8f70b4
Packit 8f70b4
/* --------------------- gl_recursive_lock_t datatype --------------------- */
Packit 8f70b4
Packit 8f70b4
#define gl_recursive_lock_init(NAME) \
Packit 8f70b4
   do                                            \
Packit 8f70b4
     {                                           \
Packit 8f70b4
       if (glthread_recursive_lock_init (&NAME)) \
Packit 8f70b4
         abort ();                               \
Packit 8f70b4
     }                                           \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_recursive_lock_lock(NAME) \
Packit 8f70b4
   do                                            \
Packit 8f70b4
     {                                           \
Packit 8f70b4
       if (glthread_recursive_lock_lock (&NAME)) \
Packit 8f70b4
         abort ();                               \
Packit 8f70b4
     }                                           \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_recursive_lock_unlock(NAME) \
Packit 8f70b4
   do                                              \
Packit 8f70b4
     {                                             \
Packit 8f70b4
       if (glthread_recursive_lock_unlock (&NAME)) \
Packit 8f70b4
         abort ();                                 \
Packit 8f70b4
     }                                             \
Packit 8f70b4
   while (0)
Packit 8f70b4
#define gl_recursive_lock_destroy(NAME) \
Packit 8f70b4
   do                                               \
Packit 8f70b4
     {                                              \
Packit 8f70b4
       if (glthread_recursive_lock_destroy (&NAME)) \
Packit 8f70b4
         abort ();                                  \
Packit 8f70b4
     }                                              \
Packit 8f70b4
   while (0)
Packit 8f70b4
Packit 8f70b4
/* -------------------------- gl_once_t datatype -------------------------- */
Packit 8f70b4
Packit 8f70b4
#define gl_once(NAME, INITFUNCTION) \
Packit 8f70b4
   do                                           \
Packit 8f70b4
     {                                          \
Packit 8f70b4
       if (glthread_once (&NAME, INITFUNCTION)) \
Packit 8f70b4
         abort ();                              \
Packit 8f70b4
     }                                          \
Packit 8f70b4
   while (0)
Packit 8f70b4
Packit 8f70b4
/* ========================================================================= */
Packit 8f70b4
Packit 8f70b4
#endif /* _LOCK_H */