summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <wendling@ncsa.uiuc.edu>2000-05-19 22:02:24 (GMT)
committerBill Wendling <wendling@ncsa.uiuc.edu>2000-05-19 22:02:24 (GMT)
commitb97c63cdbcdcf3f575aedfbfb3b2e00e2a28be60 (patch)
treed817141cf75aad516b6f8571eff324eddb7247ad
parentfb75b8a89ce45af2ac6c14ed31ffc884b0d0fc88 (diff)
downloadhdf5-b97c63cdbcdcf3f575aedfbfb3b2e00e2a28be60.zip
hdf5-b97c63cdbcdcf3f575aedfbfb3b2e00e2a28be60.tar.gz
hdf5-b97c63cdbcdcf3f575aedfbfb3b2e00e2a28be60.tar.bz2
[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.
-rw-r--r--src/H5TS.c230
-rw-r--r--src/H5TSprivate.h27
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 <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 */
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_ */