From e7aad04774553fe7653dd19d95abade62db5d333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Wed, 24 May 2023 13:20:19 +0300 Subject: validation: time: use ODPH_ERR() instead of fprintf() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ODPH_ERR() instead of fprintf() to produce more uniform error messages. Signed-off-by: Jere Leppänen Reviewed-by: Matias Elo --- test/validation/api/time/time.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index f285bf8e4..df30c86c6 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -423,16 +423,16 @@ static void time_test_wait_until(time_cb time_cur, time_from_ns_cb time_from_ns) DELAY_TOLERANCE); if (odp_time_cmp(wait, lower_limit) < 0) { - fprintf(stderr, "Exceed lower limit: " - "wait is %" PRIu64 ", lower_limit %" PRIu64 "\n", - odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); + ODPH_ERR("Exceed lower limit: " + "wait is %" PRIu64 ", lower_limit %" PRIu64 "\n", + odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed lower limit\n"); } if (odp_time_cmp(wait, upper_limit) > 0) { - fprintf(stderr, "Exceed upper limit: " - "wait is %" PRIu64 ", upper_limit %" PRIu64 "\n", - odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); + ODPH_ERR("Exceed upper limit: " + "wait is %" PRIu64 ", upper_limit %" PRIu64 "\n", + odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed upper limit\n"); } } @@ -466,16 +466,16 @@ static void time_test_wait_ns(void) DELAY_TOLERANCE); if (odp_time_cmp(diff, lower_limit) < 0) { - fprintf(stderr, "Exceed lower limit: " - "diff is %" PRIu64 ", lower_limit %" PRIu64 "\n", - odp_time_to_ns(diff), odp_time_to_ns(lower_limit)); + ODPH_ERR("Exceed lower limit: " + "diff is %" PRIu64 ", lower_limit %" PRIu64 "\n", + odp_time_to_ns(diff), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed lower limit\n"); } if (odp_time_cmp(diff, upper_limit) > 0) { - fprintf(stderr, "Exceed upper limit: " - "diff is %" PRIu64 ", upper_limit %" PRIu64 "\n", - odp_time_to_ns(diff), odp_time_to_ns(upper_limit)); + ODPH_ERR("Exceed upper limit: " + "diff is %" PRIu64 ", upper_limit %" PRIu64 "\n", + odp_time_to_ns(diff), odp_time_to_ns(upper_limit)); CU_FAIL("Exceed upper limit\n"); } } @@ -486,13 +486,13 @@ static void check_time_diff(double t_odp, double t_system, { if (t_odp > t_system * 1.05) { CU_FAIL("ODP time too high"); - fprintf(stderr, "ODP time too high (%s/%d): t_odp: %f, t_system: %f\n", - test, id, t_odp, t_system); + ODPH_ERR("ODP time too high (%s/%d): t_odp: %f, t_system: %f\n", + test, id, t_odp, t_system); } if (t_odp < t_system * 0.95) { CU_FAIL("ODP time too low"); - fprintf(stderr, "ODP time too low (%s/%d): t_odp: %f, t_system: %f\n", - test, id, t_odp, t_system); + ODPH_ERR("ODP time too low (%s/%d): t_odp: %f, t_system: %f\n", + test, id, t_odp, t_system); } } -- cgit v1.2.3 From f65eaefd7eaf6d9917d20963adb0d7832aeb2175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Fri, 12 May 2023 14:52:20 +0300 Subject: validation: time: test that global time is in sync between different threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call odp_time_global() in different threads at the same time, using a barrier. Check that the difference is within an acceptable range. Signed-off-by: Jere Leppänen Reviewed-by: Matias Elo --- test/validation/api/time/time.c | 187 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index df30c86c6..16e1199f9 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -1,5 +1,5 @@ /* Copyright (c) 2015-2018, Linaro Limited - * Copyright (c) 2019-2022, Nokia + * Copyright (c) 2019-2023, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ #include #include +#include #include "odp_cunit_common.h" #define BUSY_LOOP_CNT 30000000 /* used for t > min resolution */ @@ -19,6 +20,11 @@ #define MAX_TIME_RATE 15000000000 #define DELAY_TOLERANCE 40000000 /* deviation for delay */ #define WAIT_SECONDS 3 +#define MAX_WORKERS 32 +#define TIME_SAMPLES 2 +#define TIME_TOLERANCE_NS 1000000 +#define TIME_TOLERANCE_CI_NS 40000000 +#define GLOBAL_SHM_NAME "GlobalTimeTest" static uint64_t local_res; static uint64_t global_res; @@ -28,6 +34,96 @@ typedef uint64_t time_res_cb(void); typedef odp_time_t time_from_ns_cb(uint64_t ns); typedef uint64_t time_nsec_cb(void); +typedef struct { + uint32_t num_threads; + odp_barrier_t test_barrier; + odp_time_t time[MAX_WORKERS + 1][TIME_SAMPLES]; +} global_shared_mem_t; + +static global_shared_mem_t *global_mem; +static odp_instance_t *instance; + +static int time_global_init(odp_instance_t *inst) +{ + odp_shm_t global_shm; + odp_init_t init_param; + odph_helper_options_t helper_options; + uint32_t workers_count, max_threads; + + if (odph_options(&helper_options)) { + ODPH_ERR("odph_options() failed\n"); + return -1; + } + + odp_init_param_init(&init_param); + init_param.mem_model = helper_options.mem_model; + + if (0 != odp_init_global(inst, &init_param, NULL)) { + ODPH_ERR("odp_init_global() failed\n"); + return -1; + } + if (0 != odp_init_local(*inst, ODP_THREAD_CONTROL)) { + ODPH_ERR("odp_init_local() failed\n"); + return -1; + } + + global_shm = odp_shm_reserve(GLOBAL_SHM_NAME, + sizeof(global_shared_mem_t), + ODP_CACHE_LINE_SIZE, 0); + if (global_shm == ODP_SHM_INVALID) { + ODPH_ERR("Unable reserve memory for global_shm\n"); + return -1; + } + + global_mem = odp_shm_addr(global_shm); + memset(global_mem, 0, sizeof(global_shared_mem_t)); + + global_mem->num_threads = MAX_WORKERS; + + workers_count = odp_cpumask_default_worker(NULL, 0); + + max_threads = (workers_count >= MAX_WORKERS) ? + MAX_WORKERS : workers_count; + + if (max_threads < global_mem->num_threads) { + printf("Requested num of threads is too large\n"); + printf("reducing from %" PRIu32 " to %" PRIu32 "\n", + global_mem->num_threads, + max_threads); + global_mem->num_threads = max_threads; + } + + printf("Num of threads used = %" PRIu32 "\n", + global_mem->num_threads); + + instance = inst; + + return 0; +} + +static int time_global_term(odp_instance_t inst) +{ + odp_shm_t shm; + + shm = odp_shm_lookup(GLOBAL_SHM_NAME); + if (0 != odp_shm_free(shm)) { + ODPH_ERR("odp_shm_free() failed\n"); + return -1; + } + + if (0 != odp_term_local()) { + ODPH_ERR("odp_term_local() failed\n"); + return -1; + } + + if (0 != odp_term_global(inst)) { + ODPH_ERR("odp_term_global() failed\n"); + return -1; + } + + return 0; +} + static void time_test_constants(void) { uint64_t ns; @@ -589,6 +685,91 @@ static void time_test_accuracy_nsec(void) } } +static int time_test_global_sync_thr(void *arg ODP_UNUSED) +{ + int tid = odp_thread_id(); + odp_shm_t global_shm = odp_shm_lookup(GLOBAL_SHM_NAME); + global_shared_mem_t *global_mem = odp_shm_addr(global_shm); + + if (!global_mem) + return 1; + + odp_barrier_wait(&global_mem->test_barrier); + global_mem->time[tid][0] = odp_time_global(); + odp_time_wait_ns(ODP_TIME_MSEC_IN_NS * 100); + odp_barrier_wait(&global_mem->test_barrier); + global_mem->time[tid][1] = odp_time_global(); + + return 0; +} + +static void time_test_global_sync(void) +{ + odp_cpumask_t cpumask; + odph_thread_common_param_t thr_common; + odph_thread_param_t thr_param; + odph_thread_t thread_tbl[MAX_WORKERS]; + const uint64_t tolerance = + odp_cunit_ci() ? TIME_TOLERANCE_CI_NS : TIME_TOLERANCE_NS; + int num = global_mem->num_threads; + int tid = odp_thread_id(); + + /* Test using num threads plus the current thread. */ + odp_barrier_init(&global_mem->test_barrier, num + 1); + + odp_cpumask_default_worker(&cpumask, num); + + odph_thread_param_init(&thr_param); + thr_param.start = time_test_global_sync_thr; + thr_param.thr_type = ODP_THREAD_WORKER; + + odph_thread_common_param_init(&thr_common); + thr_common.instance = *instance; + + int thr = 0, cpu = odp_cpumask_first(&cpumask); + + while (cpu >= 0) { + odp_cpumask_t cpumask_one; + + odp_cpumask_zero(&cpumask_one); + odp_cpumask_set(&cpumask_one, cpu); + thr_common.cpumask = &cpumask_one; + + CU_ASSERT_FATAL(odph_thread_create(&thread_tbl[thr++], + &thr_common, &thr_param, 1) == 1); + + /* + * Delay for more than the tolerance, so that we notice if the + * thread's view of global time is affected. + */ + odp_time_wait_ns(tolerance * 2); + + cpu = odp_cpumask_next(&cpumask, cpu); + } + + odp_barrier_wait(&global_mem->test_barrier); + global_mem->time[tid][0] = odp_time_global(); + odp_time_wait_ns(ODP_TIME_MSEC_IN_NS * 100); + odp_barrier_wait(&global_mem->test_barrier); + global_mem->time[tid][1] = odp_time_global(); + CU_ASSERT(odph_thread_join(thread_tbl, num) == num); + + for (int s = 0; s < TIME_SAMPLES; s++) { + uint64_t min = UINT64_MAX, max = 0; + + for (int i = 0; i < num + 1; i++) { + uint64_t t = odp_time_to_ns(global_mem->time[i][s]); + + if (t < min) + min = t; + if (t > max) + max = t; + } + + CU_ASSERT(max - min < tolerance); + } +} + odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_constants), ODP_TEST_INFO(time_test_local_res), @@ -614,6 +795,7 @@ odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_global_strict_diff), ODP_TEST_INFO(time_test_global_strict_sum), ODP_TEST_INFO(time_test_global_strict_cmp), + ODP_TEST_INFO(time_test_global_sync), ODP_TEST_INFO_NULL }; @@ -630,6 +812,9 @@ int main(int argc, char *argv[]) if (odp_cunit_parse_options(argc, argv)) return -1; + odp_cunit_register_global_init(time_global_init); + odp_cunit_register_global_term(time_global_term); + ret = odp_cunit_register(time_suites); if (ret == 0) -- cgit v1.2.3 From f1b6c6d6878608da82659d496e4d78b5cd275b1a Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Wed, 24 May 2023 12:05:55 +0300 Subject: validation: use ODPH_ERR() macro for error prints Use ODPH_ERR() macro for all error prints in the validation tests and make error messages more consistent. The helper macro adds additional debug information (filename, line number, function name) to the error messages, which can help debugging. Signed-off-by: Matias Elo Reviewed-by: Tuomas Taipale --- test/validation/api/time/time.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index 16e1199f9..b00d788a0 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -519,15 +519,13 @@ static void time_test_wait_until(time_cb time_cur, time_from_ns_cb time_from_ns) DELAY_TOLERANCE); if (odp_time_cmp(wait, lower_limit) < 0) { - ODPH_ERR("Exceed lower limit: " - "wait is %" PRIu64 ", lower_limit %" PRIu64 "\n", + ODPH_ERR("Exceed lower limit: wait is %" PRIu64 ", lower_limit %" PRIu64 "\n", odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed lower limit\n"); } if (odp_time_cmp(wait, upper_limit) > 0) { - ODPH_ERR("Exceed upper limit: " - "wait is %" PRIu64 ", upper_limit %" PRIu64 "\n", + ODPH_ERR("Exceed upper limit: wait is %" PRIu64 ", upper_limit %" PRIu64 "\n", odp_time_to_ns(wait), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed upper limit\n"); } @@ -562,15 +560,13 @@ static void time_test_wait_ns(void) DELAY_TOLERANCE); if (odp_time_cmp(diff, lower_limit) < 0) { - ODPH_ERR("Exceed lower limit: " - "diff is %" PRIu64 ", lower_limit %" PRIu64 "\n", + ODPH_ERR("Exceed lower limit: diff is %" PRIu64 ", lower_limit %" PRIu64 "\n", odp_time_to_ns(diff), odp_time_to_ns(lower_limit)); CU_FAIL("Exceed lower limit\n"); } if (odp_time_cmp(diff, upper_limit) > 0) { - ODPH_ERR("Exceed upper limit: " - "diff is %" PRIu64 ", upper_limit %" PRIu64 "\n", + ODPH_ERR("Exceed upper limit: diff is %" PRIu64 ", upper_limit %" PRIu64 "\n", odp_time_to_ns(diff), odp_time_to_ns(upper_limit)); CU_FAIL("Exceed upper limit\n"); } -- cgit v1.2.3 From 09cd7cc9e54c7c838f7e1e3e02476b37616bf6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Fri, 26 May 2023 17:25:09 +0300 Subject: validation: time: fix coverity warning "Incorrect expression (ASSERT_SIDE_EFFECT)" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix coverity warning CID 408074: Incorrect expression (ASSERT_SIDE_EFFECT). In coverity's opinion, CU_ASSERT*() must not contain any side effects, because this could result in different behavior in debug vs. non-debug builds. Signed-off-by: Jere Leppänen Reviewed-by: Petri Savolainen --- test/validation/api/time/time.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index b00d788a0..175234f50 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -731,8 +731,9 @@ static void time_test_global_sync(void) odp_cpumask_set(&cpumask_one, cpu); thr_common.cpumask = &cpumask_one; - CU_ASSERT_FATAL(odph_thread_create(&thread_tbl[thr++], - &thr_common, &thr_param, 1) == 1); + int r = odph_thread_create(&thread_tbl[thr++], + &thr_common, &thr_param, 1); + CU_ASSERT_FATAL(r == 1); /* * Delay for more than the tolerance, so that we notice if the -- cgit v1.2.3 From 2b94fbad865b69c01f03539cedd65eb972558aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Mon, 29 May 2023 16:24:21 +0300 Subject: validation: time: test global time sync also with control thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test for global time sync with one control thread and one worker thread. Also, do not include the main thread in the time sync tests. Signed-off-by: Jere Leppänen Reviewed-by: Petri Savolainen --- test/validation/api/time/time.c | 66 ++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index 175234f50..b5ceaec04 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -699,7 +699,7 @@ static int time_test_global_sync_thr(void *arg ODP_UNUSED) return 0; } -static void time_test_global_sync(void) +static void time_test_global_sync(const int ctrl) { odp_cpumask_t cpumask; odph_thread_common_param_t thr_common; @@ -707,33 +707,42 @@ static void time_test_global_sync(void) odph_thread_t thread_tbl[MAX_WORKERS]; const uint64_t tolerance = odp_cunit_ci() ? TIME_TOLERANCE_CI_NS : TIME_TOLERANCE_NS; - int num = global_mem->num_threads; - int tid = odp_thread_id(); + const int num = ctrl ? 2 : global_mem->num_threads; - /* Test using num threads plus the current thread. */ - odp_barrier_init(&global_mem->test_barrier, num + 1); + if (num < 2) { + printf(" number of threads is less than two, test skipped. "); + return; + } - odp_cpumask_default_worker(&cpumask, num); + odp_barrier_init(&global_mem->test_barrier, num); odph_thread_param_init(&thr_param); thr_param.start = time_test_global_sync_thr; - thr_param.thr_type = ODP_THREAD_WORKER; odph_thread_common_param_init(&thr_common); thr_common.instance = *instance; - int thr = 0, cpu = odp_cpumask_first(&cpumask); + int thr = 0; - while (cpu >= 0) { - odp_cpumask_t cpumask_one; - - odp_cpumask_zero(&cpumask_one); - odp_cpumask_set(&cpumask_one, cpu); - thr_common.cpumask = &cpumask_one; + if (ctrl) { + /* Test sync between one control and one worker thread. */ + odp_cpumask_default_control(&cpumask, 1); + thr_common.cpumask = &cpumask; + thr_param.thr_type = ODP_THREAD_CONTROL; int r = odph_thread_create(&thread_tbl[thr++], &thr_common, &thr_param, 1); CU_ASSERT_FATAL(r == 1); + odp_cpumask_default_worker(&cpumask, 1); + } else { + /* Test sync between num worker threads. */ + odp_cpumask_default_worker(&cpumask, num); + } + + int cpu = odp_cpumask_first(&cpumask); + + while (cpu >= 0) { + odp_cpumask_t cpumask_one; /* * Delay for more than the tolerance, so that we notice if the @@ -741,20 +750,24 @@ static void time_test_global_sync(void) */ odp_time_wait_ns(tolerance * 2); + odp_cpumask_zero(&cpumask_one); + odp_cpumask_set(&cpumask_one, cpu); + thr_common.cpumask = &cpumask_one; + thr_param.thr_type = ODP_THREAD_WORKER; + + int r = odph_thread_create(&thread_tbl[thr++], + &thr_common, &thr_param, 1); + CU_ASSERT_FATAL(r == 1); + cpu = odp_cpumask_next(&cpumask, cpu); } - odp_barrier_wait(&global_mem->test_barrier); - global_mem->time[tid][0] = odp_time_global(); - odp_time_wait_ns(ODP_TIME_MSEC_IN_NS * 100); - odp_barrier_wait(&global_mem->test_barrier); - global_mem->time[tid][1] = odp_time_global(); CU_ASSERT(odph_thread_join(thread_tbl, num) == num); for (int s = 0; s < TIME_SAMPLES; s++) { uint64_t min = UINT64_MAX, max = 0; - for (int i = 0; i < num + 1; i++) { + for (int i = 1; i < num + 1; i++) { uint64_t t = odp_time_to_ns(global_mem->time[i][s]); if (t < min) @@ -767,6 +780,16 @@ static void time_test_global_sync(void) } } +static void time_test_global_sync_workers(void) +{ + time_test_global_sync(0); +} + +static void time_test_global_sync_control(void) +{ + time_test_global_sync(1); +} + odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_constants), ODP_TEST_INFO(time_test_local_res), @@ -792,7 +815,8 @@ odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_global_strict_diff), ODP_TEST_INFO(time_test_global_strict_sum), ODP_TEST_INFO(time_test_global_strict_cmp), - ODP_TEST_INFO(time_test_global_sync), + ODP_TEST_INFO(time_test_global_sync_workers), + ODP_TEST_INFO(time_test_global_sync_control), ODP_TEST_INFO_NULL }; -- cgit v1.2.3 From b684efe827c7227d2f78184a662adb4b9a577067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Mon, 29 May 2023 17:06:40 +0300 Subject: validation: time: print time differences in global time sync test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the time differences as well as min, max and average in the global time sync test. This makes the result of the test visible beyond just pass or fail. Signed-off-by: Jere Leppänen Reviewed-by: Petri Savolainen --- test/validation/api/time/time.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'test/validation/api/time/time.c') diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index b5ceaec04..22189ce03 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -765,19 +765,42 @@ static void time_test_global_sync(const int ctrl) CU_ASSERT(odph_thread_join(thread_tbl, num) == num); for (int s = 0; s < TIME_SAMPLES; s++) { + int min_idx = 0, max_idx = 0; uint64_t min = UINT64_MAX, max = 0; + double avg = 0; for (int i = 1; i < num + 1; i++) { uint64_t t = odp_time_to_ns(global_mem->time[i][s]); - if (t < min) + if (t < min) { min = t; - if (t > max) + min_idx = i; + } + } + + printf("\nround %d\nthread time diffs: ", s); + + for (int i = 1; i < num + 1; i++) { + uint64_t t = odp_time_to_ns(global_mem->time[i][s]) - min; + + printf("%" PRIu64 " ", t); + + if (t > max) { max = t; + max_idx = i; + } + + avg += t; } - CU_ASSERT(max - min < tolerance); + /* The min result itself is not included in the average. */ + avg /= num - 1; + printf("\nmin: %" PRIu64 " (tid %d) max diff: %" PRIu64 + " (tid %d) avg diff: %g", min, min_idx, max, max_idx, avg); + CU_ASSERT(max < tolerance); } + + printf("\n"); } static void time_test_global_sync_workers(void) -- cgit v1.2.3