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