1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/ztest.h>
7 #include <zephyr/kernel.h>
8 #include <zephyr/kernel_structs.h>
9
10 /* Internal APIs */
11 #include <kernel_internal.h>
12 #include <ksched.h>
13 #include <kthread.h>
14
15 struct k_thread kthread_thread;
16 struct k_thread kthread_thread1;
17
18 #define STACKSIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
19 K_THREAD_STACK_DEFINE(kthread_stack, STACKSIZE);
20 K_SEM_DEFINE(sync_sem, 0, 1);
21
22 static bool fatal_error_signaled;
23
thread_entry(void * p1,void * p2,void * p3)24 static void thread_entry(void *p1, void *p2, void *p3)
25 {
26 ARG_UNUSED(p1);
27 ARG_UNUSED(p2);
28 ARG_UNUSED(p3);
29
30 z_thread_essential_set(_current);
31
32 if (z_is_thread_essential(_current)) {
33 k_busy_wait(100);
34 } else {
35 zassert_unreachable("The thread is not set as essential");
36 }
37
38 z_thread_essential_clear(_current);
39 zassert_false(z_is_thread_essential(_current),
40 "Essential flag of the thread is not cleared");
41
42 k_sem_give(&sync_sem);
43 }
44
45 /**
46 * @brief Test to validate essential flag set/clear
47 *
48 * @ingroup kernel_thread_tests
49 *
50 * @see #K_ESSENTIAL(x)
51 */
ZTEST(threads_lifecycle,test_essential_thread_operation)52 ZTEST(threads_lifecycle, test_essential_thread_operation)
53 {
54 k_tid_t tid = k_thread_create(&kthread_thread, kthread_stack,
55 STACKSIZE, thread_entry, NULL,
56 NULL, NULL, K_PRIO_PREEMPT(0), 0,
57 K_NO_WAIT);
58
59 k_sem_take(&sync_sem, K_FOREVER);
60 k_thread_abort(tid);
61 }
62
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * esf)63 void k_sys_fatal_error_handler(unsigned int reason,
64 const struct arch_esf *esf)
65 {
66 ARG_UNUSED(esf);
67 ARG_UNUSED(reason);
68
69 fatal_error_signaled = true;
70 }
71
abort_thread_entry(void * p1,void * p2,void * p3)72 static void abort_thread_entry(void *p1, void *p2, void *p3)
73 {
74 ARG_UNUSED(p1);
75 ARG_UNUSED(p2);
76 ARG_UNUSED(p3);
77
78 if (z_is_thread_essential(_current)) {
79 k_msleep(200);
80 } else {
81 zassert_unreachable("The thread is not set as essential");
82 }
83
84 zassert_true(false, "Should not reach this line");
85 }
86
abort_thread_self(void * p1,void * p2,void * p3)87 static void abort_thread_self(void *p1, void *p2, void *p3)
88 {
89 k_thread_abort(k_current_get());
90 zassert_true(false, "Should not reach this line");
91 }
92
93 /**
94 * @brief Abort an essential thread
95 *
96 * @details The kernel shall raise a fatal system error if an essential thread
97 * aborts, implement k_sys_fatal_error_handler to handle this error.
98 *
99 * @ingroup kernel_thread_tests
100 *
101 * @see #K_ESSENTIAL(x)
102 */
103
ZTEST(threads_lifecycle,test_essential_thread_abort)104 ZTEST(threads_lifecycle, test_essential_thread_abort)
105 {
106 fatal_error_signaled = false;
107 k_thread_create(&kthread_thread1, kthread_stack, STACKSIZE,
108 abort_thread_entry,
109 NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_ESSENTIAL,
110 K_NO_WAIT);
111
112 k_msleep(100);
113 k_thread_abort(&kthread_thread1);
114 zassert_true(fatal_error_signaled, "fatal error was not signaled");
115 }
116
117 /**
118 * @brief Abort an essential thread from itself
119 *
120 * @details The kernel shall raise a fatal system error if an essential thread
121 * aborts, implement k_sys_fatal_error_handler to handle this error.
122 *
123 * @ingroup kernel_thread_tests
124 *
125 * @see #K_ESSENTIAL(x)
126 */
ZTEST(threads_lifecycle,test_essential_thread_abort_self)127 ZTEST(threads_lifecycle, test_essential_thread_abort_self)
128 {
129 /* This test case needs to be able to handle a k_panic() call
130 * that aborts the current thread inside of the panic handler
131 * itself. That's putting a lot of strain on the arch layer
132 * to handle things that haven't traditionally been required.
133 * These ones aren't there yet.
134 *
135 * But run it for everyone else to catch regressions in the
136 * code we are actually trying to test.
137 */
138 if (IS_ENABLED(CONFIG_RISCV) || IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_SPARC)) {
139 ztest_test_skip();
140 }
141
142 fatal_error_signaled = false;
143 k_thread_create(&kthread_thread1, kthread_stack, STACKSIZE,
144 abort_thread_self,
145 NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_ESSENTIAL,
146 K_NO_WAIT);
147
148 k_msleep(100);
149 zassert_true(fatal_error_signaled, "fatal error was not signaled");
150 }
151