Blame lib/glthread/lock.h

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