mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-04-12 17:31:09 +08:00
[svn-r2286] Gave the threading functions return types (herr_t). pthreads' calls
return 0 on success and non-zero on failure. That's what happens with these calls. There was a problem compiling threading on Linux. The pthread_t type is not consistent among different implementations, so it cannot simply be assigned to NULL or tested against it. I initialize it by calling HDmemset(foo_thread, 0, sizeof(pthread_t)). To see if it's a "null" pthread, I created a special pthread_t object (assigned to only in the init phase and then only read...i.e., thread safe) and assigned it "null" as above. Then I use pthread_equal() to determine if the thread is null.
This commit is contained in:
parent
fb75b8a89c
commit
b97c63cdbc
230
src/H5TS.c
230
src/H5TS.c
@ -1,14 +1,14 @@
|
||||
/****************************************************************************
|
||||
* NCSA HDF *
|
||||
* Software Development Group *
|
||||
* National Center for Supercomputing Applications *
|
||||
* University of Illinois at Urbana-Champaign *
|
||||
* 605 E. Springfield, Champaign IL 61820 *
|
||||
* *
|
||||
* For conditions of distribution and use, see the accompanying *
|
||||
* hdf/COPYING file. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
* NCSA HDF *
|
||||
* Software Development Group *
|
||||
* National Center for Supercomputing Applications *
|
||||
* University of Illinois at Urbana-Champaign *
|
||||
* 605 E. Springfield, Champaign IL 61820 *
|
||||
* *
|
||||
* For conditions of distribution and use, see the accompanying *
|
||||
* hdf/COPYING file. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef RCSID
|
||||
static char RcsId[] = "@(#)$Revision$";
|
||||
@ -17,8 +17,9 @@ static char RcsId[] = "@(#)$Revision$";
|
||||
/* $Id$ */
|
||||
|
||||
/* private headers */
|
||||
#include <H5private.h> /*library */
|
||||
#include <H5Eprivate.h> /*error handling */
|
||||
#include <H5private.h> /*library */
|
||||
#include <H5Eprivate.h> /*error handling */
|
||||
#include <H5MMprivate.h> /*memory management functions */
|
||||
|
||||
#ifdef H5_HAVE_THREADSAFE
|
||||
|
||||
@ -26,8 +27,8 @@ static char RcsId[] = "@(#)$Revision$";
|
||||
|
||||
/* cancelability structure */
|
||||
typedef struct H5TS_cancel_struct {
|
||||
int previous_state;
|
||||
unsigned int cancel_count;
|
||||
int previous_state;
|
||||
unsigned int cancel_count;
|
||||
} H5TS_cancel_t;
|
||||
|
||||
/* Global variable definitions */
|
||||
@ -36,6 +37,9 @@ 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 variable declarations */
|
||||
static pthread_t H5TS_null_g; /* Set to ``null'' with HDmemset for comparing*/
|
||||
|
||||
/* Local function definitions */
|
||||
#ifdef NOT_USED
|
||||
static void H5TS_mutex_init(H5TS_mutex_t *mutex);
|
||||
@ -44,15 +48,16 @@ static void H5TS_mutex_init(H5TS_mutex_t *mutex);
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_first_thread_init
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_first_thread_init()
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initialization of global API lock, keys for per-thread error stacks
|
||||
* and cancallability information. Called by the first thread that enters
|
||||
* the library.
|
||||
* Initialization of global API lock, keys for per-thread error stacks and
|
||||
* cancallability information. Called by the first thread that enters the
|
||||
* library.
|
||||
*
|
||||
* PROGRAMMER: Chee Wai LEE
|
||||
* May 2, 2000
|
||||
@ -64,17 +69,21 @@ static void H5TS_mutex_init(H5TS_mutex_t *mutex);
|
||||
void
|
||||
H5TS_first_thread_init(void)
|
||||
{
|
||||
/* initialize global API mutex lock */
|
||||
H5_g.H5_libinit_g = FALSE;
|
||||
H5_g.init_lock.owner_thread = NULL;
|
||||
|
||||
/* set the two pthread_t objects to ``null'' */
|
||||
HDmemset(&H5_g.init_lock.owner_thread, 0, sizeof(pthread_t));
|
||||
HDmemset(&H5TS_null_g, 0, sizeof(pthread_t));
|
||||
|
||||
/* initialize global API mutex lock */
|
||||
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 */
|
||||
/* initialize key for thread-specific error stacks */
|
||||
pthread_key_create(&H5TS_errstk_key_g, NULL);
|
||||
|
||||
/* initialize key for thread cancellability mechanism */
|
||||
/* initialize key for thread cancellability mechanism */
|
||||
pthread_key_create(&H5TS_cancel_key_g, NULL);
|
||||
}
|
||||
|
||||
@ -82,119 +91,155 @@ H5TS_first_thread_init(void)
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_mutex_init
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_mutex_init(&mutex_var)
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Recursive lock semantics for HDF5 (lock initialization) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
* Recursive lock semantics for HDF5 (lock initialization) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
*
|
||||
* PROGRAMMER: Chee Wai LEE
|
||||
* May 2, 2000
|
||||
*
|
||||
* MODIFICATIONS:
|
||||
*
|
||||
* 19 May 2000, Bill Wendling
|
||||
* Changed (*foo). form of accessing structure members to the -> form.
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
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;
|
||||
HDmemset(&H5_g.init_lock.owner_thread, 0, sizeof(pthread_t));
|
||||
pthread_mutex_init(&mutex->atomic_lock, NULL);
|
||||
pthread_cond_init(&mutex->cond_var, NULL);
|
||||
mutex->lock_count = 0;
|
||||
}
|
||||
#endif /* NOT_USED */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_mutex_lock
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_mutex_lock(&mutex_var)
|
||||
*
|
||||
* RETURNS
|
||||
* 0 on success and non-zero on error.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Recursive lock semantics for HDF5 (locking) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
* Recursive lock semantics for HDF5 (locking) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
*
|
||||
* PROGRAMMER: Chee Wai LEE
|
||||
* May 2, 2000
|
||||
*
|
||||
* MODIFICATIONS:
|
||||
*
|
||||
* 19 May 2000, Bill Wendling
|
||||
* Changed (*foo). form of accessing structure members to the -> form.
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
herr_t
|
||||
H5TS_mutex_lock(H5TS_mutex_t *mutex)
|
||||
{
|
||||
pthread_mutex_lock(&(*mutex).atomic_lock);
|
||||
if (pthread_equal(pthread_self(), (*mutex).owner_thread)) {
|
||||
herr_t ret_value;
|
||||
|
||||
ret_value = pthread_mutex_lock(&mutex->atomic_lock);
|
||||
|
||||
if (ret_value)
|
||||
return ret_value;
|
||||
|
||||
if (pthread_equal(pthread_self(), mutex->owner_thread)) {
|
||||
/* already owned by self - increment count */
|
||||
(*mutex).lock_count++;
|
||||
mutex->lock_count++;
|
||||
} else if (pthread_equal(mutex->owner_thread, H5TS_null_g)) {
|
||||
/* no one else has locked it - set owner and grab lock */
|
||||
mutex->owner_thread = pthread_self();
|
||||
mutex->lock_count = 1;
|
||||
} else {
|
||||
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*/
|
||||
}
|
||||
/* if already locked by someone else */
|
||||
for (;;) {
|
||||
pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock);
|
||||
|
||||
if (pthread_equal(mutex->owner_thread, H5TS_null_g)) {
|
||||
mutex->owner_thread = pthread_self();
|
||||
mutex->lock_count = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&(*mutex).atomic_lock);
|
||||
|
||||
return pthread_mutex_unlock(&mutex->atomic_lock);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_mutex_unlock
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_mutex_unlock(&mutex_var)
|
||||
*
|
||||
* RETURNS
|
||||
* 0 on success and non-zero on error.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Recursive lock semantics for HDF5 (unlocking) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
* Recursive lock semantics for HDF5 (unlocking) -
|
||||
* Multiple acquisition of a lock by a thread is permitted with a
|
||||
* corresponding unlock operation required.
|
||||
*
|
||||
* PROGRAMMER: Chee Wai LEE
|
||||
* May 2, 2000
|
||||
*
|
||||
* MODIFICATIONS:
|
||||
*
|
||||
* 19 May 2000, Bill Wendling
|
||||
* Changed (*foo). form of accessing structure members to the -> form.
|
||||
* Also gave the function a return value.
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
herr_t
|
||||
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);
|
||||
herr_t ret_value;
|
||||
|
||||
ret_value = pthread_mutex_lock(&mutex->atomic_lock);
|
||||
|
||||
if (ret_value)
|
||||
return ret_value;
|
||||
|
||||
mutex->lock_count--;
|
||||
|
||||
if (mutex->lock_count == 0) {
|
||||
HDmemset(&mutex->owner_thread, 0, sizeof(pthread_t));
|
||||
ret_value = pthread_cond_signal(&mutex->cond_var);
|
||||
|
||||
if (ret_value) {
|
||||
pthread_mutex_unlock(&mutex->atomic_lock);
|
||||
return ret_value;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&(*mutex).atomic_lock);
|
||||
|
||||
return pthread_mutex_unlock(&mutex->atomic_lock);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_cancel_count_inc
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_cancel_count_inc()
|
||||
*
|
||||
* RETURNS
|
||||
* 0 on success non-zero error code on error.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Creates a cancelation counter for a thread if it is the first time
|
||||
@ -210,41 +255,59 @@ H5TS_mutex_unlock(H5TS_mutex_t *mutex)
|
||||
*
|
||||
* MODIFICATIONS:
|
||||
*
|
||||
* 19 May 2000, Bill Wendling
|
||||
* Changed function to return a value. Also changed the malloc() call to
|
||||
* the H5MM_malloc() call and checked the returned pointer.
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
herr_t
|
||||
H5TS_cancel_count_inc(void)
|
||||
{
|
||||
H5TS_cancel_t *cancel_counter;
|
||||
herr_t ret_value = 0;
|
||||
|
||||
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 = pthread_getspecific(H5TS_cancel_key_g);
|
||||
|
||||
if (!cancel_counter) {
|
||||
/*
|
||||
* First time thread calls library - create new counter and associate
|
||||
* with key
|
||||
*/
|
||||
cancel_counter = (H5TS_cancel_t *)malloc(sizeof(H5TS_cancel_t));
|
||||
cancel_counter = H5MM_malloc(sizeof(H5TS_cancel_t));
|
||||
|
||||
if (!cancel_counter) {
|
||||
H5E_push(H5E_RESOURCE, H5E_NOSPACE, "H5TS_cancel_count_inc",
|
||||
__FILE__, __LINE__, "memory allocation failed");
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
cancel_counter->cancel_count = 0;
|
||||
pthread_setspecific(H5TS_cancel_key_g, (void *)cancel_counter);
|
||||
ret_value = pthread_setspecific(H5TS_cancel_key_g,
|
||||
(void *)cancel_counter);
|
||||
}
|
||||
|
||||
if (cancel_counter->cancel_count == 0) {
|
||||
if (cancel_counter->cancel_count == 0)
|
||||
/* thread entering library */
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &(cancel_counter->previous_state));
|
||||
}
|
||||
cancel_counter->cancel_count++;
|
||||
ret_value = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
|
||||
&cancel_counter->previous_state);
|
||||
|
||||
++cancel_counter->cancel_count;
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* NAME
|
||||
* H5TS_cancel_count_dec
|
||||
*
|
||||
* USAGE
|
||||
* H5TS_cancel_count_dec()
|
||||
*
|
||||
* RETURNS
|
||||
* 0 on success and a non-zero error code on error.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* if counter value is one, then set cancelability type of the thread
|
||||
* If counter value is one, then set cancelability type of the thread
|
||||
* to the previous cancelability type stored in the cancelation counter.
|
||||
* (the thread is leaving the library).
|
||||
*
|
||||
@ -255,17 +318,24 @@ H5TS_cancel_count_inc(void)
|
||||
*
|
||||
* MODIFICATIONS:
|
||||
*
|
||||
* 19 May 2000, Bill Wendling
|
||||
* Changed so that function returns a value. May be of limited usefulness.
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
herr_t
|
||||
H5TS_cancel_count_dec(void)
|
||||
{
|
||||
H5TS_cancel_t *cancel_counter = pthread_getspecific(H5TS_cancel_key_g);
|
||||
herr_t ret_value = 0;
|
||||
register H5TS_cancel_t *cancel_counter;
|
||||
|
||||
if (cancel_counter->cancel_count == 1) {
|
||||
pthread_setcancelstate(cancel_counter->previous_state, NULL);
|
||||
}
|
||||
cancel_counter->cancel_count--;
|
||||
cancel_counter = pthread_getspecific(H5TS_cancel_key_g);
|
||||
|
||||
if (cancel_counter->cancel_count == 1)
|
||||
ret_value = pthread_setcancelstate(cancel_counter->previous_state, NULL);
|
||||
|
||||
--cancel_counter->cancel_count;
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* H5_HAVE_THREADSAFE */
|
||||
|
@ -14,8 +14,8 @@
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef _H5TSprivate_H
|
||||
#define _H5TSprivate_H
|
||||
#ifndef H5TSprivate_H_
|
||||
#define H5TSprivate_H_
|
||||
|
||||
/* Public headers needed by this file */
|
||||
#ifdef LATER
|
||||
@ -25,10 +25,10 @@
|
||||
/* 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;
|
||||
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 */
|
||||
@ -38,17 +38,16 @@ extern pthread_key_t H5TS_errstk_key_g;
|
||||
#if defined c_plusplus || defined __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* c_plusplus || __cplusplus */
|
||||
#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);
|
||||
__DLL__ herr_t H5TS_mutex_lock(H5TS_mutex_t *mutex);
|
||||
__DLL__ herr_t H5TS_mutex_unlock(H5TS_mutex_t *mutex);
|
||||
__DLL__ herr_t H5TS_cancel_count_inc(void);
|
||||
__DLL__ herr_t H5TS_cancel_count_dec(void);
|
||||
|
||||
#if defined c_plusplus || defined __cplusplus
|
||||
}
|
||||
#endif /* c_plusplus || __cplusplus */
|
||||
|
||||
#endif /* _H5TSprivate_H */
|
||||
#endif /* c_plusplus || __cplusplus */
|
||||
|
||||
#endif /* H5TSprivate_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user