[svn-r2276] Modifed thread-safety code to more closely align with rest of HDF5 coding

standards.
This commit is contained in:
Quincey Koziol 2000-05-19 09:51:50 -05:00
parent c0d424e947
commit d894ed6d0d
6 changed files with 186 additions and 126 deletions

View File

@ -43,14 +43,9 @@ FILE *fdopen(int fd, const char *mode);
/* statically initialize block for pthread_once call used in initializing */
/* the first global mutex */
#ifdef H5_HAVE_THREADSAFE
pthread_once_t H5_first_init_g = PTHREAD_ONCE_INIT;
pthread_key_t H5_errstk_key_g;
pthread_key_t H5_cancel_key_g;
hbool_t H5_allow_concurrent_g = FALSE; /* concurrent APIs override this */
H5_api_t H5_g;
#else
hbool_t H5_libinit_g = FALSE;
hbool_t H5_libinit_g = FALSE;
#endif
hbool_t dont_atexit_g = FALSE;
@ -164,9 +159,9 @@ H5_term_library(void)
#ifdef H5_HAVE_THREADSAFE
/* explicit locking of the API */
pthread_once(&H5_first_init_g, H5_first_thread_init);
pthread_once(&H5TS_first_init_g, H5TS_first_thread_init);
H5_mutex_lock(&H5_g.init_lock);
H5TS_mutex_lock(&H5_g.init_lock);
if (!H5_g.H5_libinit_g) return;
#else
@ -217,7 +212,7 @@ H5_term_library(void)
#ifdef H5_HAVE_THREADSAFE
H5_g.H5_libinit_g = FALSE;
H5_mutex_unlock(&H5_g.init_lock);
H5TS_mutex_unlock(&H5_g.init_lock);
#else
H5_libinit_g = FALSE;
#endif
@ -256,16 +251,16 @@ H5dont_atexit(void)
/* locking code explicitly since FUNC_ENTER is not called */
#ifdef H5_HAVE_THREADSAFE
pthread_once(&H5_first_init_g, H5_first_thread_init);
pthread_once(&H5TS_first_init_g, H5TS_first_thread_init);
H5_mutex_lock(&H5_g.init_lock);
H5TS_mutex_lock(&H5_g.init_lock);
#endif
H5_trace(FALSE, "H5dont_atexit", "");
if (dont_atexit_g) return FAIL;
dont_atexit_g = TRUE;
H5_trace(TRUE, NULL, "e", SUCCEED);
#ifdef H5_HAVE_THREADSAFE
H5_mutex_unlock(&H5_g.init_lock);
H5TS_mutex_unlock(&H5_g.init_lock);
#endif
return(SUCCEED);
}
@ -521,13 +516,13 @@ H5close (void)
*/
/* Explicitly lock the call since FUNC_ENTER is not called */
#ifdef H5_HAVE_THREADSAFE
pthread_once(&H5_first_init_g, H5_first_thread_init);
pthread_once(&H5TS_first_init_g, H5TS_first_thread_init);
H5_mutex_lock(&H5_g.init_lock);
H5TS_mutex_lock(&H5_g.init_lock);
#endif
H5_term_library();
#ifdef H5_HAVE_THREADSAFE
H5_mutex_unlock(&H5_g.init_lock);
H5TS_mutex_unlock(&H5_g.init_lock);
#endif
return SUCCEED;
}

View File

@ -197,12 +197,12 @@ void *H5E_auto_data_g = NULL;
H5E_t *H5E_get_stack() {
H5E_t *estack;
if (estack = pthread_getspecific(H5_errstk_key_g)) {
if ((estack = pthread_getspecific(H5TS_errstk_key_g))!=NULL) {
return estack;
} else {
/* no associated value with current thread - create one */
estack = (H5E_t *)malloc(sizeof(H5E_t));
pthread_setspecific(H5_errstk_key_g, (void *)estack);
pthread_setspecific(H5TS_errstk_key_g, (void *)estack);
return estack;
}
}
@ -359,7 +359,7 @@ H5Eprint(FILE *stream)
if (!stream) stream = stderr;
#ifdef H5_HAVE_THREADSAFE
fprintf (stream, "HDF5-DIAG: Error detected in thread %d."
,pthread_self());
,(int)pthread_self());
#else
fprintf (stream, "HDF5-DIAG: Error detected in thread 0.");
#endif

View File

@ -22,11 +22,30 @@ static char RcsId[] = "@(#)$Revision$";
#ifdef H5_HAVE_THREADSAFE
/* Module specific data structures */
/* cancelability structure */
typedef struct H5TS_cancel_struct {
int previous_state;
unsigned int cancel_count;
} H5TS_cancel_t;
/* Global variable definitions */
pthread_once_t H5TS_first_init_g = PTHREAD_ONCE_INIT;
pthread_key_t H5TS_errstk_key_g;
pthread_key_t H5TS_cancel_key_g;
hbool_t H5TS_allow_concurrent_g = FALSE; /* concurrent APIs override this */
/* Local function definitions */
#ifdef NOT_USED
static void H5TS_mutex_init(H5TS_mutex_t *mutex);
#endif /* NOT_USED */
/*--------------------------------------------------------------------------
* NAME
* H5_first_thread_init
* H5TS_first_thread_init
* USAGE
* H5_first_thread_init()
* H5TS_first_thread_init()
*
* RETURNS
*
@ -42,26 +61,29 @@ static char RcsId[] = "@(#)$Revision$";
*
*--------------------------------------------------------------------------
*/
void H5_first_thread_init() {
/* initialize global API mutex lock */
H5_g.H5_libinit_g = FALSE;
H5_g.init_lock.owner_thread = NULL;
pthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL);
pthread_cond_init(&H5_g.init_lock.cond_var, NULL);
H5_g.init_lock.lock_count = 0;
void
H5TS_first_thread_init(void)
{
/* initialize global API mutex lock */
H5_g.H5_libinit_g = FALSE;
H5_g.init_lock.owner_thread = NULL;
pthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL);
pthread_cond_init(&H5_g.init_lock.cond_var, NULL);
H5_g.init_lock.lock_count = 0;
/* initialize key for thread-specific error stacks */
pthread_key_create(&H5_errstk_key_g, NULL);
/* initialize key for thread-specific error stacks */
pthread_key_create(&H5TS_errstk_key_g, NULL);
/* initialize key for thread cancellability mechanism */
pthread_key_create(&H5_cancel_key_g, NULL);
/* initialize key for thread cancellability mechanism */
pthread_key_create(&H5TS_cancel_key_g, NULL);
}
#ifdef NOT_USED
/*--------------------------------------------------------------------------
* NAME
* H5_mutex_init
* H5TS_mutex_init
* USAGE
* H5_mutex_init(&mutex_var)
* H5TS_mutex_init(&mutex_var)
*
* RETURNS
*
@ -77,18 +99,21 @@ void H5_first_thread_init() {
*
*--------------------------------------------------------------------------
*/
void H5_mutex_init(H5_mutex_t *H5_mutex) {
(*H5_mutex).owner_thread = NULL;
pthread_mutex_init(&(*H5_mutex).atomic_lock, NULL);
pthread_cond_init(&(*H5_mutex).cond_var, NULL);
(*H5_mutex).lock_count = 0;
static void
H5TS_mutex_init(H5TS_mutex_t *mutex)
{
(*mutex).owner_thread = NULL;
pthread_mutex_init(&(*mutex).atomic_lock, NULL);
pthread_cond_init(&(*mutex).cond_var, NULL);
(*mutex).lock_count = 0;
}
#endif /* NOT_USED */
/*--------------------------------------------------------------------------
* NAME
* H5_mutex_lock
* H5TS_mutex_lock
* USAGE
* H5_mutex_lock(&mutex_var)
* H5TS_mutex_lock(&mutex_var)
*
* RETURNS
*
@ -104,36 +129,38 @@ void H5_mutex_init(H5_mutex_t *H5_mutex) {
*
*--------------------------------------------------------------------------
*/
void H5_mutex_lock(H5_mutex_t *H5_mutex) {
pthread_mutex_lock(&(*H5_mutex).atomic_lock);
if (pthread_equal(pthread_self(), (*H5_mutex).owner_thread)) {
/* already owned by self - increment count */
(*H5_mutex).lock_count++;
} else {
if ((*H5_mutex).owner_thread == NULL) {
/* no one else has locked it - set owner and grab lock */
(*H5_mutex).owner_thread = pthread_self();
(*H5_mutex).lock_count = 1;
void
H5TS_mutex_lock(H5TS_mutex_t *mutex)
{
pthread_mutex_lock(&(*mutex).atomic_lock);
if (pthread_equal(pthread_self(), (*mutex).owner_thread)) {
/* already owned by self - increment count */
(*mutex).lock_count++;
} else {
/* if already locked by someone else */
while (1) {
pthread_cond_wait(&(*H5_mutex).cond_var, &(*H5_mutex).atomic_lock);
if ((*H5_mutex).owner_thread == NULL) {
(*H5_mutex).owner_thread = pthread_self();
(*H5_mutex).lock_count = 1;
break;
} /* else do nothing and loop back to wait on condition*/
}
if ((*mutex).owner_thread == NULL) {
/* no one else has locked it - set owner and grab lock */
(*mutex).owner_thread = pthread_self();
(*mutex).lock_count = 1;
} else {
/* if already locked by someone else */
while (1) {
pthread_cond_wait(&(*mutex).cond_var, &(*mutex).atomic_lock);
if ((*mutex).owner_thread == NULL) {
(*mutex).owner_thread = pthread_self();
(*mutex).lock_count = 1;
break;
} /* else do nothing and loop back to wait on condition*/
}
}
}
}
pthread_mutex_unlock(&(*H5_mutex).atomic_lock);
pthread_mutex_unlock(&(*mutex).atomic_lock);
}
/*--------------------------------------------------------------------------
* NAME
* H5_mutex_unlock
* H5TS_mutex_unlock
* USAGE
* H5_mutex_unlock(&mutex_var)
* H5TS_mutex_unlock(&mutex_var)
*
* RETURNS
*
@ -149,21 +176,23 @@ void H5_mutex_lock(H5_mutex_t *H5_mutex) {
*
*--------------------------------------------------------------------------
*/
void H5_mutex_unlock(H5_mutex_t *H5_mutex) {
pthread_mutex_lock(&(*H5_mutex).atomic_lock);
(*H5_mutex).lock_count--;
if ((*H5_mutex).lock_count == 0) {
(*H5_mutex).owner_thread = NULL;
pthread_cond_signal(&(*H5_mutex).cond_var);
}
pthread_mutex_unlock(&(*H5_mutex).atomic_lock);
void
H5TS_mutex_unlock(H5TS_mutex_t *mutex)
{
pthread_mutex_lock(&(*mutex).atomic_lock);
(*mutex).lock_count--;
if ((*mutex).lock_count == 0) {
(*mutex).owner_thread = NULL;
pthread_cond_signal(&(*mutex).cond_var);
}
pthread_mutex_unlock(&(*mutex).atomic_lock);
}
/*--------------------------------------------------------------------------
* NAME
* H5_cancel_count_inc
* H5TS_cancel_count_inc
* USAGE
* H5_cancel_count_inc()
* H5TS_cancel_count_inc()
*
* RETURNS
*
@ -184,34 +213,33 @@ void H5_mutex_unlock(H5_mutex_t *H5_mutex) {
*--------------------------------------------------------------------------
*/
void
H5_cancel_count_inc(void)
H5TS_cancel_count_inc(void)
{
H5_cancel_t *cancel_counter;
H5TS_cancel_t *cancel_counter;
if (cancel_counter = pthread_getspecific(H5_cancel_key_g)) {
/* do nothing here */
} else {
/* first time thread calls library - create new counter and associate
with key
*/
cancel_counter = (H5_cancel_t *)malloc(sizeof(H5_cancel_t));
cancel_counter->cancel_count = 0;
pthread_setspecific(H5_cancel_key_g, (void *)cancel_counter);
}
if ((cancel_counter = pthread_getspecific(H5TS_cancel_key_g))!=NULL) {
/* do nothing here */
} else {
/* first time thread calls library - create new counter and associate
* with key
*/
cancel_counter = (H5TS_cancel_t *)malloc(sizeof(H5TS_cancel_t));
cancel_counter->cancel_count = 0;
pthread_setspecific(H5TS_cancel_key_g, (void *)cancel_counter);
}
if (cancel_counter->cancel_count == 0) {
/* thread entering library */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
&(cancel_counter->previous_state));
}
cancel_counter->cancel_count++;
if (cancel_counter->cancel_count == 0) {
/* thread entering library */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &(cancel_counter->previous_state));
}
cancel_counter->cancel_count++;
}
/*--------------------------------------------------------------------------
* NAME
* H5_cancel_count_dec
* H5TS_cancel_count_dec
* USAGE
* H5_cancel_count_dec()
* H5TS_cancel_count_dec()
*
* RETURNS
*
@ -230,14 +258,14 @@ H5_cancel_count_inc(void)
*--------------------------------------------------------------------------
*/
void
H5_cancel_count_dec(void)
H5TS_cancel_count_dec(void)
{
H5_cancel_t *cancel_counter = pthread_getspecific(H5_cancel_key_g);
H5TS_cancel_t *cancel_counter = pthread_getspecific(H5TS_cancel_key_g);
if (cancel_counter->cancel_count == 1) {
pthread_setcancelstate(cancel_counter->previous_state, NULL);
}
cancel_counter->cancel_count--;
if (cancel_counter->cancel_count == 1) {
pthread_setcancelstate(cancel_counter->previous_state, NULL);
}
cancel_counter->cancel_count--;
}
#endif

54
src/H5TSprivate.h Normal file
View File

@ -0,0 +1,54 @@
/*-------------------------------------------------------------------------
* Copyright (C) 2000 National Center for Supercomputing Applications.
* All rights reserved.
*
*-------------------------------------------------------------------------
*
* Created: H5TSprivate.h
* May 2 2000
* Chee Wai LEE
*
* Purpose: Private non-prototype header.
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
#ifndef _H5TSprivate_H
#define _H5TSprivate_H
/* Public headers needed by this file */
#ifdef LATER
#include <H5TSpublic.h> /*Public API prototypes */
#endif /* LATER */
/* Library level data structures */
typedef struct H5TS_mutex_struct {
pthread_t owner_thread; /* current lock owner */
pthread_mutex_t atomic_lock; /* lock for atomicity of new mechanism */
pthread_cond_t cond_var; /* condition variable */
unsigned int lock_count;
} H5TS_mutex_t;
/* Extern global variables */
extern pthread_once_t H5TS_first_init_g;
extern pthread_key_t H5TS_errstk_key_g;
#if defined c_plusplus || defined __cplusplus
extern "C"
{
#endif /* c_plusplus || __cplusplus */
__DLL__ void H5TS_first_thread_init(void);
__DLL__ void H5TS_mutex_lock(H5TS_mutex_t *mutex);
__DLL__ void H5TS_mutex_unlock(H5TS_mutex_t *mutex);
__DLL__ void H5TS_cancel_count_inc(void);
__DLL__ void H5TS_cancel_count_dec(void);
#if defined c_plusplus || defined __cplusplus
}
#endif /* c_plusplus || __cplusplus */
#endif /* _H5TSprivate_H */

View File

@ -879,61 +879,44 @@ __DLL__ void H5_trace(hbool_t returning, const char *func, const char *type,
/* Lock headers */
#ifdef H5_HAVE_THREADSAFE
typedef struct H5_mutex_struct {
pthread_t owner_thread; /* current lock owner */
pthread_mutex_t atomic_lock; /* lock for atomicity of new mechanism */
pthread_cond_t cond_var; /* condition variable */
unsigned int lock_count;
} H5_mutex_t;
/* cancelability structure */
typedef struct H5_cancel_struct {
int previous_state;
unsigned int cancel_count;
} H5_cancel_t;
/* Include required thread-safety header */
#include <H5TSprivate.h>
/* replacement structure for original global variable */
typedef struct H5_api_struct {
H5_mutex_t init_lock; /* API entrance mutex */
H5TS_mutex_t init_lock; /* API entrance mutex */
hbool_t H5_libinit_g;
} H5_api_t;
/* Macro for first thread initialization */
#define H5_FIRST_THREAD_INIT \
pthread_once(&H5_first_init_g, H5_first_thread_init);
pthread_once(&H5TS_first_init_g, H5TS_first_thread_init);
/* Macros for threadsafe HDF-5 Phase I locks */
#define H5_INIT_GLOBAL H5_g.H5_libinit_g
#define H5_API_LOCK_BEGIN \
if (H5_IS_API(FUNC)) { \
H5_mutex_lock(&H5_g.init_lock);
H5TS_mutex_lock(&H5_g.init_lock);
#define H5_API_LOCK_END }
#define H5_API_UNLOCK_BEGIN \
if (H5_IS_API(FUNC)) { \
H5_mutex_unlock(&H5_g.init_lock);
H5TS_mutex_unlock(&H5_g.init_lock);
#define H5_API_UNLOCK_END }
/* Macros for thread cancellation-safe mechanism */
#define H5_API_UNSET_CANCEL \
if (H5_IS_API(FUNC)) { \
H5_cancel_count_inc(); \
H5TS_cancel_count_inc(); \
}
#define H5_API_SET_CANCEL \
if (H5_IS_API(FUNC)) { \
H5_cancel_count_dec(); \
H5TS_cancel_count_dec(); \
}
/* Extern global variables */
extern pthread_once_t H5_first_init_g;
extern pthread_key_t H5_errstk_key_g;
extern pthread_key_t H5_cancel_key_g;
extern hbool_t H5_allow_concurrent_g;
extern H5_api_t H5_g;
void H5_first_thread_init(void);
#else
/* disable any first thread init mechanism */

View File

@ -49,8 +49,8 @@ PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \
H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h H5FLprivate.h \
H5Gprivate.h H5Gpkg.h H5HGprivate.h H5HLprivate.h H5Iprivate.h \
H5MFprivate.h H5MMprivate.h H5Oprivate.h H5Pprivate.h H5Rprivate.h \
H5RAprivate.h H5Sprivate.h H5Tprivate.h H5TBprivate.h H5Tpkg.h \
H5Vprivate.h H5Zprivate.h H5config.h
H5RAprivate.h H5Sprivate.h H5Tprivate.h H5TBprivate.h H5Tpkg.h
H5TSprivate.h H5Vprivate.h H5Zprivate.h H5config.h
## Number format detection
## The LD_LIBRARY_PATH setting is a klutch.