From 1fbb458c8d4757635c2602b097a2f293338dd3ba Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 27 Mar 2024 17:42:26 -0500 Subject: [PATCH] Add support for creating recursive mutices. Signed-off-by: Quincey Koziol --- src/H5FDsubfiling/H5FDioc_threads.c | 2 +- src/H5FDsubfiling/H5subfiling_common.c | 2 +- src/H5TSatomic.c | 4 ++-- src/H5TSexlock.c | 2 +- src/H5TSint.c | 2 +- src/H5TSmutex.c | 28 +++++++++++++++++++++----- src/H5TSpool.c | 2 +- src/H5TSprivate.h | 14 ++++++++++++- src/H5TSrwlock.c | 2 +- test/ttsafe_error.c | 2 +- test/ttsafe_thread_id.c | 2 +- test/ttsafe_thread_pool.c | 2 +- 12 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/H5FDsubfiling/H5FDioc_threads.c b/src/H5FDsubfiling/H5FDioc_threads.c index 8ccfdb021fa..1c468e2d771 100644 --- a/src/H5FDsubfiling/H5FDioc_threads.c +++ b/src/H5FDsubfiling/H5FDioc_threads.c @@ -151,7 +151,7 @@ initialize_ioc_threads(void *_sf_context) t_start = MPI_Wtime(); #endif - if (H5TS_mutex_init(&ioc_data->io_queue.q_mutex) < 0) + if (H5TS_mutex_init(&ioc_data->io_queue.q_mutex, H5TS_MUTEX_TYPE_PLAIN) < 0) H5_SUBFILING_GOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, (-1), "can't initialize IOC thread queue mutex"); /* Allow experimentation with the number of helper threads */ diff --git a/src/H5FDsubfiling/H5subfiling_common.c b/src/H5FDsubfiling/H5subfiling_common.c index fd3da781b42..0b90ebc1923 100644 --- a/src/H5FDsubfiling/H5subfiling_common.c +++ b/src/H5FDsubfiling/H5subfiling_common.c @@ -1851,7 +1851,7 @@ init_subfiling_context(subfiling_context_t *sf_context, const char *base_filenam sf_context->h5_file_id = file_id; sf_context->threads_inited = false; - if (H5TS_mutex_init(&sf_context->mutex) < 0) + if (H5TS_mutex_init(&sf_context->mutex, H5TS_MUTEX_TYPE_PLAIN) < 0) return FAIL; sf_context->file_ref = 0; sf_context->sf_fids = NULL; diff --git a/src/H5TSatomic.c b/src/H5TSatomic.c index 1a41e2f5f35..ab8d1c4fe00 100644 --- a/src/H5TSatomic.c +++ b/src/H5TSatomic.c @@ -78,7 +78,7 @@ H5TS_atomic_init_int(H5TS_atomic_int_t *obj, int desired) FUNC_ENTER_NOAPI_NAMECHECK_ONLY /* Initialize mutex that protects the "atomic" value */ - (void) H5TS_mutex_init(&obj->mutex); + (void) H5TS_mutex_init(&obj->mutex, H5TS_MUTEX_TYPE_PLAIN); /* Set the value */ obj->value = desired; @@ -247,7 +247,7 @@ H5TS_atomic_init_uint(H5TS_atomic_uint_t *obj, unsigned desired) FUNC_ENTER_NOAPI_NAMECHECK_ONLY /* Initialize mutex that protects the "atomic" value */ - (void) H5TS_mutex_init(&obj->mutex); + (void) H5TS_mutex_init(&obj->mutex, H5TS_MUTEX_TYPE_PLAIN); /* Set the value */ obj->value = desired; diff --git a/src/H5TSexlock.c b/src/H5TSexlock.c index a0e5be8cc24..a96612440af 100644 --- a/src/H5TSexlock.c +++ b/src/H5TSexlock.c @@ -82,7 +82,7 @@ H5TS__ex_lock_init(H5TS_ex_lock_t *lock) /* Initialize the lock */ memset(lock, 0, sizeof(*lock)); - if (H5_UNLIKELY(H5TS_mutex_init(&lock->mutex) < 0)) + if (H5_UNLIKELY(H5TS_mutex_init(&lock->mutex, H5TS_MUTEX_TYPE_PLAIN) < 0)) HGOTO_DONE(FAIL); if (H5_UNLIKELY(H5TS_cond_init(&lock->cond_var) < 0)) HGOTO_DONE(FAIL); diff --git a/src/H5TSint.c b/src/H5TSint.c index 02b0cf71854..95bbcbcff96 100644 --- a/src/H5TSint.c +++ b/src/H5TSint.c @@ -293,7 +293,7 @@ H5TS__tinfo_init(void) FUNC_ENTER_PACKAGE_NAMECHECK_ONLY /* Initialize the critical section for modifying the thread info globals */ - H5TS_mutex_init(&H5TS_tinfo_mtx_s); + H5TS_mutex_init(&H5TS_tinfo_mtx_s, H5TS_MUTEX_TYPE_PLAIN); /* Initialize key for thread-specific API contexts */ #ifdef H5_HAVE_WIN_THREADS diff --git a/src/H5TSmutex.c b/src/H5TSmutex.c index a1169cfa0e4..2aca42d82e2 100644 --- a/src/H5TSmutex.c +++ b/src/H5TSmutex.c @@ -71,13 +71,13 @@ *------------------------------------------------------------------------- */ herr_t -H5TS_mutex_init(H5TS_mutex_t *mutex) +H5TS_mutex_init(H5TS_mutex_t *mutex, int type) { herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NAMECHECK_ONLY - if (H5_UNLIKELY(mtx_init(mutex, mtx_plain) != thrd_success)) + if (H5_UNLIKELY(mtx_init(mutex, type) != thrd_success)) HGOTO_DONE(FAIL); done: @@ -185,12 +185,14 @@ H5TS_mutex_destroy(H5TS_mutex_t *mutex) * * Purpose: Initialize a H5TS_mutex_t (does not allocate it) * + * Note: All Windows CriticalSections are recursive + * * Return: Non-negative on success / Negative on failure * *------------------------------------------------------------------------- */ herr_t -H5TS_mutex_init(H5TS_mutex_t *mutex) +H5TS_mutex_init(H5TS_mutex_t *mutex, int H5_ATTR_UNUSED type) { FUNC_ENTER_NOAPI_NAMECHECK_ONLY @@ -286,16 +288,32 @@ H5TS_mutex_destroy(H5TS_mutex_t *mutex) *------------------------------------------------------------------------- */ herr_t -H5TS_mutex_init(H5TS_mutex_t *mutex) +H5TS_mutex_init(H5TS_mutex_t *mutex, int type) { + pthread_mutexattr_t _attr; + pthread_mutexattr_t *attr = NULL; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NAMECHECK_ONLY - if (H5_UNLIKELY(pthread_mutex_init(mutex, NULL))) + /* Set up recursive mutex, if requested */ + if (H5TS_MUTEX_TYPE_RECURSIVE == type) { + if (H5_UNLIKELY(pthread_mutexattr_init(&_attr))) + HGOTO_DONE(FAIL); + attr = &_attr; + + if (H5_UNLIKELY(pthread_mutexattr_settype(attr, PTHREAD_MUTEX_RECURSIVE))) + HGOTO_DONE(FAIL); + } + + if (H5_UNLIKELY(pthread_mutex_init(mutex, attr))) HGOTO_DONE(FAIL); done: + if (NULL != attr) + if (H5_UNLIKELY(pthread_mutexattr_destroy(attr))) + ret_value = FAIL; + FUNC_LEAVE_NOAPI_NAMECHECK_ONLY(ret_value) } /* end H5TS_mutex_init() */ diff --git a/src/H5TSpool.c b/src/H5TSpool.c index 39735b23611..51c04b448f0 100644 --- a/src/H5TSpool.c +++ b/src/H5TSpool.c @@ -227,7 +227,7 @@ H5TS_pool_create(H5TS_pool_t **pool, unsigned num_threads) /* Initialize pool fields to defaults */ memset(new_pool, 0, sizeof(*new_pool)); - if (H5_UNLIKELY(H5TS_mutex_init(&new_pool->mutex) < 0)) + if (H5_UNLIKELY(H5TS_mutex_init(&new_pool->mutex, H5TS_MUTEX_TYPE_PLAIN) < 0)) HGOTO_DONE(FAIL); if (H5_UNLIKELY(H5TS_cond_init(&new_pool->cond) < 0)) HGOTO_DONE(FAIL); diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h index beed1ce38a4..40c3af16503 100644 --- a/src/H5TSprivate.h +++ b/src/H5TSprivate.h @@ -47,6 +47,10 @@ #define H5TS_thread_equal(t1, t2) thrd_equal((t1), (t2)) #define H5TS_THREAD_RETURN_TYPE H5TS_thread_ret_t #define H5TS_THREAD_CANCEL_DISABLE 0 + +/* Mutex macros */ +#define H5TS_MUTEX_TYPE_PLAIN mtx_plain +#define H5TS_MUTEX_TYPE_RECURSIVE (mtx_plain | mtx_recursive) #else #ifdef H5_HAVE_WIN_THREADS /* Static initialization values */ @@ -57,6 +61,10 @@ #define H5TS_thread_equal(t1, t2) (GetThreadId(t1) == GetThreadId(t2)) #define H5TS_THREAD_RETURN_TYPE H5TS_thread_ret_t WINAPI #define H5TS_THREAD_CANCEL_DISABLE 0 + +/* Mutex macros */ +#define H5TS_MUTEX_TYPE_PLAIN 0 +#define H5TS_MUTEX_TYPE_RECURSIVE 1 #else /* Static initialization values */ #define H5TS_ONCE_INITIALIZER PTHREAD_ONCE_INIT @@ -66,6 +74,10 @@ #define H5TS_thread_equal(t1, t2) pthread_equal((t1), (t2)) #define H5TS_THREAD_RETURN_TYPE H5TS_thread_ret_t #define H5TS_THREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE + +/* Mutex macros */ +#define H5TS_MUTEX_TYPE_PLAIN 0 +#define H5TS_MUTEX_TYPE_RECURSIVE 1 #endif #endif @@ -169,7 +181,7 @@ H5_DLL struct H5E_t *H5TS_get_err_stack(void); H5_DLL herr_t H5TS_once(H5TS_once_t *once, H5TS_once_init_func_t func); /* Mutex operations */ -H5_DLL herr_t H5TS_mutex_init(H5TS_mutex_t *mutex); +H5_DLL herr_t H5TS_mutex_init(H5TS_mutex_t *mutex, int type); H5_DLL herr_t H5TS_mutex_lock(H5TS_mutex_t *mutex) H5TS_ACQUIRE(*mutex); H5_DLL herr_t H5TS_mutex_try_lock(H5TS_mutex_t *mutex, bool *acquired) H5TS_TRY_ACQUIRE(SUCCEED, *mutex); H5_DLL herr_t H5TS_mutex_unlock(H5TS_mutex_t *mutex) H5TS_RELEASE(*mutex); diff --git a/src/H5TSrwlock.c b/src/H5TSrwlock.c index 899fb62a40b..395caa05cf2 100644 --- a/src/H5TSrwlock.c +++ b/src/H5TSrwlock.c @@ -422,7 +422,7 @@ H5TS__rw_lock_init(H5TS_rw_lock_t *rw_lock) /* Initialize the lock */ memset(rw_lock, 0, sizeof(*rw_lock)); HDcompile_assert(H5TS_RW_LOCK_UNUSED == 0); - if (H5_UNLIKELY(H5TS_mutex_init(&rw_lock->mutex) < 0)) + if (H5_UNLIKELY(H5TS_mutex_init(&rw_lock->mutex, H5TS_MUTEX_TYPE_PLAIN) < 0)) HGOTO_DONE(FAIL); if (H5_UNLIKELY(H5TS_cond_init(&rw_lock->writers_cv) < 0)) HGOTO_DONE(FAIL); diff --git a/test/ttsafe_error.c b/test/ttsafe_error.c index 199487eee97..95062eaa8d1 100644 --- a/test/ttsafe_error.c +++ b/test/ttsafe_error.c @@ -99,7 +99,7 @@ tts_error(void) expected_g[10].maj_num = H5E_LINK; expected_g[10].min_num = H5E_EXISTS; - status = H5TS_mutex_init(&error_mutex_g); + status = H5TS_mutex_init(&error_mutex_g, H5TS_MUTEX_TYPE_PLAIN); CHECK_I(status, "H5TS_mutex_init"); def_fapl = H5Pcreate(H5P_FILE_ACCESS); diff --git a/test/ttsafe_thread_id.c b/test/ttsafe_thread_id.c index 37300b7c431..70673e674cc 100644 --- a/test/ttsafe_thread_id.c +++ b/test/ttsafe_thread_id.c @@ -100,7 +100,7 @@ tts_thread_id(void) int i; herr_t result; - result = H5TS_mutex_init(&used_lock); + result = H5TS_mutex_init(&used_lock, H5TS_MUTEX_TYPE_PLAIN); CHECK_I(result, "H5TS_mutex_lock"); result = H5TS__barrier_init(&barrier, NTHREADS); CHECK_I(result, "H5TS__barrier_init"); diff --git a/test/ttsafe_thread_pool.c b/test/ttsafe_thread_pool.c index 3d17574f6f3..43baeebad35 100644 --- a/test/ttsafe_thread_pool.c +++ b/test/ttsafe_thread_pool.c @@ -98,7 +98,7 @@ tts_thread_pool(void) herr_t result; /* Initialize the counter */ - result = H5TS_mutex_init(&counter_g.mutex); + result = H5TS_mutex_init(&counter_g.mutex, H5TS_MUTEX_TYPE_PLAIN); CHECK_I(result, "H5TS_mutex_init"); counter_g.val = 0;