/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 */