Blame gnulib/lib/glthread/lock.h

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