diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5CS.c | 6 | ||||
-rw-r--r-- | src/H5Eint.c | 9 | ||||
-rw-r--r-- | src/H5TS.c | 153 | ||||
-rw-r--r-- | src/H5TSprivate.h | 10 | ||||
-rw-r--r-- | src/H5private.h | 9 | ||||
-rw-r--r-- | src/H5win32defs.h | 4 |
6 files changed, 164 insertions, 27 deletions
@@ -145,11 +145,7 @@ H5CS_print_stack(const H5CS_t *fstack, FILE *stream) HDfprintf(stream, "HDF5-DIAG: Function stack from %s ", H5_lib_vers_info_g); /* try show the process or thread id in multiple processes cases*/ -#ifdef H5_HAVE_THREADSAFE - HDfprintf(stream, "thread %lu.", HDpthread_self_ulong()); -#else /* H5_HAVE_THREADSAFE */ - HDfprintf(stream, "thread 0."); -#endif /* H5_HAVE_THREADSAFE */ + HDfprintf(stream, "thread %" PRIu64 ".", H5TS_thread_id()); if(fstack && fstack->nused>0) HDfprintf(stream, " Back trace follows."); HDfputc('\n', stream); 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 */ @@ -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) |