/* * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include volatile int ztress_dummy; bool ztress_handler_busy(void *user_data, uint32_t cnt, bool last, int prio) { /* On nios2 k_busy_wait in k_timer handler context is hanging. */ if (IS_ENABLED(CONFIG_NIOS2) && k_is_in_isr()) { for (int i = 0; i < 1000; i++) { ztress_dummy++; } } else { k_busy_wait((prio+1) * 100); } return true; } ZTEST(ztress, test_timeout) { int64_t d; uint32_t repeat = 1000000; k_timeout_t t = Z_TIMEOUT_TICKS(20); int err; int timeout = 1000; ztress_set_timeout(K_MSEC(timeout)); d = k_uptime_get(); /* Set of two threads */ ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, t), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 1000, t)); d = k_uptime_get() - d; zassert_within(d, 1000, 200); /* Set of two threads and timer. Test is setup manually, without helper macro. */ struct ztress_context_data timer_data = ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 0, t); struct ztress_context_data thread_data[] = { ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t), ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t) }; d = k_uptime_get(); err = ztress_execute(&timer_data, thread_data, ARRAY_SIZE(thread_data)); zassert_equal(err, 0, "ztress_execute failed (err: %d)", err); d = k_uptime_get() - d; zassert_within(d, timeout + 500, 500); ztress_set_timeout(K_NO_WAIT); } static void timeout_abort(struct k_timer *timer) { ztress_abort(); } ZTEST(ztress, test_abort) { struct k_timer timer; uint32_t repeat = 10000000; k_timer_init(&timer, timeout_abort, NULL); k_timer_start(&timer, K_MSEC(100), K_NO_WAIT); ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, K_MSEC(1)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, K_MSEC(1))); zassert_true(ztress_exec_count(0) < repeat); zassert_true(ztress_exec_count(1) < repeat); } ZTEST(ztress, test_repeat_completion) { uint32_t repeat = 10; /* Set of two threads */ ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20))); for (int i = 0; i < 2; i++) { uint32_t exec_cnt = ztress_exec_count(i); zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10); } /* Set of two threads and timer */ ZTRESS_EXECUTE(ZTRESS_TIMER(ztress_handler_busy, NULL, repeat, Z_TIMEOUT_TICKS(30)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30))); for (int i = 0; i < 3; i++) { uint32_t exec_cnt = ztress_exec_count(i); zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10); } } ZTEST(ztress, test_no_context_requirements) { uint32_t repeat = 10; /* Set of two threads. First thread has no ending condition (exec_cnt and * preempt_cnt are 0) */ ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, 0, 0, Z_TIMEOUT_TICKS(20)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20))); uint32_t exec_cnt = ztress_exec_count(1); zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10, "exec_cnt: %u", exec_cnt); /* Set of two threads. Second thread and timer context has no ending * condition (exec_cnt and preempt_cnt are 0). */ ZTRESS_EXECUTE(ZTRESS_TIMER(ztress_handler_busy, NULL, 0, Z_TIMEOUT_TICKS(30)), ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30)), ZTRESS_THREAD(ztress_handler_busy, NULL, 0, 0, Z_TIMEOUT_TICKS(30))); exec_cnt = ztress_exec_count(1); zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10); } ZTEST(ztress, test_too_many_threads) { uint32_t repeat = 10; k_timeout_t t = Z_TIMEOUT_TICKS(20); int err; /* Negative check on too many threads set and a timer. * Assuming ZTRESS_MAX_THREADS=3 */ struct ztress_context_data timer_data = ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 0, t); struct ztress_context_data thread_data[] = { ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t), ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t), ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t) }; err = ztress_execute(&timer_data, thread_data, ARRAY_SIZE(thread_data)); zassert_equal(err, -EINVAL, "ztress_execute: unexpected err=%d (expected -EINVAL)", err); } ZTEST_SUITE(ztress, NULL, NULL, NULL, NULL, NULL);