From 8edf9817c08d0378fbd33d942504650262db8d74 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Mon, 17 Jan 2022 17:04:25 +0100 Subject: [PATCH] tests/kernel/smp: Add SMP switch torture test Formalize and rework the issue reproducer for #40795 and add it to the SMP test suite. Signed-off-by: Carlo Caione --- .../smp/boards/qemu_cortex_a53_smp.conf | 4 ++ .../smp/boards/qemu_cortex_a53_smp.overlay | 19 ++++++ tests/kernel/smp/prj.conf | 1 + tests/kernel/smp/src/main.c | 66 ++++++++++++++++++- 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 tests/kernel/smp/boards/qemu_cortex_a53_smp.conf create mode 100644 tests/kernel/smp/boards/qemu_cortex_a53_smp.overlay diff --git a/tests/kernel/smp/boards/qemu_cortex_a53_smp.conf b/tests/kernel/smp/boards/qemu_cortex_a53_smp.conf new file mode 100644 index 0000000000..f62fce907d --- /dev/null +++ b/tests/kernel/smp/boards/qemu_cortex_a53_smp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2022 Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MP_NUM_CPUS=4 diff --git a/tests/kernel/smp/boards/qemu_cortex_a53_smp.overlay b/tests/kernel/smp/boards/qemu_cortex_a53_smp.overlay new file mode 100644 index 0000000000..5bb497069d --- /dev/null +++ b/tests/kernel/smp/boards/qemu_cortex_a53_smp.overlay @@ -0,0 +1,19 @@ +/* Copyright 2022 Carlo Caione + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + cpus { + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <3>; + }; + }; +}; diff --git a/tests/kernel/smp/prj.conf b/tests/kernel/smp/prj.conf index d175a28c0c..82aba8421f 100644 --- a/tests/kernel/smp/prj.conf +++ b/tests/kernel/smp/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_SMP=y CONFIG_TRACE_SCHED_IPI=y +CONFIG_POLL=y diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c index e7b1b6abc8..d6a2c050ae 100644 --- a/tests/kernel/smp/src/main.c +++ b/tests/kernel/smp/src/main.c @@ -22,6 +22,7 @@ #define EQUAL_PRIORITY 1 #define TIME_SLICE_MS 500 #define THREAD_DELAY 1 +#define SLEEP_MS_LONG 15000 struct k_thread t2; K_THREAD_STACK_DEFINE(t2_stack, T2_STACK_SIZE); @@ -52,6 +53,9 @@ static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREADS_NUM, STACK_SIZE); static volatile int thread_started[THREADS_NUM - 1]; +static struct k_poll_signal tsignal[THREADS_NUM]; +static struct k_poll_event tevent[THREADS_NUM]; + static int curr_cpu(void) { unsigned int k = arch_irq_lock(); @@ -948,6 +952,65 @@ void test_inc_concurrency(void) "total count %d is wrong(M)", global_cnt); } +/** + * @brief Torture test for context switching code + * + * @ingroup kernel_smp_tests + * + * @details Leverage the polling API to stress test the context switching code. + * This test will hammer all the CPUs with thread swapping requests. + */ +static void process_events(void *arg0, void *arg1, void *arg2) +{ + uintptr_t id = (uintptr_t) arg0; + + while (1) { + k_poll(&tevent[id], 1, K_FOREVER); + + if (tevent[id].signal->result != 0x55) { + ztest_test_fail(); + } + + tevent[id].signal->signaled = 0; + tevent[id].state = K_POLL_STATE_NOT_READY; + + k_poll_signal_reset(&tsignal[id]); + } +} + +static void signal_raise(void *arg0, void *arg1, void *arg2) +{ + while (1) { + for (uintptr_t i = 0; i < THREADS_NUM; i++) { + k_poll_signal_raise(&tsignal[i], 0x55); + } + } +} + +void test_smp_switch_torture(void) +{ + for (uintptr_t i = 0; i < THREADS_NUM; i++) { + k_poll_signal_init(&tsignal[i]); + k_poll_event_init(&tevent[i], K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, &tsignal[i]); + + k_thread_create(&tthread[i], tstack[i], STACK_SIZE, + (k_thread_entry_t) process_events, + (void *) i, NULL, NULL, K_PRIO_PREEMPT(i + 1), + K_INHERIT_PERMS, K_NO_WAIT); + } + + k_thread_create(&t2, t2_stack, T2_STACK_SIZE, signal_raise, + NULL, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT); + + k_sleep(K_MSEC(SLEEP_MS_LONG)); + + k_thread_abort(&t2); + for (uintptr_t i = 0; i < THREADS_NUM; i++) { + k_thread_abort(&tthread[i]); + } +} + void test_main(void) { /* Sleep a bit to guarantee that both CPUs enter an idle @@ -969,7 +1032,8 @@ void test_main(void) ztest_unit_test(test_fatal_on_smp), ztest_unit_test(test_workq_on_smp), ztest_unit_test(test_smp_release_global_lock), - ztest_unit_test(test_inc_concurrency) + ztest_unit_test(test_inc_concurrency), + ztest_unit_test(test_smp_switch_torture) ); ztest_run_test_suite(smp); }