hdf5/test/ttsafe_atomic.c
jhendersonHDF 34d6ef545a
Refactor h5test.c, testframe.c and testpar.h testing frameworks (#4891)
Added new testframe.h header to document testing framework functions and
split them away from h5test.h and from test programs that don't
integrate with the testframe.c testing framework

Added new test setup callback to testframe.c testing framework

Added parameters to AddTest() to specify size of test parameters so they
can be copied for later use

Enabled HDF5 error stacks in testframe.c framework by default and added
some error stack suppressions to some testhdf5 tests

Added new maxthreads option to testframe.c framework to allow specifying
the maximum number of threads a multi-threaded test can use

Moved TestExpress functionality out of testframe.c and into more general
h5test.c for wider use by tests through getter and setter

Updated some tests to not mix and match functionality between h5test.c/h
and testframe.c/h

Moved some functionality from testphdf5.h into testpar.h for parallel
tests that aren't part of testphdf5

Added new parallel test library that contains common shared
functionality for parallel tests (similar to h5test library)
2024-10-01 16:10:03 -05: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 COPYING 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 */