hdf5/test/ttsafe_atomic.c
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

180 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 thread pool routines
*
********************************************************************/
#include "ttsafe.h"
#ifdef H5_HAVE_THREADS
#define NUM_THREADS 16
static H5TS_atomic_int_t counter_g;
static H5TS_THREAD_RETURN_TYPE
noop_task(void *_counter)
{
H5TS_atomic_int_t *counter = (H5TS_atomic_int_t *)_counter;
H5TS_thread_ret_t ret_value = 0;
VERIFY(H5TS_atomic_load_int(counter), 0, "noop_task");
return ret_value;
}
static H5TS_THREAD_RETURN_TYPE
incr_task(void *_counter)
{
H5TS_atomic_int_t *counter = (H5TS_atomic_int_t *)_counter;
H5TS_thread_ret_t ret_value = 0;
H5TS_atomic_fetch_add_int(counter, 1);
return ret_value;
}
static H5TS_THREAD_RETURN_TYPE
decr_task(void *_counter)
{
H5TS_atomic_int_t *counter = (H5TS_atomic_int_t *)_counter;
H5TS_thread_ret_t ret_value = 0;
H5TS_atomic_fetch_sub_int(counter, 1);
return ret_value;
}
/*
**********************************************************************
* tts_atomics
*
**********************************************************************
*/
void
tts_atomics(const void H5_ATTR_UNUSED *params)
{
H5TS_pool_t *pool = NULL;
herr_t result;
/* Initialize the counter */
H5TS_atomic_init_int(&counter_g, 0);
/* Sanity checks on bad input */
result = H5TS_pool_create(NULL, NUM_THREADS);
VERIFY(result, FAIL, "H5TS_pool_create");
result = H5TS_pool_create(&pool, 0);
VERIFY(result, FAIL, "H5TS_pool_create");
result = H5TS_pool_add_task(NULL, noop_task, NULL);
VERIFY(result, FAIL, "H5TS_pool_add_task");
result = H5TS_pool_add_task(pool, NULL, NULL);
VERIFY(result, FAIL, "H5TS_pool_add_task");
result = H5TS_pool_destroy(NULL);
VERIFY(result, FAIL, "H5TS_pool_destroy");
/* Create & destroy empty pool */
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
/* Create pool, add single 'noop' task, destroy pool */
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
result = H5TS_pool_add_task(pool, noop_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
VERIFY(H5TS_atomic_load_int(&counter_g), 0, "noop");
/* Create pool, add single 'incr' task, destroy pool */
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
result = H5TS_pool_add_task(pool, incr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
VERIFY(H5TS_atomic_load_int(&counter_g), 1, "single incr");
/* Create pool, add pair of 'incr' & 'decr' tasks, destroy pool */
H5TS_atomic_store_int(&counter_g, 10);
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
result = H5TS_pool_add_task(pool, incr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
result = H5TS_pool_add_task(pool, decr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
VERIFY(H5TS_atomic_load_int(&counter_g), 10, "incr + decr");
/* Create pool, add many 'incr' & 'decr' tasks, destroy pool */
H5TS_atomic_store_int(&counter_g, 3);
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
for (unsigned u = 0; u < 200; u++) {
result = H5TS_pool_add_task(pool, incr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
}
for (unsigned u = 0; u < 100; u++) {
result = H5TS_pool_add_task(pool, decr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
}
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
VERIFY(H5TS_atomic_load_int(&counter_g), 103, "200 incr + 100 decr");
/* Create pool, add *lots* of 'incr' & 'decr' tasks, destroy pool */
H5TS_atomic_store_int(&counter_g, 5);
result = H5TS_pool_create(&pool, NUM_THREADS);
CHECK_I(result, "H5TS_pool_create");
for (unsigned u = 0; u < 2 * 1000 * 1000; u++) {
result = H5TS_pool_add_task(pool, incr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
}
for (unsigned u = 0; u < 1 * 1000 * 1000; u++) {
result = H5TS_pool_add_task(pool, decr_task, &counter_g);
CHECK_I(result, "H5TS_pool_add_task");
}
result = H5TS_pool_destroy(pool);
CHECK_I(result, "H5TS_pool_destroy");
VERIFY(H5TS_atomic_load_int(&counter_g), 5 + (1000 * 1000), "2,000,000 incr + 1,000,000 decr");
/* Destroy the atomic counter */
H5TS_atomic_destroy_int(&counter_g);
} /* end tts_atomics() */
#endif /* H5_HAVE_THREADS */