1 /*
2 * Copyright (c) 2024 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/tc_util.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/irq_offload.h>
11
12 #if CONFIG_MP_MAX_NUM_CPUS < 2
13 #error "SMP test requires at least two CPUs!"
14 #endif
15
16 #define NUM_THREADS CONFIG_MP_MAX_NUM_CPUS
17 #define STACK_SIZE 1024
18
19 K_THREAD_STACK_ARRAY_DEFINE(thread_stack, NUM_THREADS, STACK_SIZE);
20 struct k_thread thread[NUM_THREADS];
21
22 struct isr_args {
23 volatile bool *sync;
24 volatile bool *wait;
25 struct k_thread *target;
26 };
27
28 volatile bool sync[NUM_THREADS];
29
30 struct isr_args isr_args[NUM_THREADS];
31
isr(const void * args)32 static void isr(const void *args)
33 {
34 const struct isr_args *var = args;
35
36 *(var->sync) = true; /* Flag that ISR is in progress */
37
38 while (*(var->wait) == false) { /* Wait upon dependent CPU */
39 }
40
41 k_thread_abort(var->target); /* Abort thread on another CPU */
42 }
43
thread_entry(void * p1,void * p2,void * p3)44 static void thread_entry(void *p1, void *p2, void *p3)
45 {
46 unsigned int index = (unsigned int)(uintptr_t)p1;
47 struct isr_args *var = p2;
48
49 printk("Thread %u started\n", index);
50
51 irq_offload(isr, var);
52
53 zassert_true(false, "Thread %u did not abort!", index);
54 }
55
ZTEST(smp_abort,test_smp_thread_abort_deadlock)56 ZTEST(smp_abort, test_smp_thread_abort_deadlock)
57 {
58 unsigned int i;
59 int priority;
60
61 priority = k_thread_priority_get(k_current_get());
62
63 /*
64 * Each thread will run on its own CPU and invoke an ISR.
65 * Each ISR will wait until the next thread enters its ISR
66 * before attempting to abort that thread. This ensures that
67 * we have a scenario where each CPU is attempting to abort
68 * the active thread that was interrupted by an ISR.
69 */
70
71 for (i = 0; i < NUM_THREADS; i++) {
72 isr_args[i].sync = &sync[i];
73 isr_args[i].wait = &sync[(i + 1) % NUM_THREADS];
74 isr_args[i].target = &thread[(i + 1) % NUM_THREADS];
75 }
76
77 for (i = 0; i < NUM_THREADS; i++) {
78
79 k_thread_create(&thread[i], thread_stack[i],
80 STACK_SIZE, thread_entry,
81 (void *)(uintptr_t)i, &isr_args[i], NULL,
82 priority - 1, 0, K_NO_WAIT);
83 }
84
85 for (i = 0; i < NUM_THREADS; i++) {
86 k_thread_join(&thread[i], K_FOREVER);
87 }
88
89 printk("Done!\n");
90 }
91
92 ZTEST_SUITE(smp_abort, NULL, NULL, NULL, NULL, NULL);
93