From b97c63cdbcdcf3f575aedfbfb3b2e00e2a28be60 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Fri, 19 May 2000 17:02:24 -0500 Subject: [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. --- src/H5TS.c | 230 +++++++++++++++++++++++++++++++++++------------------- src/H5TSprivate.h | 27 +++---- 2 files changed, 163 insertions(+), 94 deletions(-) diff --git a/src/H5TS.c b/src/H5TS.c index 37b7244..7c29a95 100644 --- a/src/H5TS.c +++ b/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 /*library */ -#include /*error handling */ +#include /*library */ +#include /*error handling */ +#include /*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 */ diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index 601b6f0..525450c 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -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_ */ -- cgit v0.12