1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 
8 #include <zephyr/ztest.h>
9 
10 #include "tests_thread_apis.h"
11 
12 static ZTEST_BMEM char tp1[8];
13 static ZTEST_DMEM int tp2 = 100;
14 static ZTEST_BMEM struct k_sema *tp3;
15 static ZTEST_BMEM int spawn_prio;
16 
thread_entry_params(void * p1,void * p2,void * p3)17 static void thread_entry_params(void *p1, void *p2, void *p3)
18 {
19 	/* checkpoint: check parameter 1, 2, 3 */
20 	zassert_equal(p1, tp1);
21 	zassert_equal(POINTER_TO_INT(p2), tp2);
22 	zassert_equal(p3, tp3);
23 }
24 
thread_entry_priority(void * p1,void * p2,void * p3)25 static void thread_entry_priority(void *p1, void *p2, void *p3)
26 {
27 	/* checkpoint: check priority */
28 	zassert_equal(k_thread_priority_get(k_current_get()), spawn_prio);
29 }
30 
thread_entry_delay(void * p1,void * p2,void * p3)31 static void thread_entry_delay(void *p1, void *p2, void *p3)
32 {
33 	tp2 = 100;
34 }
35 
36 /* test cases */
37 
38 /**
39  * @ingroup kernel_thread_tests
40  * @brief Check the parameters passed to thread entry function
41  *
42  * @details Create an user thread and pass 2 variables and a
43  * semaphore to a thread entry function. Check for the correctness
44  * of the parameters passed.
45  *
46  * @see k_thread_create()
47  */
ZTEST_USER(threads_lifecycle,test_threads_spawn_params)48 ZTEST_USER(threads_lifecycle, test_threads_spawn_params)
49 {
50 	k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_params,
51 			tp1, INT_TO_POINTER(tp2), tp3, 0,
52 			K_USER, K_NO_WAIT);
53 	k_msleep(100);
54 }
55 
56 /**
57  * @ingroup kernel_thread_tests
58  * @brief Spawn thread with higher priority
59  *
60  * @details Create an user thread with priority greater than
61  * current thread and check its behavior.
62  *
63  * @see k_thread_create()
64  */
ZTEST(threads_lifecycle,test_threads_spawn_priority)65 ZTEST(threads_lifecycle, test_threads_spawn_priority)
66 {
67 	/* spawn thread with higher priority */
68 	spawn_prio = k_thread_priority_get(k_current_get()) - 1;
69 	k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_priority,
70 			NULL, NULL, NULL, spawn_prio, K_USER, K_NO_WAIT);
71 	k_msleep(100);
72 }
73 
74 /**
75  * @ingroup kernel_thread_tests
76  * @brief Spawn thread with a delay
77  *
78  * @details Create a user thread with delay and check if the
79  * thread entry function is executed only after the timeout occurs.
80  *
81  * @see k_thread_create()
82  */
ZTEST_USER(threads_lifecycle,test_threads_spawn_delay)83 ZTEST_USER(threads_lifecycle, test_threads_spawn_delay)
84 {
85 	/* spawn thread with higher priority */
86 	tp2 = 10;
87 	k_thread_create(&tdata, tstack, STACK_SIZE, thread_entry_delay,
88 			NULL, NULL, NULL, 0, K_USER, K_MSEC(120));
89 	/* 100 < 120 ensure spawn thread not start */
90 	k_msleep(100);
91 	/* checkpoint: check spawn thread not execute */
92 	zassert_true(tp2 == 10);
93 	/* checkpoint: check spawn thread executed */
94 	k_msleep(100);
95 	zassert_true(tp2 == 100);
96 }
97 
98 /**
99  * @ingroup kernel_thread_tests
100  * @brief Spawn thread with forever delay and highest priority
101  *
102  * @details Create an user thread with forever delay and yield
103  * the current thread. Even though the current thread has yielded,
104  * the thread will not be put in ready queue since it has forever delay,
105  * the thread is explicitly started using k_thread_start() and checked
106  * if thread has started executing.
107  *
108  * @see k_thread_create()
109  */
ZTEST(threads_lifecycle,test_threads_spawn_forever)110 ZTEST(threads_lifecycle, test_threads_spawn_forever)
111 {
112 	/* spawn thread with highest priority. It will run immediately once
113 	 * started.
114 	 */
115 	tp2 = 10;
116 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
117 				      thread_entry_delay, NULL, NULL, NULL,
118 				      K_HIGHEST_THREAD_PRIO,
119 				      K_USER, K_FOREVER);
120 	k_yield();
121 	/* checkpoint: check spawn thread not execute */
122 	zassert_true(tp2 == 10);
123 	/* checkpoint: check spawn thread executed */
124 	k_thread_start(tid);
125 	k_yield();
126 	zassert_true(tp2 == 100);
127 	k_thread_abort(tid);
128 }
129 
130 /**
131  * @ingroup kernel_thread_tests
132  * @brief Validate behavior of multiple calls to k_thread_start()
133  *
134  * @details Call k_thread_start() on an already terminated thread
135  *
136  * @see k_thread_start()
137  */
ZTEST(threads_lifecycle,test_thread_start)138 ZTEST(threads_lifecycle, test_thread_start)
139 {
140 	tp2 = 5;
141 
142 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
143 				      thread_entry_delay, NULL, NULL, NULL,
144 				      K_HIGHEST_THREAD_PRIO,
145 				      K_USER, K_FOREVER);
146 
147 	k_thread_start(tid);
148 	k_yield();
149 	zassert_true(tp2 == 100);
150 
151 	/* checkpoint: k_thread_start() should not start the
152 	 * terminated thread
153 	 */
154 
155 	tp2 = 50;
156 	k_thread_start(tid);
157 	k_yield();
158 	zassert_false(tp2 == 100);
159 }
160 
user_start_thread(void * p1,void * p2,void * p3)161 static void user_start_thread(void *p1, void *p2, void *p3)
162 {
163 	*(int *)p1 = 100;
164 }
ZTEST_USER(threads_lifecycle,test_thread_start_user)165 ZTEST_USER(threads_lifecycle, test_thread_start_user)
166 {
167 	tp2 = 5;
168 
169 	k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
170 				      user_start_thread, &tp2, NULL, NULL,
171 				      0,
172 				      K_USER, K_FOREVER);
173 
174 	k_thread_start(tid);
175 	k_msleep(100);
176 	zassert_true(tp2 == 100);
177 	k_thread_abort(tid);
178 }
179