1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8
9 #include <zephyr/irq_offload.h>
10
11 #include "tests_thread_apis.h"
12
13 static int thread2_data;
14
15 K_SEM_DEFINE(sem_thread2, 0, 1);
16 K_SEM_DEFINE(sem_thread1, 0, 1);
17
18 struct isr_arg {
19 k_tid_t thread;
20 int prio;
21 };
22
23 static struct isr_arg prio_args;
24
25 /**
26 * @brief Test changing a thread's priority from an ISR
27 */
test_isr(const void * arg)28 static void test_isr(const void *arg)
29 {
30 const struct isr_arg *data = arg;
31
32 k_thread_priority_set(data->thread, data->prio);
33 }
34
35 /**
36 * @brief Test thread behavior when its priority is changed
37 */
thread2_set_prio_test(void * p1,void * p2,void * p3)38 void thread2_set_prio_test(void *p1, void *p2, void *p3)
39 {
40 ARG_UNUSED(p1);
41 ARG_UNUSED(p2);
42 ARG_UNUSED(p3);
43
44 /* lower thread2 priority by 5 */
45 k_sem_take(&sem_thread2, K_FOREVER);
46 thread2_data = k_thread_priority_get(k_current_get());
47 k_sem_give(&sem_thread1);
48
49 /* raise thread2 priority by 10 */
50 k_sem_take(&sem_thread2, K_FOREVER);
51 thread2_data = k_thread_priority_get(k_current_get());
52 k_sem_give(&sem_thread1);
53
54 /* restore thread2 priority */
55 k_sem_take(&sem_thread2, K_FOREVER);
56 thread2_data = k_thread_priority_get(k_current_get());
57 k_sem_give(&sem_thread1);
58 }
59
60 /**
61 * @ingroup kernel_thread_tests
62 * @brief Test setting and verifying thread priorities
63 *
64 * @details This test creates a thread with a lower priority than the
65 * current thread. It then sets the priority of the thread to a
66 * higher value, and checks that the priority has been set correctly.
67 *
68 * @see k_thread_priority_set(), k_thread_priority_get()
69 */
ZTEST(threads_lifecycle,test_threads_priority_set)70 ZTEST(threads_lifecycle, test_threads_priority_set)
71 {
72 int rv;
73 int prio = k_thread_priority_get(k_current_get());
74
75 /* Lower the priority of the current thread (thread1) */
76 k_thread_priority_set(k_current_get(), prio + 2);
77 rv = k_thread_priority_get(k_current_get());
78 zassert_equal(rv, prio + 2,
79 "Expected priority to be changed to %d, not %d\n",
80 prio + 2, rv);
81
82 /* Raise the priority of the current thread (thread1) */
83 k_thread_priority_set(k_current_get(), prio - 2);
84 rv = k_thread_priority_get(k_current_get());
85 zassert_equal(rv, prio - 2,
86 "Expected priority to be changed to %d, not %d\n",
87 prio - 2, rv);
88
89 /* Restore the priority of the current thread (thread1) */
90 k_thread_priority_set(k_current_get(), prio);
91 rv = k_thread_priority_get(k_current_get());
92 zassert_equal(rv, prio,
93 "Expected priority to be changed to %d, not %d\n",
94 prio, rv);
95
96 /* create thread with lower priority */
97 int thread2_prio = prio + 1;
98
99 k_tid_t thread2_id = k_thread_create(&tdata, tstack, STACK_SIZE,
100 thread2_set_prio_test,
101 NULL, NULL, NULL, thread2_prio, 0,
102 K_NO_WAIT);
103
104 /* Lower the priority of thread2 */
105 k_thread_priority_set(thread2_id, thread2_prio + 2);
106 k_sem_give(&sem_thread2);
107 k_sem_take(&sem_thread1, K_FOREVER);
108 zassert_equal(thread2_data, thread2_prio + 2,
109 "Expected priority to be changed to %d, not %d\n",
110 thread2_prio + 2, thread2_data);
111
112 /* Raise the priority of thread2 */
113 k_thread_priority_set(thread2_id, thread2_prio - 2);
114 k_sem_give(&sem_thread2);
115 k_sem_take(&sem_thread1, K_FOREVER);
116 zassert_equal(thread2_data, thread2_prio - 2,
117 "Expected priority to be changed to %d, not %d\n",
118 thread2_prio - 2, thread2_data);
119
120 /* Restore the priority of thread2 */
121 k_thread_priority_set(thread2_id, thread2_prio);
122 k_sem_give(&sem_thread2);
123 k_sem_take(&sem_thread1, K_FOREVER);
124 zassert_equal(thread2_data, thread2_prio,
125 "Expected priority to be changed to %d, not %d\n",
126 thread2_prio, thread2_data);
127
128 k_thread_join(thread2_id, K_FOREVER);
129 }
130
131 /**
132 * @ingroup kernel_thread_tests
133 * @brief Test changing thread priorities from an ISR
134 *
135 * @details This test verifies that thread priorities can be changed
136 * correctly when invoked from an interrupt service routine (ISR).
137 *
138 * @see k_thread_priority_set(), k_thread_priority_get()
139 */
ZTEST(threads_lifecycle,test_isr_threads_priority_set_)140 ZTEST(threads_lifecycle, test_isr_threads_priority_set_)
141 {
142 int rv;
143 int prio = k_thread_priority_get(k_current_get());
144
145 /* Lower the priority of the current thread (thread1) */
146 prio_args.thread = k_current_get();
147 prio_args.prio = prio + 2;
148 irq_offload(test_isr, &prio_args);
149 rv = k_thread_priority_get(k_current_get());
150 zassert_equal(rv, prio + 2,
151 "Expected priority to be changed to %d, not %d\n",
152 prio + 2, rv);
153
154 /* Raise the priority of the current thread (thread1) */
155 prio_args.prio = prio - 2;
156 irq_offload(test_isr, &prio_args);
157 rv = k_thread_priority_get(k_current_get());
158 zassert_equal(rv, prio - 2,
159 "Expected priority to be changed to %d, not %d\n",
160 prio - 2, rv);
161
162 /* Restore the priority of the current thread (thread1) */
163 prio_args.prio = prio;
164 irq_offload(test_isr, &prio_args);
165 rv = k_thread_priority_get(k_current_get());
166 zassert_equal(rv, prio,
167 "Expected priority to be changed to %d, not %d\n",
168 prio, rv);
169
170 /* create thread with lower priority */
171 int thread2_prio = prio + 1;
172
173 k_tid_t thread2_id = k_thread_create(&tdata, tstack, STACK_SIZE,
174 thread2_set_prio_test,
175 NULL, NULL, NULL, thread2_prio, 0,
176 K_NO_WAIT);
177
178 /* Lower the priority of thread2 */
179 prio_args.thread = thread2_id;
180 prio_args.prio = thread2_prio + 2;
181 irq_offload(test_isr, &prio_args);
182 k_sem_give(&sem_thread2);
183 k_sem_take(&sem_thread1, K_FOREVER);
184 zassert_equal(thread2_data, thread2_prio + 2,
185 "Expected priority to be changed to %d, not %d\n",
186 thread2_prio + 2, thread2_data);
187
188 /* Raise the priority of thread2 */
189 prio_args.prio = thread2_prio - 2;
190 irq_offload(test_isr, &prio_args);
191 k_sem_give(&sem_thread2);
192 k_sem_take(&sem_thread1, K_FOREVER);
193 zassert_equal(thread2_data, thread2_prio - 2,
194 "Expected priority to be changed to %d, not %d\n",
195 thread2_prio - 2, thread2_data);
196
197 /* Restore the priority of thread2 */
198 prio_args.prio = thread2_prio;
199 irq_offload(test_isr, &prio_args);
200 k_sem_give(&sem_thread2);
201 k_sem_take(&sem_thread1, K_FOREVER);
202 zassert_equal(thread2_data, thread2_prio,
203 "Expected priority to be changed to %d, not %d\n",
204 thread2_prio, thread2_data);
205 k_thread_join(thread2_id, K_FOREVER);
206 }
207