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 ISR used to change a thread's priority
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  *
37  * @brief thread2 portion to test setting the priority
38  *
39  */
thread2_set_prio_test(void * p1,void * p2,void * p3)40 void thread2_set_prio_test(void *p1, void *p2, void *p3)
41 {
42 	ARG_UNUSED(p1);
43 	ARG_UNUSED(p2);
44 	ARG_UNUSED(p3);
45 
46 	/* lower thread2 priority by 5 */
47 	k_sem_take(&sem_thread2, K_FOREVER);
48 	thread2_data = k_thread_priority_get(k_current_get());
49 	k_sem_give(&sem_thread1);
50 
51 	/* raise thread2 priority by 10 */
52 	k_sem_take(&sem_thread2, K_FOREVER);
53 	thread2_data = k_thread_priority_get(k_current_get());
54 	k_sem_give(&sem_thread1);
55 
56 	/* restore thread2 priority */
57 	k_sem_take(&sem_thread2, K_FOREVER);
58 	thread2_data = k_thread_priority_get(k_current_get());
59 	k_sem_give(&sem_thread1);
60 }
61 
62 /**
63  * @ingroup kernel_thread_tests
64  * @brief Test the k_thread_priority_set() API
65  *
66  * @see k_thread_priority_set(), k_thread_priority_get()
67  */
ZTEST(threads_lifecycle,test_threads_priority_set)68 ZTEST(threads_lifecycle, test_threads_priority_set)
69 {
70 	int rv;
71 	int prio = k_thread_priority_get(k_current_get());
72 
73 	/* Lower the priority of the current thread (thread1) */
74 	k_thread_priority_set(k_current_get(), prio + 2);
75 	rv = k_thread_priority_get(k_current_get());
76 	zassert_equal(rv, prio + 2,
77 		      "Expected priority to be changed to %d, not %d\n",
78 		      prio + 2, rv);
79 
80 	/* Raise the priority of the current thread (thread1) */
81 	k_thread_priority_set(k_current_get(), prio - 2);
82 	rv = k_thread_priority_get(k_current_get());
83 	zassert_equal(rv, prio - 2,
84 		      "Expected priority to be changed to %d, not %d\n",
85 		      prio - 2, rv);
86 
87 	/* Restore the priority of the current thread (thread1) */
88 	k_thread_priority_set(k_current_get(), prio);
89 	rv = k_thread_priority_get(k_current_get());
90 	zassert_equal(rv, prio,
91 		      "Expected priority to be changed to %d, not %d\n",
92 		      prio, rv);
93 
94 	/* create thread with lower priority */
95 	int thread2_prio = prio + 1;
96 
97 	k_tid_t thread2_id = k_thread_create(&tdata, tstack, STACK_SIZE,
98 					     thread2_set_prio_test,
99 					     NULL, NULL, NULL, thread2_prio, 0,
100 					     K_NO_WAIT);
101 
102 	/* Lower the priority of thread2 */
103 	k_thread_priority_set(thread2_id, thread2_prio + 2);
104 	k_sem_give(&sem_thread2);
105 	k_sem_take(&sem_thread1, K_FOREVER);
106 	zassert_equal(thread2_data, thread2_prio + 2,
107 		      "Expected priority to be changed to %d, not %d\n",
108 		      thread2_prio + 2, thread2_data);
109 
110 	/* Raise the priority of thread2 */
111 	k_thread_priority_set(thread2_id, thread2_prio - 2);
112 	k_sem_give(&sem_thread2);
113 	k_sem_take(&sem_thread1, K_FOREVER);
114 	zassert_equal(thread2_data, thread2_prio - 2,
115 		      "Expected priority to be changed to %d, not %d\n",
116 		      thread2_prio - 2, thread2_data);
117 
118 	/* Restore the priority of thread2 */
119 	k_thread_priority_set(thread2_id, thread2_prio);
120 	k_sem_give(&sem_thread2);
121 	k_sem_take(&sem_thread1, K_FOREVER);
122 	zassert_equal(thread2_data, thread2_prio,
123 		      "Expected priority to be changed to %d, not %d\n",
124 		      thread2_prio, thread2_data);
125 
126 	k_thread_join(thread2_id, K_FOREVER);
127 }
128 
129 /**
130  * @ingroup kernel_thread_tests
131  * @brief Test the k_thread_priority_set() API from an ISR
132  *
133  * @see k_thread_priority_set(), k_thread_priority_get()
134  */
ZTEST(threads_lifecycle,test_isr_threads_priority_set_)135 ZTEST(threads_lifecycle, test_isr_threads_priority_set_)
136 {
137 	int rv;
138 	int prio = k_thread_priority_get(k_current_get());
139 
140 	/* Lower the priority of the current thread (thread1) */
141 	prio_args.thread = k_current_get();
142 	prio_args.prio = prio + 2;
143 	irq_offload(test_isr, &prio_args);
144 	rv = k_thread_priority_get(k_current_get());
145 	zassert_equal(rv, prio + 2,
146 		      "Expected priority to be changed to %d, not %d\n",
147 		      prio + 2, rv);
148 
149 	/* Raise the priority of the current thread (thread1) */
150 	prio_args.prio = prio - 2;
151 	irq_offload(test_isr, &prio_args);
152 	rv = k_thread_priority_get(k_current_get());
153 	zassert_equal(rv, prio - 2,
154 		      "Expected priority to be changed to %d, not %d\n",
155 		      prio - 2, rv);
156 
157 	/* Restore the priority of the current thread (thread1) */
158 	prio_args.prio = prio;
159 	irq_offload(test_isr, &prio_args);
160 	rv = k_thread_priority_get(k_current_get());
161 	zassert_equal(rv, prio,
162 		      "Expected priority to be changed to %d, not %d\n",
163 		      prio, rv);
164 
165 	/* create thread with lower priority */
166 	int thread2_prio = prio + 1;
167 
168 	k_tid_t thread2_id = k_thread_create(&tdata, tstack, STACK_SIZE,
169 					     thread2_set_prio_test,
170 					     NULL, NULL, NULL, thread2_prio, 0,
171 					     K_NO_WAIT);
172 
173 	/* Lower the priority of thread2 */
174 	prio_args.thread = thread2_id;
175 	prio_args.prio = thread2_prio + 2;
176 	irq_offload(test_isr, &prio_args);
177 	k_sem_give(&sem_thread2);
178 	k_sem_take(&sem_thread1, K_FOREVER);
179 	zassert_equal(thread2_data, thread2_prio + 2,
180 		      "Expected priority to be changed to %d, not %d\n",
181 		      thread2_prio + 2, thread2_data);
182 
183 	/* Raise the priority of thread2 */
184 	prio_args.prio = thread2_prio - 2;
185 	irq_offload(test_isr, &prio_args);
186 	k_sem_give(&sem_thread2);
187 	k_sem_take(&sem_thread1, K_FOREVER);
188 	zassert_equal(thread2_data, thread2_prio - 2,
189 		      "Expected priority to be changed to %d, not %d\n",
190 		      thread2_prio - 2, thread2_data);
191 
192 	/* Restore the priority of thread2 */
193 	prio_args.prio = thread2_prio;
194 	irq_offload(test_isr, &prio_args);
195 	k_sem_give(&sem_thread2);
196 	k_sem_take(&sem_thread1, K_FOREVER);
197 	zassert_equal(thread2_data, thread2_prio,
198 		      "Expected priority to be changed to %d, not %d\n",
199 		      thread2_prio, thread2_data);
200 	k_thread_join(thread2_id, K_FOREVER);
201 }
202