From 65bdf35448200a253a0bbb38dcdfa12e15f15c0b Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 3 Aug 2008 20:45:40 +0200 Subject: [PATCH] Additional non-aborting API for lock and tls. --- ChangeLog | 69 +++++ lib/lock.c | 534 +++++++++++++++++++++------------- lib/lock.h | 823 +++++++++++++++++++++-------------------------------- lib/tls.c | 4 +- lib/tls.h | 211 ++++++-------- 5 files changed, 824 insertions(+), 817 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96e0279a30..b770e87adb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,72 @@ +2008-08-03 Bruno Haible + + Additional non-aborting API for lock and tls. + * lib/lock.h: Include . + (glthread_lock_init): New macro/function. + (gl_lock_init): Define as wrapper around glthread_lock_init. + (glthread_lock_lock): New macro/function. + (gl_lock_lock): Define as wrapper around glthread_lock_lock. + (glthread_lock_unlock): New macro/function. + (gl_lock_unlock): Define as wrapper around glthread_lock_unlock. + (glthread_lock_destroy): New macro/function. + (gl_lock_destroy): Define as wrapper around glthread_lock_destroy. + (glthread_rwlock_init): New macro/function. + (gl_rwlock_init): Define as wrapper around glthread_rwlock_init. + (glthread_rwlock_rdlock): New macro/function. + (gl_rwlock_rdlock): Define as wrapper around glthread_rwlock_rdlock. + (glthread_rwlock_wrlock): New macro/function. + (gl_rwlock_wrlock): Define as wrapper around glthread_rwlock_wrlock. + (glthread_rwlock_unlock): New macro/function. + (gl_rwlock_unlock): Define as wrapper around glthread_rwlock_unlock. + (glthread_rwlock_destroy): New macro/function. + (gl_rwlock_destroy): Define as wrapper around glthread_rwlock_destroy. + (glthread_recursive_lock_init): New macro/function. + (gl_recursive_lock_init): Define as wrapper around + glthread_recursive_lock_init. + (glthread_recursive_lock_lock): New macro/function. + (gl_recursive_lock_lock): Define as wrapper around + glthread_recursive_lock_lock. + (glthread_recursive_lock_unlock): New macro/function. + (gl_recursive_lock_unlock): Define as wrapper around + glthread_recursive_lock_unlock. + (glthread_recursive_lock_destroy): New macro/function. + (gl_recursive_lock_destroy): Define as wrapper around + glthread_recursive_lock_destroy. + (glthread_once): New macro/function. + (gl_once): Define as wrapper around glthread_once. + Update function declarations. + * lib/lock.c (glthread_rwlock_init_multithreaded): Renamed from + glthread_rwlock_init. Return error code. + (glthread_rwlock_rdlock_multithreaded): Renamed from + glthread_rwlock_rdlock. Return error code. + (glthread_rwlock_wrlock_multithreaded): Renamed from + glthread_rwlock_wrlock. Return error code. + (glthread_rwlock_unlock_multithreaded): Renamed from + glthread_rwlock_unlock. Return error code. + (glthread_rwlock_destroy_multithreaded): Renamed from + glthread_rwlock_destroy. Return error code. + (glthread_recursive_lock_init_multithreaded): Renamed from + glthread_recursive_lock_init. Return error code. + (glthread_recursive_lock_lock_multithreaded): Renamed from + glthread_recursive_lock_lock. Return error code. + (glthread_recursive_lock_unlock_multithreaded): Renamed from + glthread_recursive_lock_unlock. Return error code. + (glthread_recursive_lock_destroy_multithreaded): Renamed from + glthread_recursive_lock_destroy. Return error code. + (glthread_once_call): Make static. + (glthread_once_multithreaded): Renamed from glthread_once. + * lib/tls.h: Include . + (glthread_tls_key_init): New macro/function. + (gl_tls_key_init): Define as wrapper around glthread_tls_key_init. + (glthread_tls_set): New macro/function. + (gl_tls_set): Define as wrapper around glthread_tls_set. + (glthread_tls_key_destroy): New macro/function. + (gl_tls_key_destroy): Define as wrapper around glthread_tls_key_destroy. + Update function declarations. + * lib/tls.c (glthread_tls_get_multithreaded): Renamed from + glthread_tls_get. + Suggested by Yoann Vandoorselaere . + 2008-08-04 Eric Blake gnumakefile: use space, not TAB, outside of targets diff --git a/lib/lock.c b/lib/lock.c index c23b8b8460..709da69ccc 100644 --- a/lib/lock.c +++ b/lib/lock.c @@ -1,5 +1,5 @@ /* Locking in multithreaded situations. - Copyright (C) 2005-2007 Free Software Foundation, Inc. + Copyright (C) 2005-2008 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,87 +74,123 @@ glthread_in_use (void) # if !defined PTHREAD_RWLOCK_INITIALIZER -void -glthread_rwlock_init (gl_rwlock_t *lock) +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) { - if (pthread_rwlock_init (&lock->rwlock, NULL) != 0) - abort (); + int err; + + err = pthread_rwlock_init (&lock->rwlock, NULL); + if (err != 0) + return err; lock->initialized = 1; + return 0; } -void -glthread_rwlock_rdlock (gl_rwlock_t *lock) +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) { if (!lock->initialized) { - if (pthread_mutex_lock (&lock->guard) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; if (!lock->initialized) - glthread_rwlock_init (lock); - if (pthread_mutex_unlock (&lock->guard) != 0) - abort (); + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; } - if (pthread_rwlock_rdlock (&lock->rwlock) != 0) - abort (); + return pthread_rwlock_rdlock (&lock->rwlock); } -void -glthread_rwlock_wrlock (gl_rwlock_t *lock) +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) { if (!lock->initialized) { - if (pthread_mutex_lock (&lock->guard) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; if (!lock->initialized) - glthread_rwlock_init (lock); - if (pthread_mutex_unlock (&lock->guard) != 0) - abort (); + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; } - if (pthread_rwlock_wrlock (&lock->rwlock) != 0) - abort (); + return pthread_rwlock_wrlock (&lock->rwlock); } -void -glthread_rwlock_unlock (gl_rwlock_t *lock) +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) { if (!lock->initialized) - abort (); - if (pthread_rwlock_unlock (&lock->rwlock) != 0) - abort (); + return EINVAL; + return pthread_rwlock_unlock (&lock->rwlock); } -void -glthread_rwlock_destroy (gl_rwlock_t *lock) +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) { + int err; + if (!lock->initialized) - abort (); - if (pthread_rwlock_destroy (&lock->rwlock) != 0) - abort (); + return EINVAL; + err = pthread_rwlock_destroy (&lock->rwlock); + if (err != 0) + return err; lock->initialized = 0; + return 0; } # endif # else -void -glthread_rwlock_init (gl_rwlock_t *lock) -{ - if (pthread_mutex_init (&lock->lock, NULL) != 0) - abort (); - if (pthread_cond_init (&lock->waiting_readers, NULL) != 0) - abort (); - if (pthread_cond_init (&lock->waiting_writers, NULL) != 0) - abort (); +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_init (&lock->lock, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_readers, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_writers, NULL); + if (err != 0) + return err; lock->waiting_writers_count = 0; lock->runcount = 0; + return 0; } -void -glthread_rwlock_rdlock (gl_rwlock_t *lock) +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) { - if (pthread_mutex_lock (&lock->lock) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; /* Test whether only readers are currently running, and whether the runcount field will not overflow. */ /* POSIX says: "It is implementation-defined whether the calling thread @@ -165,51 +201,70 @@ glthread_rwlock_rdlock (gl_rwlock_t *lock) { /* This thread has to wait for a while. Enqueue it among the waiting_readers. */ - if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0) - abort (); + err = pthread_cond_wait (&lock->waiting_readers, &lock->lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } } lock->runcount++; - if (pthread_mutex_unlock (&lock->lock) != 0) - abort (); + return pthread_mutex_unlock (&lock->lock); } -void -glthread_rwlock_wrlock (gl_rwlock_t *lock) +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) { - if (pthread_mutex_lock (&lock->lock) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; /* Test whether no readers or writers are currently running. */ while (!(lock->runcount == 0)) { /* This thread has to wait for a while. Enqueue it among the waiting_writers. */ lock->waiting_writers_count++; - if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0) - abort (); + err = pthread_cond_wait (&lock->waiting_writers, &lock->lock); + if (err != 0) + { + lock->waiting_writers_count--; + pthread_mutex_unlock (&lock->lock); + return err; + } lock->waiting_writers_count--; } lock->runcount--; /* runcount becomes -1 */ - if (pthread_mutex_unlock (&lock->lock) != 0) - abort (); + return pthread_mutex_unlock (&lock->lock); } -void -glthread_rwlock_unlock (gl_rwlock_t *lock) +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) { - if (pthread_mutex_lock (&lock->lock) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; if (lock->runcount < 0) { /* Drop a writer lock. */ if (!(lock->runcount == -1)) - abort (); + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } lock->runcount = 0; } else { /* Drop a reader lock. */ if (!(lock->runcount > 0)) - abort (); + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } lock->runcount--; } if (lock->runcount == 0) @@ -219,29 +274,42 @@ glthread_rwlock_unlock (gl_rwlock_t *lock) if (lock->waiting_writers_count > 0) { /* Wake up one of the waiting writers. */ - if (pthread_cond_signal (&lock->waiting_writers) != 0) - abort (); + err = pthread_cond_signal (&lock->waiting_writers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } } else { /* Wake up all waiting readers. */ - if (pthread_cond_broadcast (&lock->waiting_readers) != 0) - abort (); + err = pthread_cond_broadcast (&lock->waiting_readers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } } } - if (pthread_mutex_unlock (&lock->lock) != 0) - abort (); + return pthread_mutex_unlock (&lock->lock); } -void -glthread_rwlock_destroy (gl_rwlock_t *lock) +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) { - if (pthread_mutex_destroy (&lock->lock) != 0) - abort (); - if (pthread_cond_destroy (&lock->waiting_readers) != 0) - abort (); - if (pthread_cond_destroy (&lock->waiting_writers) != 0) - abort (); + int err; + + err = pthread_mutex_destroy (&lock->lock); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_readers); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_writers); + if (err != 0) + return err; + return 0; } # endif @@ -252,123 +320,171 @@ glthread_rwlock_destroy (gl_rwlock_t *lock) # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -void -glthread_recursive_lock_init (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) { pthread_mutexattr_t attributes; + int err; - if (pthread_mutexattr_init (&attributes) != 0) - abort (); - if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) - abort (); - if (pthread_mutex_init (lock, &attributes) != 0) - abort (); - if (pthread_mutexattr_destroy (&attributes) != 0) - abort (); + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (lock, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return err; + return 0; } # else -void -glthread_recursive_lock_init (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) { pthread_mutexattr_t attributes; + int err; - if (pthread_mutexattr_init (&attributes) != 0) - abort (); - if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) - abort (); - if (pthread_mutex_init (&lock->recmutex, &attributes) != 0) - abort (); - if (pthread_mutexattr_destroy (&attributes) != 0) - abort (); + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (&lock->recmutex, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return ret; lock->initialized = 1; + return 0; } -void -glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) { if (!lock->initialized) { - if (pthread_mutex_lock (&lock->guard) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; if (!lock->initialized) - glthread_recursive_lock_init (lock); - if (pthread_mutex_unlock (&lock->guard) != 0) - abort (); + { + err = glthread_recursive_lock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; } - if (pthread_mutex_lock (&lock->recmutex) != 0) - abort (); + return pthread_mutex_lock (&lock->recmutex); } -void -glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) { if (!lock->initialized) - abort (); - if (pthread_mutex_unlock (&lock->recmutex) != 0) - abort (); + return EINVAL; + return pthread_mutex_unlock (&lock->recmutex); } -void -glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) { + int err; + if (!lock->initialized) - abort (); - if (pthread_mutex_destroy (&lock->recmutex) != 0) - abort (); + return EINVAL; + err = pthread_mutex_destroy (&lock->recmutex); + if (err != 0) + return err; lock->initialized = 0; + return 0; } # endif # else -void -glthread_recursive_lock_init (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) { - if (pthread_mutex_init (&lock->mutex, NULL) != 0) - abort (); + int err; + + err = pthread_mutex_init (&lock->mutex, NULL); + if (err != 0) + return err; lock->owner = (pthread_t) 0; lock->depth = 0; + return 0; } -void -glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) { pthread_t self = pthread_self (); if (lock->owner != self) { - if (pthread_mutex_lock (&lock->mutex) != 0) - abort (); + int err; + + err = pthread_mutex_lock (&lock->mutex); + if (err != 0) + return err; lock->owner = self; } if (++(lock->depth) == 0) /* wraparound? */ - abort (); + { + lock->depth--; + return EAGAIN; + } + return 0; } -void -glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) { if (lock->owner != pthread_self ()) - abort (); + return EPERM; if (lock->depth == 0) - abort (); + return EINVAL; if (--(lock->depth) == 0) { lock->owner = (pthread_t) 0; - if (pthread_mutex_unlock (&lock->mutex) != 0) - abort (); + return pthread_mutex_unlock (&lock->mutex); } + else + return 0; } -void -glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) { if (lock->owner != (pthread_t) 0) - abort (); - if (pthread_mutex_destroy (&lock->mutex) != 0) - abort (); + return EBUSY; + return (pthread_mutex_destroy (&lock->mutex); } # endif @@ -409,7 +525,7 @@ glthread_once_singlethreaded (pthread_once_t *once_control) /* -------------------------- gl_once_t datatype -------------------------- */ -void +static void glthread_once_call (void *arg) { void (**gl_once_temp_addr) (void) = (void (**) (void)) arg; @@ -417,6 +533,13 @@ glthread_once_call (void *arg) initfunction (); } +int +glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)) +{ + void (*temp) (void) = initfunction; + return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0); +} + int glthread_once_singlethreaded (pth_once_t *once_control) { @@ -445,72 +568,87 @@ glthread_once_singlethreaded (pth_once_t *once_control) /* --------------------- gl_recursive_lock_t datatype --------------------- */ -void -glthread_recursive_lock_init (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) { - if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0) - abort (); + int err; + + err = mutex_init (&lock->mutex, USYNC_THREAD, NULL); + if (err != 0) + return err; lock->owner = (thread_t) 0; lock->depth = 0; + return 0; } -void -glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) { thread_t self = thr_self (); if (lock->owner != self) { - if (mutex_lock (&lock->mutex) != 0) - abort (); + int err; + + err = mutex_lock (&lock->mutex); + if (err != 0) + return err; lock->owner = self; } if (++(lock->depth) == 0) /* wraparound? */ - abort (); + { + lock->depth--; + return EAGAIN; + } + return 0; } -void -glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) { if (lock->owner != thr_self ()) - abort (); + return EPERM; if (lock->depth == 0) - abort (); + return EINVAL; if (--(lock->depth) == 0) { lock->owner = (thread_t) 0; - if (mutex_unlock (&lock->mutex) != 0) - abort (); + return mutex_unlock (&lock->mutex); } + else + return 0; } -void -glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) { if (lock->owner != (thread_t) 0) - abort (); - if (mutex_destroy (&lock->mutex) != 0) - abort (); + return EBUSY; + return mutex_destroy (&lock->mutex); } /* -------------------------- gl_once_t datatype -------------------------- */ -void -glthread_once (gl_once_t *once_control, void (*initfunction) (void)) +int +glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)) { if (!once_control->inited) { + int err; + /* Use the mutex to guarantee that if another thread is already calling the initfunction, this thread waits until it's finished. */ - if (mutex_lock (&once_control->mutex) != 0) - abort (); + err = mutex_lock (&once_control->mutex); + if (err != 0) + return err; if (!once_control->inited) { once_control->inited = 1; initfunction (); } - if (mutex_unlock (&once_control->mutex) != 0) - abort (); + return mutex_unlock (&once_control->mutex); } + else + return 0; } int @@ -536,13 +674,13 @@ glthread_once_singlethreaded (gl_once_t *once_control) /* -------------------------- gl_lock_t datatype -------------------------- */ void -glthread_lock_init (gl_lock_t *lock) +glthread_lock_init_func (gl_lock_t *lock) { InitializeCriticalSection (&lock->lock); lock->guard.done = 1; } -void +int glthread_lock_lock (gl_lock_t *lock) { if (!lock->guard.done) @@ -557,23 +695,26 @@ glthread_lock_lock (gl_lock_t *lock) Sleep (0); } EnterCriticalSection (&lock->lock); + return 0; } -void +int glthread_lock_unlock (gl_lock_t *lock) { if (!lock->guard.done) - abort (); + return EINVAL; LeaveCriticalSection (&lock->lock); + return 0; } -void +int glthread_lock_destroy (gl_lock_t *lock) { if (!lock->guard.done) - abort (); + return EINVAL; DeleteCriticalSection (&lock->lock); lock->guard.done = 0; + return 0; } /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -665,7 +806,7 @@ gl_waitqueue_notify_all (gl_waitqueue_t *wq) } void -glthread_rwlock_init (gl_rwlock_t *lock) +glthread_rwlock_init_func (gl_rwlock_t *lock) { InitializeCriticalSection (&lock->lock); gl_waitqueue_init (&lock->waiting_readers); @@ -674,7 +815,7 @@ glthread_rwlock_init (gl_rwlock_t *lock) lock->guard.done = 1; } -void +int glthread_rwlock_rdlock (gl_rwlock_t *lock) { if (!lock->guard.done) @@ -709,7 +850,7 @@ glthread_rwlock_rdlock (gl_rwlock_t *lock) removed us from the waiting_readers, incremented lock->runcount. */ if (!(lock->runcount > 0)) abort (); - return; + return 0; } else { @@ -725,9 +866,10 @@ glthread_rwlock_rdlock (gl_rwlock_t *lock) } lock->runcount++; LeaveCriticalSection (&lock->lock); + return 0; } -void +int glthread_rwlock_wrlock (gl_rwlock_t *lock) { if (!lock->guard.done) @@ -761,7 +903,7 @@ glthread_rwlock_wrlock (gl_rwlock_t *lock) removed us from the waiting_writers, set lock->runcount = -1. */ if (!(lock->runcount == -1)) abort (); - return; + return 0; } else { @@ -777,13 +919,14 @@ glthread_rwlock_wrlock (gl_rwlock_t *lock) } lock->runcount--; /* runcount becomes -1 */ LeaveCriticalSection (&lock->lock); + return 0; } -void +int glthread_rwlock_unlock (gl_rwlock_t *lock) { if (!lock->guard.done) - abort (); + return EINVAL; EnterCriticalSection (&lock->lock); if (lock->runcount < 0) { @@ -796,7 +939,10 @@ glthread_rwlock_unlock (gl_rwlock_t *lock) { /* Drop a reader lock. */ if (!(lock->runcount > 0)) - abort (); + { + LeaveCriticalSection (&lock->lock); + return EPERM; + } lock->runcount--; } if (lock->runcount == 0) @@ -817,27 +963,29 @@ glthread_rwlock_unlock (gl_rwlock_t *lock) } } LeaveCriticalSection (&lock->lock); + return 0; } -void +int glthread_rwlock_destroy (gl_rwlock_t *lock) { if (!lock->guard.done) - abort (); + return EINVAL; if (lock->runcount != 0) - abort (); + return EBUSY; DeleteCriticalSection (&lock->lock); if (lock->waiting_readers.array != NULL) free (lock->waiting_readers.array); if (lock->waiting_writers.array != NULL) free (lock->waiting_writers.array); lock->guard.done = 0; + return 0; } /* --------------------- gl_recursive_lock_t datatype --------------------- */ void -glthread_recursive_lock_init (gl_recursive_lock_t *lock) +glthread_recursive_lock_init_func (gl_recursive_lock_t *lock) { lock->owner = 0; lock->depth = 0; @@ -845,7 +993,7 @@ glthread_recursive_lock_init (gl_recursive_lock_t *lock) lock->guard.done = 1; } -void +int glthread_recursive_lock_lock (gl_recursive_lock_t *lock) { if (!lock->guard.done) @@ -867,37 +1015,43 @@ glthread_recursive_lock_lock (gl_recursive_lock_t *lock) lock->owner = self; } if (++(lock->depth) == 0) /* wraparound? */ - abort (); + { + lock->depth--; + return EAGAIN; + } } + return 0; } -void +int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) { if (lock->owner != GetCurrentThreadId ()) - abort (); + return EPERM; if (lock->depth == 0) - abort (); + return EINVAL; if (--(lock->depth) == 0) { lock->owner = 0; LeaveCriticalSection (&lock->lock); } + return 0; } -void +int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) { if (lock->owner != 0) - abort (); + return EBUSY; DeleteCriticalSection (&lock->lock); lock->guard.done = 0; + return 0; } /* -------------------------- gl_once_t datatype -------------------------- */ void -glthread_once (gl_once_t *once_control, void (*initfunction) (void)) +glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) { if (once_control->inited <= 0) { diff --git a/lib/lock.h b/lib/lock.h index 32a35bbc76..2064b2ffc0 100644 --- a/lib/lock.h +++ b/lib/lock.h @@ -31,6 +31,11 @@ Taking the lock: gl_lock_lock (name); Releasing the lock: gl_lock_unlock (name); De-initialization: gl_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_lock_init (&name); + Taking the lock: err = glthread_lock_lock (&name); + Releasing the lock: err = glthread_lock_unlock (&name); + De-initialization: err = glthread_lock_destroy (&name); Read-Write (non-recursive) locks: Type: gl_rwlock_t @@ -41,6 +46,12 @@ gl_rwlock_wrlock (name); Releasing the lock: gl_rwlock_unlock (name); De-initialization: gl_rwlock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_rwlock_init (&name); + Taking the lock: err = glthread_rwlock_rdlock (&name); + err = glthread_rwlock_wrlock (&name); + Releasing the lock: err = glthread_rwlock_unlock (&name); + De-initialization: err = glthread_rwlock_destroy (&name); Recursive locks: Type: gl_recursive_lock_t @@ -50,17 +61,26 @@ Taking the lock: gl_recursive_lock_lock (name); Releasing the lock: gl_recursive_lock_unlock (name); De-initialization: gl_recursive_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_recursive_lock_init (&name); + Taking the lock: err = glthread_recursive_lock_lock (&name); + Releasing the lock: err = glthread_recursive_lock_unlock (&name); + De-initialization: err = glthread_recursive_lock_destroy (&name); Once-only execution: Type: gl_once_t Initializer: gl_once_define(extern, name) Execution: gl_once (name, initfunction); + Equivalent functions with control of error handling: + Execution: err = glthread_once (&name, initfunction); */ #ifndef _LOCK_H #define _LOCK_H +#include + /* ========================================================================= */ #if USE_POSIX_THREADS @@ -146,34 +166,14 @@ typedef pthread_mutex_t gl_lock_t; STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer; # define gl_lock_initializer \ PTHREAD_MUTEX_INITIALIZER -# define gl_lock_init(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_lock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \ - abort (); \ - } \ - while (0) +# define glthread_lock_init(LOCK) \ + (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -188,41 +188,16 @@ typedef pthread_rwlock_t gl_rwlock_t; STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ PTHREAD_RWLOCK_INITIALIZER -# define gl_rwlock_init(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \ - abort (); \ - } \ - while (0) +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0) # else @@ -239,46 +214,21 @@ typedef struct STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ { 0, PTHREAD_MUTEX_INITIALIZER } -# define gl_rwlock_init(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_init (&NAME); \ - } \ - while (0) -# define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_rdlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_wrlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_unlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_destroy (&NAME); \ - } \ - while (0) -extern void glthread_rwlock_init (gl_rwlock_t *lock); -extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); -extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); -extern void glthread_rwlock_unlock (gl_rwlock_t *lock); -extern void glthread_rwlock_destroy (gl_rwlock_t *lock); +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); # endif @@ -299,46 +249,21 @@ typedef struct STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } -# define gl_rwlock_init(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_init (&NAME); \ - } \ - while (0) -# define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_rdlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_wrlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_unlock (&NAME); \ - } \ - while (0) -# define gl_rwlock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_rwlock_destroy (&NAME); \ - } \ - while (0) -extern void glthread_rwlock_init (gl_rwlock_t *lock); -extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); -extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); -extern void glthread_rwlock_unlock (gl_rwlock_t *lock); -extern void glthread_rwlock_destroy (gl_rwlock_t *lock); +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); # endif @@ -360,35 +285,15 @@ typedef pthread_mutex_t gl_recursive_lock_t; # define gl_recursive_lock_initializer \ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP # endif -# define gl_recursive_lock_init(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_init (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_lock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_recursive_lock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_recursive_lock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \ - abort (); \ - } \ - while (0) -extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); # else @@ -405,38 +310,18 @@ typedef struct STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 } -# define gl_recursive_lock_init(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_init (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_lock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_lock (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_unlock (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_destroy (&NAME); \ - } \ - while (0) -extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); # endif @@ -458,38 +343,18 @@ typedef struct STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 } -# define gl_recursive_lock_init(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_init (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_lock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_lock (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_unlock(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_unlock (&NAME); \ - } \ - while (0) -# define gl_recursive_lock_destroy(NAME) \ - do \ - { \ - if (pthread_in_use ()) \ - glthread_recursive_lock_destroy (&NAME); \ - } \ - while (0) -extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); # endif @@ -498,21 +363,10 @@ extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); typedef pthread_once_t gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; -# define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (pthread_in_use ()) \ - { \ - if (pthread_once (&NAME, INITFUNCTION) != 0) \ - abort (); \ - } \ - else \ - { \ - if (glthread_once_singlethreaded (&NAME)) \ - INITFUNCTION (); \ - } \ - } \ - while (0) +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pthread_in_use () \ + ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) extern int glthread_once_singlethreaded (pthread_once_t *once_control); # ifdef __cplusplus @@ -564,29 +418,14 @@ typedef pth_mutex_t gl_lock_t; STORAGECLASS pth_mutex_t NAME = gl_lock_initializer; # define gl_lock_initializer \ PTH_MUTEX_INIT -# define gl_lock_init(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_init (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_lock_lock(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \ - abort (); \ - } \ - while (0) -# define gl_lock_unlock(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_release (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_lock_destroy(NAME) \ - (void)(&NAME) +# define glthread_lock_init(LOCK) \ + (pth_in_use() && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_lock_lock(LOCK) \ + (pth_in_use() && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_lock_unlock(LOCK) \ + (pth_in_use() && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_lock_destroy(LOCK) \ + ((void)(LOCK), 0) /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -597,38 +436,16 @@ typedef pth_rwlock_t gl_rwlock_t; STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ PTH_RWLOCK_INIT -# define gl_rwlock_init(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_rwlock_init (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (pth_in_use() \ - && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (pth_in_use() \ - && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_rwlock_release (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_destroy(NAME) \ - (void)(&NAME) +# define glthread_rwlock_init(LOCK) \ + (pth_in_use() && !pth_rwlock_init (LOCK) ? errno : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pth_in_use() && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pth_in_use() && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pth_in_use() && !pth_rwlock_release (LOCK) ? errno : 0) +# define glthread_rwlock_destroy(LOCK) \ + ((void)(LOCK), 0) /* --------------------- gl_recursive_lock_t datatype --------------------- */ @@ -640,52 +457,25 @@ typedef pth_mutex_t gl_recursive_lock_t; STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ PTH_MUTEX_INIT -# define gl_recursive_lock_init(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_init (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_recursive_lock_lock(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \ - abort (); \ - } \ - while (0) -# define gl_recursive_lock_unlock(NAME) \ - do \ - { \ - if (pth_in_use() && !pth_mutex_release (&NAME)) \ - abort (); \ - } \ - while (0) -# define gl_recursive_lock_destroy(NAME) \ - (void)(&NAME) +# define glthread_recursive_lock_init(LOCK) \ + (pth_in_use() && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pth_in_use() && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pth_in_use() && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + ((void)(LOCK), 0) /* -------------------------- gl_once_t datatype -------------------------- */ typedef pth_once_t gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT; -# define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (pth_in_use ()) \ - { \ - void (*gl_once_temp) (void) = INITFUNCTION; \ - if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \ - abort (); \ - } \ - else \ - { \ - if (glthread_once_singlethreaded (&NAME)) \ - INITFUNCTION (); \ - } \ - } \ - while (0) -extern void glthread_once_call (void *arg); +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pth_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)); extern int glthread_once_singlethreaded (pth_once_t *once_control); # ifdef __cplusplus @@ -741,34 +531,14 @@ typedef mutex_t gl_lock_t; STORAGECLASS mutex_t NAME = gl_lock_initializer; # define gl_lock_initializer \ DEFAULTMUTEX -# define gl_lock_init(NAME) \ - do \ - { \ - if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_lock(NAME) \ - do \ - { \ - if (thread_in_use () && mutex_lock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_unlock(NAME) \ - do \ - { \ - if (thread_in_use () && mutex_unlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_lock_destroy(NAME) \ - do \ - { \ - if (thread_in_use () && mutex_destroy (&NAME) != 0) \ - abort (); \ - } \ - while (0) +# define glthread_lock_init(LOCK) \ + (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (thread_in_use () ? mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (thread_in_use () ? mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (thread_in_use () ? mutex_destroy (LOCK) : 0) /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -779,41 +549,16 @@ typedef rwlock_t gl_rwlock_t; STORAGECLASS rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ DEFAULTRWLOCK -# define gl_rwlock_init(NAME) \ - do \ - { \ - if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (thread_in_use () && rw_rdlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (thread_in_use () && rw_wrlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (thread_in_use () && rw_unlock (&NAME) != 0) \ - abort (); \ - } \ - while (0) -# define gl_rwlock_destroy(NAME) \ - do \ - { \ - if (thread_in_use () && rwlock_destroy (&NAME) != 0) \ - abort (); \ - } \ - while (0) +# define glthread_rwlock_init(LOCK) \ + (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (thread_in_use () ? rw_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (thread_in_use () ? rw_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (thread_in_use () ? rw_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (thread_in_use () ? rwlock_destroy (LOCK) : 0) /* --------------------- gl_recursive_lock_t datatype --------------------- */ @@ -833,38 +578,38 @@ typedef struct STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ { DEFAULTMUTEX, (thread_t) 0, 0 } -# define gl_recursive_lock_init(NAME) \ +# define glthread_recursive_lock_init(LOCK) \ do \ { \ if (thread_in_use ()) \ - glthread_recursive_lock_init (&NAME); \ + glthread_recursive_lock_init_multithreaded (LOCK); \ } \ while (0) -# define gl_recursive_lock_lock(NAME) \ +# define glthread_recursive_lock_lock(LOCK) \ do \ { \ if (thread_in_use ()) \ - glthread_recursive_lock_lock (&NAME); \ + glthread_recursive_lock_lock_multithreaded (LOCK); \ } \ while (0) -# define gl_recursive_lock_unlock(NAME) \ +# define glthread_recursive_lock_unlock(LOCK) \ do \ { \ if (thread_in_use ()) \ - glthread_recursive_lock_unlock (&NAME); \ + glthread_recursive_lock_unlock_multithreaded (LOCK); \ } \ while (0) -# define gl_recursive_lock_destroy(NAME) \ +# define glthread_recursive_lock_destroy(LOCK) \ do \ { \ if (thread_in_use ()) \ - glthread_recursive_lock_destroy (&NAME); \ + glthread_recursive_lock_destroy_multithreaded (LOCK); \ } \ while (0) -extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); /* -------------------------- gl_once_t datatype -------------------------- */ @@ -876,21 +621,11 @@ typedef struct gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX }; -# define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (thread_in_use ()) \ - { \ - glthread_once (&NAME, INITFUNCTION); \ - } \ - else \ - { \ - if (glthread_once_singlethreaded (&NAME)) \ - INITFUNCTION (); \ - } \ - } \ - while (0) -extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void)); +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (thread_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)); extern int glthread_once_singlethreaded (gl_once_t *once_control); # ifdef __cplusplus @@ -936,18 +671,12 @@ typedef struct STORAGECLASS gl_lock_t NAME = gl_lock_initializer; # define gl_lock_initializer \ { { 0, -1 } } -# define gl_lock_init(NAME) \ - glthread_lock_init (&NAME) -# define gl_lock_lock(NAME) \ - glthread_lock_lock (&NAME) -# define gl_lock_unlock(NAME) \ - glthread_lock_unlock (&NAME) -# define gl_lock_destroy(NAME) \ - glthread_lock_destroy (&NAME) -extern void glthread_lock_init (gl_lock_t *lock); -extern void glthread_lock_lock (gl_lock_t *lock); -extern void glthread_lock_unlock (gl_lock_t *lock); -extern void glthread_lock_destroy (gl_lock_t *lock); +# define glthread_lock_init(LOCK) \ + (glthread_lock_init_func (LOCK), 0) +extern void glthread_lock_init_func (gl_lock_t *lock); +extern int glthread_lock_lock (gl_lock_t *lock); +extern int glthread_lock_unlock (gl_lock_t *lock); +extern int glthread_lock_destroy (gl_lock_t *lock); /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -978,21 +707,13 @@ typedef struct STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ { { 0, -1 } } -# define gl_rwlock_init(NAME) \ - glthread_rwlock_init (&NAME) -# define gl_rwlock_rdlock(NAME) \ - glthread_rwlock_rdlock (&NAME) -# define gl_rwlock_wrlock(NAME) \ - glthread_rwlock_wrlock (&NAME) -# define gl_rwlock_unlock(NAME) \ - glthread_rwlock_unlock (&NAME) -# define gl_rwlock_destroy(NAME) \ - glthread_rwlock_destroy (&NAME) -extern void glthread_rwlock_init (gl_rwlock_t *lock); -extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); -extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); -extern void glthread_rwlock_unlock (gl_rwlock_t *lock); -extern void glthread_rwlock_destroy (gl_rwlock_t *lock); +# define glthread_rwlock_init(LOCK) \ + (glthread_rwlock_init_func (LOCK), 0) +extern void glthread_rwlock_init_func (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy (gl_rwlock_t *lock); /* --------------------- gl_recursive_lock_t datatype --------------------- */ @@ -1014,18 +735,12 @@ typedef struct STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ { { 0, -1 }, 0, 0 } -# define gl_recursive_lock_init(NAME) \ - glthread_recursive_lock_init (&NAME) -# define gl_recursive_lock_lock(NAME) \ - glthread_recursive_lock_lock (&NAME) -# define gl_recursive_lock_unlock(NAME) \ - glthread_recursive_lock_unlock (&NAME) -# define gl_recursive_lock_destroy(NAME) \ - glthread_recursive_lock_destroy (&NAME) -extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); -extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); +# define glthread_recursive_lock_init(LOCK) \ + (glthread_recursive_lock_init_func (LOCK), 0) +extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); /* -------------------------- gl_once_t datatype -------------------------- */ @@ -1038,9 +753,9 @@ typedef struct gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ STORAGECLASS gl_once_t NAME = { -1, -1 }; -# define gl_once(NAME, INITFUNCTION) \ - glthread_once (&NAME, INITFUNCTION) -extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void)); +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) +extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)); # ifdef __cplusplus } @@ -1059,50 +774,156 @@ extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void)) typedef int gl_lock_t; # define gl_lock_define(STORAGECLASS, NAME) # define gl_lock_define_initialized(STORAGECLASS, NAME) -# define gl_lock_init(NAME) -# define gl_lock_lock(NAME) -# define gl_lock_unlock(NAME) -# define gl_lock_destroy(NAME) +# define glthread_lock_init(NAME) 0 +# define glthread_lock_lock(NAME) 0 +# define glthread_lock_unlock(NAME) 0 +# define glthread_lock_destroy(NAME) 0 /* ------------------------- gl_rwlock_t datatype ------------------------- */ typedef int gl_rwlock_t; # define gl_rwlock_define(STORAGECLASS, NAME) # define gl_rwlock_define_initialized(STORAGECLASS, NAME) -# define gl_rwlock_init(NAME) -# define gl_rwlock_rdlock(NAME) -# define gl_rwlock_wrlock(NAME) -# define gl_rwlock_unlock(NAME) -# define gl_rwlock_destroy(NAME) +# define glthread_rwlock_init(NAME) 0 +# define glthread_rwlock_rdlock(NAME) 0 +# define glthread_rwlock_wrlock(NAME) 0 +# define glthread_rwlock_unlock(NAME) 0 +# define glthread_rwlock_destroy(NAME) 0 /* --------------------- gl_recursive_lock_t datatype --------------------- */ typedef int gl_recursive_lock_t; # define gl_recursive_lock_define(STORAGECLASS, NAME) # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) -# define gl_recursive_lock_init(NAME) -# define gl_recursive_lock_lock(NAME) -# define gl_recursive_lock_unlock(NAME) -# define gl_recursive_lock_destroy(NAME) +# define glthread_recursive_lock_init(NAME) 0 +# define glthread_recursive_lock_lock(NAME) 0 +# define glthread_recursive_lock_unlock(NAME) 0 +# define glthread_recursive_lock_destroy(NAME) 0 /* -------------------------- gl_once_t datatype -------------------------- */ typedef int gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ STORAGECLASS gl_once_t NAME = 0; -# define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (NAME == 0) \ - { \ - NAME = ~ 0; \ - INITFUNCTION (); \ - } \ - } \ - while (0) +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) #endif /* ========================================================================= */ +/* Macros with built-in error handling. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +#define gl_lock_init(NAME) \ + do \ + { \ + if (glthread_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_lock(NAME) \ + do \ + { \ + if (glthread_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_unlock(NAME) \ + do \ + { \ + if (glthread_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_destroy(NAME) \ + do \ + { \ + if (glthread_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +#define gl_rwlock_init(NAME) \ + do \ + { \ + if (glthread_rwlock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (glthread_rwlock_rdlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (glthread_rwlock_wrlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (glthread_rwlock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (glthread_rwlock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +#define gl_recursive_lock_init(NAME) \ + do \ + { \ + if (glthread_recursive_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (glthread_recursive_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +#define gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (glthread_once (&NAME, INITFUNCTION)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + #endif /* _LOCK_H */ diff --git a/lib/tls.c b/lib/tls.c index f85ce033fc..e857f611b1 100644 --- a/lib/tls.c +++ b/lib/tls.c @@ -1,5 +1,5 @@ /* Thread-local storage in multithreaded situations. - Copyright (C) 2005-2007 Free Software Foundation, Inc. + Copyright (C) 2005-2008 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,7 +41,7 @@ /* ------------------------- gl_tls_key_t datatype ------------------------- */ void * -glthread_tls_get (thread_key_t key) +glthread_tls_get_multithreaded (thread_key_t key) { void *value; diff --git a/lib/tls.h b/lib/tls.h index 9b195063d1..9a03336937 100644 --- a/lib/tls.h +++ b/lib/tls.h @@ -20,11 +20,15 @@ thread library. It does not contain primitives for creating threads or for other multithreading primitives. - Type: gl_tls_key_t - Initialization: gl_tls_key_init (name, destructor); - Getting per-thread value: gl_tls_get (name) - Setting per-thread value: gl_tls_set (name, pointer); - De-initialization: gl_tls_key_destroy (name); + Type: gl_tls_key_t + Initialization: gl_tls_key_init (name, destructor); + Getting per-thread value: gl_tls_get (name) + Setting per-thread value: gl_tls_set (name, pointer); + De-initialization: gl_tls_key_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_tls_key_init (&name, destructor); + Setting per-thread value: err = glthread_tls_set (&name, pointer); + De-initialization: err = glthread_tls_key_destroy (&name); A per-thread value is of type 'void *'. @@ -39,6 +43,8 @@ #ifndef _TLS_H #define _TLS_H +#include + /* ========================================================================= */ #if USE_POSIX_THREADS @@ -90,41 +96,20 @@ typedef union pthread_key_t key; } gl_tls_key_t; -# define gl_tls_key_init(NAME, DESTRUCTOR) \ - do \ - { \ - if (pthread_in_use ()) \ - { \ - if (pthread_key_create (&(NAME).key, DESTRUCTOR) != 0) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = NULL; \ - } \ - while (0) +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (pthread_in_use () \ + ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \ + : ((KEY)->singlethread_value = NULL, 0)) # define gl_tls_get(NAME) \ (pthread_in_use () \ ? pthread_getspecific ((NAME).key) \ : (NAME).singlethread_value) -# define gl_tls_set(NAME, POINTER) \ - do \ - { \ - if (pthread_in_use ()) \ - { \ - if (pthread_setspecific ((NAME).key, (POINTER)) != 0) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = (POINTER); \ - } \ - while (0) -# define gl_tls_key_destroy(NAME) \ - do \ - { \ - if (pthread_in_use () && pthread_key_delete ((NAME).key) != 0) \ - abort (); \ - } \ - while (0) +# define glthread_tls_set(KEY, POINTER) \ + (pthread_in_use () \ + ? pthread_setspecific ((KEY)->key, (POINTER)) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ + (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0) #endif @@ -163,41 +148,22 @@ typedef union pth_key_t key; } gl_tls_key_t; -# define gl_tls_key_init(NAME, DESTRUCTOR) \ - do \ - { \ - if (pth_in_use ()) \ - { \ - if (!pth_key_create (&(NAME).key, DESTRUCTOR)) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = NULL; \ - } \ - while (0) +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (pth_in_use () \ + ? (!pth_key_create (&(KEY)->key, DESTRUCTOR) ? errno : 0) \ + : ((KEY)->singlethread_value = NULL, 0)) # define gl_tls_get(NAME) \ (pth_in_use () \ ? pth_key_getdata ((NAME).key) \ : (NAME).singlethread_value) -# define gl_tls_set(NAME, POINTER) \ - do \ - { \ - if (pth_in_use ()) \ - { \ - if (!pth_key_setdata ((NAME).key, (POINTER))) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = (POINTER); \ - } \ - while (0) -# define gl_tls_key_destroy(NAME) \ - do \ - { \ - if (pth_in_use () && !pth_key_delete ((NAME).key)) \ - abort (); \ - } \ - while (0) +# define glthread_tls_set(KEY, POINTER) \ + (pth_in_use () \ + ? (!pth_key_setdata ((KEY)->key, (POINTER)) ? errno : 0) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ + (pth_in_use () \ + ? (!pth_key_delete ((KEY)->key) ? errno : 0) \ + : 0) #endif @@ -235,38 +201,22 @@ typedef union thread_key_t key; } gl_tls_key_t; -# define gl_tls_key_init(NAME, DESTRUCTOR) \ - do \ - { \ - if (thread_in_use ()) \ - { \ - if (thr_keycreate (&(NAME).key, DESTRUCTOR) != 0) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = NULL; \ - } \ - while (0) +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (thread_in_use () \ + ? thr_keycreate (&(KEY)->key, DESTRUCTOR) \ + : ((KEY)->singlethread_value = NULL, 0)) # define gl_tls_get(NAME) \ (thread_in_use () \ - ? glthread_tls_get ((NAME).key) \ + ? glthread_tls_get_multithreaded ((NAME).key) \ : (NAME).singlethread_value) -extern void *glthread_tls_get (thread_key_t key); -# define gl_tls_set(NAME, POINTER) \ - do \ - { \ - if (thread_in_use ()) \ - { \ - if (thr_setspecific ((NAME).key, (POINTER)) != 0) \ - abort (); \ - } \ - else \ - (NAME).singlethread_value = (POINTER); \ - } \ - while (0) -# define gl_tls_key_destroy(NAME) \ +extern void *glthread_tls_get_multithreaded (thread_key_t key); +# define glthread_tls_set(KEY, POINTER) \ + (thread_in_use () \ + ? thr_setspecific ((KEY)->key, (POINTER)) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ /* Unsupported. */ \ - (void)0 + 0 #endif @@ -279,31 +229,15 @@ extern void *glthread_tls_get (thread_key_t key); /* ------------------------- gl_tls_key_t datatype ------------------------- */ typedef DWORD gl_tls_key_t; -# define gl_tls_key_init(NAME, DESTRUCTOR) \ +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ /* The destructor is unsupported. */ \ - do \ - { \ - if (((NAME) = TlsAlloc ()) == (DWORD)-1) \ - abort (); \ - (void) (DESTRUCTOR); \ - } \ - while (0) + ((*(KEY) = TlsAlloc ()) == (DWORD)-1 ? EAGAIN : ((void) (DESTRUCTOR), 0)) # define gl_tls_get(NAME) \ TlsGetValue (NAME) -# define gl_tls_set(NAME, POINTER) \ - do \ - { \ - if (!TlsSetValue (NAME, POINTER)) \ - abort (); \ - } \ - while (0) -# define gl_tls_key_destroy(NAME) \ - do \ - { \ - if (!TlsFree (NAME)) \ - abort (); \ - } \ - while (0) +# define glthread_tls_set(KEY, POINTER) \ + (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0) +# define glthread_tls_key_destroy(KEY) \ + (!TlsFree (*(KEY)) ? EINVAL : 0) #endif @@ -320,18 +254,47 @@ typedef struct void *singlethread_value; } gl_tls_key_t; -# define gl_tls_key_init(NAME, DESTRUCTOR) \ - ((NAME).singlethread_value = NULL, \ - (void) (DESTRUCTOR)) +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + ((KEY)->singlethread_value = NULL, \ + (void) (DESTRUCTOR), \ + 0) # define gl_tls_get(NAME) \ (NAME).singlethread_value -# define gl_tls_set(NAME, POINTER) \ - (NAME).singlethread_value = (POINTER) -# define gl_tls_key_destroy(NAME) \ - (void)0 +# define glthread_tls_set(KEY, POINTER) \ + ((KEY)->singlethread_value = (POINTER), 0) +# define glthread_tls_key_destroy(KEY) \ + 0 #endif /* ========================================================================= */ +/* Macros with built-in error handling. */ + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +#define gl_tls_key_init(NAME, DESTRUCTOR) \ + do \ + { \ + if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \ + abort (); \ + } \ + while (0) +#define gl_tls_set(NAME, POINTER) \ + do \ + { \ + if (glthread_tls_set (&NAME, POINTER)) \ + abort (); \ + } \ + while (0) +#define gl_tls_key_destroy(NAME) \ + do \ + { \ + if (glthread_tls_key_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + #endif /* _TLS_H */ -- 2.30.2