Files
hdf5/test/ttsafe_develop.c
T
Dana Robinson 7f1e49206d Renamed COPYING to LICENSE (#4978)
This is where most people will expect to find license information. The
COPYING_LBNL_HDF5 file has also been renamed to LICENSE_LBNL_HDF5.
The licenses are unchanged.
2024-10-18 21:13:04 -07:00

166 lines
5.8 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/********************************************************************
*
* Test the correctness of the threadsafety developer API routines
*
********************************************************************/
#include "ttsafe.h"
#ifdef H5_HAVE_THREADSAFE
typedef struct {
H5TS_barrier_t *barrier;
} tts_develop_api_udata_t;
/*
**********************************************************************
* tts_develop_api_thr_1
*
**********************************************************************
*/
static H5TS_THREAD_RETURN_TYPE
tts_develop_api_thr_1(void *_udata)
{
tts_develop_api_udata_t *udata = (tts_develop_api_udata_t *)_udata;
unsigned lock_count = UINT_MAX;
bool acquired = false;
herr_t result;
/* Acquire the API lock - should acquire it */
result = H5TSmutex_acquire(1, &acquired);
CHECK_I(result, "H5TSmutex_acquire");
VERIFY(acquired, true, "H5TSmutex_acquire");
result = H5TS_barrier_wait(udata->barrier);
CHECK_I(result, "H5TS_barrier_wait");
/* Thread #2 will attempt (unsuccessfully) to acquire the API lock */
result = H5TS_barrier_wait(udata->barrier);
CHECK_I(result, "H5TS_barrier_wait");
/* Release the API lock */
result = H5TSmutex_release(&lock_count);
CHECK_I(result, "H5TSmutex_release");
VERIFY(lock_count, 1, "H5TSmutex_release");
return (H5TS_thread_ret_t)0;
} /* end tts_develop_api_thr_1() */
/*
**********************************************************************
* tts_develop_api_thr_2
*
**********************************************************************
*/
static H5TS_THREAD_RETURN_TYPE
tts_develop_api_thr_2(void *_udata)
{
tts_develop_api_udata_t *udata = (tts_develop_api_udata_t *)_udata;
bool acquired = false;
herr_t result;
/* Thread #1 will acquire the API lock */
result = H5TS_barrier_wait(udata->barrier);
CHECK_I(result, "H5TS_barrier_wait");
/* Attempt to acquire the API lock - should not acquire it */
result = H5TSmutex_acquire(1, &acquired);
CHECK_I(result, "H5TSmutex_acquire");
VERIFY(acquired, false, "H5TSmutex_acquire");
result = H5TS_barrier_wait(udata->barrier);
CHECK_I(result, "H5TS_barrier_wait");
/* Thread #1 will release the API lock */
return (H5TS_thread_ret_t)0;
} /* end tts_develop_api_thr_2() */
/*
**********************************************************************
* tts_develop_api
*
**********************************************************************
*/
void
tts_develop_api(const void H5_ATTR_UNUSED *params)
{
H5TS_thread_t thread_1, thread_2;
H5TS_barrier_t barrier;
unsigned lock_count = UINT_MAX;
bool acquired = false;
tts_develop_api_udata_t udata;
unsigned api_count_1 = 0, api_count_2 = 0;
herr_t result;
/* Check that API count increases with each API call */
result = H5TSmutex_get_attempt_count(&api_count_1);
CHECK_I(result, "H5TSmutex_get_attempt_count");
/* No-op API call, to increment the API counter */
result = H5garbage_collect();
CHECK_I(result, "H5garbage_collect");
result = H5TSmutex_get_attempt_count(&api_count_2);
CHECK_I(result, "H5TSmutex_get_attempt_count");
VERIFY(api_count_2, (api_count_1 + 1), "H5TSmutex_get_attempt_count");
/* Check H5TSmutex_acquire & H5TSmutex_release in thread callbacks */
/* Create the thread barrier for the two threads */
result = H5TS_barrier_init(&barrier, 2);
CHECK_I(result, "H5TS_barrier_init");
/* Create the threads */
udata.barrier = &barrier;
result = H5TS_thread_create(&thread_1, tts_develop_api_thr_1, &udata);
CHECK_I(result, "H5TS_thread_create");
result = H5TS_thread_create(&thread_2, tts_develop_api_thr_2, &udata);
CHECK_I(result, "H5TS_thread_create");
/* Wait for threads to complete. */
result = H5TS_thread_join(thread_1, NULL);
CHECK_I(result, "H5TS_thread_join");
result = H5TS_thread_join(thread_2, NULL);
CHECK_I(result, "H5TS_thread_join");
result = H5TS_barrier_destroy(&barrier);
CHECK_I(result, "H5TS_barrier_destroy");
/* Test multiple / recursive acquisition of the API lock */
/* Acquire the API lock - should acquire it */
result = H5TSmutex_acquire(1, &acquired);
CHECK_I(result, "H5TSmutex_acquire");
VERIFY(acquired, true, "H5TSmutex_acquire");
/* Acquire the API lock again - should acquire it, since it's the same thread */
acquired = false;
result = H5TSmutex_acquire(1, &acquired);
CHECK_I(result, "H5TSmutex_acquire");
VERIFY(acquired, true, "H5TSmutex_acquire");
/* Release the API lock */
result = H5TSmutex_release(&lock_count);
CHECK_I(result, "H5TSmutex_release");
VERIFY(lock_count, 2, "H5TSmutex_release");
} /* end tts_develop_api() */
#endif /*H5_HAVE_THREADSAFE*/