summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2020-07-20 21:06:54 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2020-07-20 21:06:54 (GMT)
commita3aedfff18d9e0f75f53a9b55ed8112bc991a26b (patch)
tree62aa1bc5c0efbcddce3cf5b8440bf616f0bed08f /src
parent09c266186d68e78055ba05d509e28ffe1589a27a (diff)
downloadhdf5-a3aedfff18d9e0f75f53a9b55ed8112bc991a26b.zip
hdf5-a3aedfff18d9e0f75f53a9b55ed8112bc991a26b.tar.gz
hdf5-a3aedfff18d9e0f75f53a9b55ed8112bc991a26b.tar.bz2
Brought over thread-safety changes from develop.
Diffstat (limited to 'src')
-rw-r--r--src/H5Eint.c9
-rw-r--r--src/H5TS.c153
-rw-r--r--src/H5TSprivate.h10
-rw-r--r--src/H5private.h9
-rw-r--r--src/H5win32defs.h4
5 files changed, 163 insertions, 22 deletions
diff --git a/src/H5Eint.c b/src/H5Eint.c
index d0880f5..2371a5f 100644
--- a/src/H5Eint.c
+++ b/src/H5Eint.c
@@ -36,6 +36,7 @@
#include "H5Epkg.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
+#include "H5TSprivate.h" /* Thread stuff */
/****************/
@@ -258,10 +259,8 @@ H5E__walk1_cb(int n, H5E_error1_t *err_desc, void *client_data)
else
HDfprintf(stream, "thread 0");
} /* end block */
-#elif defined(H5_HAVE_THREADSAFE)
- HDfprintf(stream, "thread %lu", (unsigned long)HDpthread_self_ulong());
#else
- HDfprintf(stream, "thread 0");
+ HDfprintf(stream, "thread %" PRIu64, H5TS_thread_id());
#endif
HDfprintf(stream, ":\n");
} /* end if */
@@ -390,10 +389,8 @@ H5E__walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data)
else
HDfprintf(stream, "thread 0");
} /* end block */
-#elif defined(H5_HAVE_THREADSAFE)
- HDfprintf(stream, "thread %lu", (unsigned long)HDpthread_self_ulong());
#else
- HDfprintf(stream, "thread 0");
+ HDfprintf(stream, "thread %" PRIu64, H5TS_thread_id());
#endif
HDfprintf(stream, ":\n");
} /* end if */
diff --git a/src/H5TS.c b/src/H5TS.c
index adc31dc..ee3b219 100644
--- a/src/H5TS.c
+++ b/src/H5TS.c
@@ -37,6 +37,31 @@ H5TS_key_t H5TS_funcstk_key_g;
H5TS_key_t H5TS_apictx_key_g;
H5TS_key_t H5TS_cancel_key_g;
+#ifndef H5_HAVE_WIN_THREADS
+
+/* An H5TS_tid_t is a record of a thread identifier that is
+ * available for reuse.
+ */
+struct _tid;
+typedef struct _tid H5TS_tid_t;
+
+struct _tid {
+ H5TS_tid_t *next;
+ uint64_t id;
+};
+
+/* Pointer to first free thread ID record or NULL. */
+static H5TS_tid_t *H5TS_tid_next_free = NULL;
+static uint64_t H5TS_tid_next_id = 0;
+
+/* Mutual exclusion for access to H5TS_tid_next_free and H5TS_tid_next_id. */
+static pthread_mutex_t H5TS_tid_mtx;
+
+/* Key for thread-local storage of the thread ID. */
+static H5TS_key_t H5TS_tid_key;
+
+#endif /* H5_HAVE_WIN_THREADS */
+
/*--------------------------------------------------------------------------
* NAME
@@ -70,6 +95,127 @@ H5TS_key_destructor(void *key_val)
/*--------------------------------------------------------------------------
* NAME
+ * H5TS_tid_destructor
+ *
+ * USAGE
+ * H5TS_tid_destructor()
+ *
+ * RETURNS
+ *
+ * DESCRIPTION
+ * When a thread shuts down, put its ID record on the free list.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+H5TS_tid_destructor(void *_v)
+{
+ H5TS_tid_t *tid = _v;
+
+ if (tid == NULL)
+ return;
+
+ /* TBD use an atomic CAS */
+ pthread_mutex_lock(&H5TS_tid_mtx);
+ tid->next = H5TS_tid_next_free;
+ H5TS_tid_next_free = tid;
+ pthread_mutex_unlock(&H5TS_tid_mtx);
+}
+
+/*--------------------------------------------------------------------------
+ * NAME
+ * H5TS_tid_init
+ *
+ * USAGE
+ * H5TS_tid_init()
+ *
+ * RETURNS
+ *
+ * DESCRIPTION
+ * Initialize for integer thread identifiers.
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+H5TS_tid_init(void)
+{
+ pthread_mutex_init(&H5TS_tid_mtx, NULL);
+ pthread_key_create(&H5TS_tid_key, H5TS_tid_destructor);
+}
+
+/*--------------------------------------------------------------------------
+ * NAME
+ * H5TS_thread_id
+ *
+ * USAGE
+ * uint64_t id = H5TS_thread_id()
+ *
+ * RETURNS
+ * Return an integer identifier, ID, for the current thread.
+ *
+ * DESCRIPTION
+ * The ID satisfies the following properties:
+ *
+ * 1 1 <= ID <= UINT64_MAX
+ * 2 ID is constant over the thread's lifetime.
+ * 3 No two threads share an ID during their lifetimes.
+ * 4 A thread's ID is available for reuse as soon as it is joined.
+ *
+ * ID 0 is reserved. H5TS_thread_id() returns 0 if the library was not
+ * built with thread safety or if an error prevents it from assigning an
+ * ID.
+ *
+ *--------------------------------------------------------------------------
+ */
+uint64_t
+H5TS_thread_id(void)
+{
+ H5TS_tid_t *tid = pthread_getspecific(H5TS_tid_key);
+ H5TS_tid_t proto_tid;
+
+ /* An ID is already assigned. */
+ if (tid != NULL)
+ return tid->id;
+
+ /* An ID is *not* already assigned: reuse an ID that's on the
+ * free list, or else generate a new ID.
+ *
+ * Allocating memory while holding a mutex is bad form, so
+ * point `tid` at `proto_tid` if we need to allocate some
+ * memory.
+ */
+ pthread_mutex_lock(&H5TS_tid_mtx);
+ if ((tid = H5TS_tid_next_free) != NULL)
+ H5TS_tid_next_free = tid->next;
+ else if (H5TS_tid_next_id != UINT64_MAX) {
+ tid = &proto_tid;
+ tid->id = ++H5TS_tid_next_id;
+ }
+ pthread_mutex_unlock(&H5TS_tid_mtx);
+
+ /* If a prototype ID record was established, copy it to the heap. */
+ if (tid == &proto_tid) {
+ if ((tid = HDmalloc(sizeof(*tid))) != NULL)
+ *tid = proto_tid;
+ }
+
+ if (tid == NULL)
+ return 0;
+
+ /* Finish initializing the ID record and set a thread-local pointer
+ * to it.
+ */
+ tid->next = NULL;
+ if (pthread_setspecific(H5TS_tid_key, tid) != 0) {
+ H5TS_tid_destructor(tid);
+ return 0;
+ }
+
+ return tid->id;
+}
+
+/*--------------------------------------------------------------------------
+ * NAME
* H5TS_pthread_first_thread_init
*
* USAGE
@@ -104,6 +250,9 @@ H5TS_pthread_first_thread_init(void)
pthread_cond_init(&H5_g.init_lock.cond_var, NULL);
H5_g.init_lock.lock_count = 0;
+ /* Initialize integer thread identifiers. */
+ H5TS_tid_init();
+
/* initialize key for thread-specific error stacks */
pthread_key_create(&H5TS_errstk_key_g, H5TS_key_destructor);
@@ -151,7 +300,7 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex)
if (ret_value)
return ret_value;
- if(mutex->lock_count && pthread_equal(HDpthread_self(), mutex->owner_thread)) {
+ if(mutex->lock_count && pthread_equal(pthread_self(), mutex->owner_thread)) {
/* already owned by self - increment count */
mutex->lock_count++;
} else {
@@ -160,7 +309,7 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex)
pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock);
/* After we've received the signal, take ownership of the mutex */
- mutex->owner_thread = HDpthread_self();
+ mutex->owner_thread = pthread_self();
mutex->lock_count = 1;
}
diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h
index 9e093a6..887f001 100644
--- a/src/H5TSprivate.h
+++ b/src/H5TSprivate.h
@@ -26,6 +26,7 @@
#ifndef H5TSprivate_H_
#define H5TSprivate_H_
+#ifdef H5_HAVE_THREADSAFE
/* Public headers needed by this file */
#ifdef LATER
#include "H5TSpublic.h" /*Public API prototypes */
@@ -68,7 +69,7 @@ H5_DLL void H5TS_win32_process_exit(void);
H5_DLL herr_t H5TS_win32_thread_enter(void);
H5_DLL herr_t H5TS_win32_thread_exit(void);
-
+#define H5TS_thread_id() ((uint64_t)GetCurrentThreadId())
#else /* H5_HAVE_WIN_THREADS */
@@ -102,6 +103,7 @@ typedef pthread_once_t H5TS_once_t;
#define H5TS_mutex_init(mutex) pthread_mutex_init(mutex, NULL)
#define H5TS_mutex_lock_simple(mutex) pthread_mutex_lock(mutex)
#define H5TS_mutex_unlock_simple(mutex) pthread_mutex_unlock(mutex)
+H5_DLL uint64_t H5TS_thread_id(void);
#endif /* H5_HAVE_WIN_THREADS */
@@ -127,5 +129,11 @@ H5_DLL H5TS_thread_t H5TS_create_thread(void *(*func)(void *), H5TS_attr_t * att
}
#endif /* c_plusplus || __cplusplus */
+#else /* H5_HAVE_THREADSAFE */
+
+#define H5TS_thread_id() ((uint64_t)0)
+
+#endif /* H5_HAVE_THREADSAFE */
+
#endif /* H5TSprivate_H_ */
diff --git a/src/H5private.h b/src/H5private.h
index 5b1c4db..c0d39fc 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1596,15 +1596,6 @@ extern char *strdup(const char *s);
#define HDstrdup(S) strdup(S)
#endif /* HDstrdup */
-#ifndef HDpthread_self
- #define HDpthread_self() pthread_self()
-#endif /* HDpthread_self */
-
-/* Use this version of pthread_self for printing the thread ID */
-#ifndef HDpthread_self_ulong
- #define HDpthread_self_ulong() ((unsigned long)pthread_self())
-#endif /* HDpthread_self_ulong */
-
/* Macro for "stringizing" an integer in the C preprocessor (use H5_TOSTRING) */
/* (use H5_TOSTRING, H5_STRINGIZE is just part of the implementation) */
#define H5_STRINGIZE(x) #x
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 8c5ae1a..71162eb 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -199,10 +199,6 @@ extern "C" {
/* Non-POSIX functions */
-/* Don't use actual pthread_self on Windows because the return
- * type cannot be cast as a ulong like other systems. */
-#define HDpthread_self_ulong() ((unsigned long)GetCurrentThreadId())
-
#ifndef H5_HAVE_MINGW
#define HDftruncate(F,L) _chsize_s(F,L)
#define HDfseek(F,O,W) _fseeki64(F,O,W)