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