1 /*
2 * Copyright (c) 2024 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <stdio.h>
10
11
12 /* COMMON DEFFINITIONS */
13 #define STACK_SIZE 500
14 #define LIST_LEN 8
15
16 static struct k_sem sema;
17 static struct k_thread tdata;
18
19 static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
20
21
22 /* FIFO SCENARIO */
23 /* Thread A enters items into a fifo, starts Thread B and waits for a semaphore. */
24 /* Thread B extracts all items from the fifo and enters some items back into the fifo. */
25 /* Thread B gives the semaphore for Thread A to continue. */
26 /* Once the control is returned back to Thread A, it extracts all items from the fifo. */
27 /* Verify the data's correctness. */
28
29 static K_FIFO_DEFINE(fifo);
30 struct fifo_item_t {
31 void *fifo_reserved; /* 1st word reserved for use by FIFO */
32 uint8_t value;
33 };
34 static struct fifo_item_t fifo_data[LIST_LEN];
35
thread_entry_fn_fifo(void * p1,void * p2,void * p3)36 static void thread_entry_fn_fifo(void *p1, void *p2, void *p3)
37 {
38 struct fifo_item_t *rx_data;
39 uint32_t i;
40
41 /* Get items from fifo */
42 for (i = 0U; i < LIST_LEN; i++) {
43 rx_data = k_fifo_get((struct k_fifo *)p1, K_NO_WAIT);
44 zassert_equal(rx_data->value, fifo_data[i].value);
45 }
46
47 /* Put items into fifo */
48 for (i = 0U; i < LIST_LEN; i++) {
49 fifo_data[i].value *= i;
50 k_fifo_put((struct k_fifo *)p1, &fifo_data[i]);
51 }
52
53 /* Give control back to Thread A */
54 k_sem_give(&sema);
55 }
56
57
ZTEST(kernel,test_fifo_usage)58 ZTEST(kernel, test_fifo_usage)
59 {
60 struct fifo_item_t *rx_data;
61 uint32_t i;
62
63 /* Init binary semaphore */
64 k_sem_init(&sema, 0, 1);
65
66 /* Set and Put items into fifo */
67 for (i = 0U; i < LIST_LEN; i++) {
68 fifo_data[i].value = i;
69 k_fifo_put(&fifo, &fifo_data[i]);
70 }
71
72 /* Create the Thread B */
73 k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
74 thread_entry_fn_fifo, &fifo, NULL, NULL,
75 K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
76
77 /* Let the thread B run */
78 k_sem_take(&sema, K_FOREVER);
79
80 /* Get items from fifo */
81 for (i = 0U; i < LIST_LEN; i++) {
82 rx_data = k_fifo_get(&fifo, K_NO_WAIT);
83 zassert_equal(rx_data->value, fifo_data[i].value);
84 }
85
86 /* Clear the spawn thread */
87 k_thread_abort(tid);
88 }
89
90 /* LIFO SCENARIO */
91 /* Thread A enters items into a lifo, starts Thread B and waits for a semaphore. */
92 /* Thread B extracts all items from the lifo and enters some items back into the lifo. */
93 /* Thread B gives the semaphore for Thread A to continue. */
94 /* Once the control is returned back to Thread A, it extracts all items from the lifo. */
95 /* Verify the data's correctness. */
96
97 struct lifo_item_t {
98 void *LIFO_reserved; /* 1st word reserved for use by LIFO */
99 uint8_t value;
100 };
101 static struct lifo_item_t lifo_data[LIST_LEN];
102 K_LIFO_DEFINE(lifo);
103
104
thread_entry_fn_lifo(void * p1,void * p2,void * p3)105 static void thread_entry_fn_lifo(void *p1, void *p2, void *p3)
106 {
107 struct lifo_item_t *rx_data;
108 uint32_t i;
109
110 /* Get items from lifo */
111 for (i = 0U; i < LIST_LEN; i++) {
112 rx_data = k_lifo_get((struct k_lifo *)p1, K_NO_WAIT);
113 zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value);
114 }
115
116 /* Put items into lifo */
117 for (i = 0U; i < LIST_LEN; i++) {
118 lifo_data[i].value *= i;
119 k_lifo_put((struct k_lifo *)p1, &lifo_data[i]);
120 }
121
122 /* Give control back to Thread A */
123 k_sem_give(&sema);
124 }
125
ZTEST(kernel,test_lifo_usage)126 ZTEST(kernel, test_lifo_usage)
127 {
128 struct lifo_item_t *rx_data;
129 uint32_t i;
130
131 /* Init binary semaphore */
132 k_sem_init(&sema, 0, 1);
133
134 /* Set and Put items into lifo */
135 for (i = 0U; i < LIST_LEN; i++) {
136 lifo_data[i].value = i;
137 k_lifo_put(&lifo, &lifo_data[i]);
138 }
139
140 /* Create the Thread B */
141 k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
142 thread_entry_fn_lifo, &lifo, NULL, NULL,
143 K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
144
145 /* Let the thread B run */
146 k_sem_take(&sema, K_FOREVER);
147
148 /* Get items from lifo */
149 for (i = 0U; i < LIST_LEN; i++) {
150 rx_data = k_lifo_get(&lifo, K_NO_WAIT);
151 zassert_equal(rx_data->value, lifo_data[LIST_LEN-1-i].value);
152 }
153
154 /* Clear the spawn thread */
155 k_thread_abort(tid);
156
157 }
158
159 /* STACK SCENARIO */
160 /* Thread A enters items into a stack, starts thread B and waits for a semaphore. */
161 /* Thread B extracts all items from the stack and enters some items back into the stack. */
162 /* Thread B gives the semaphore for Thread A to continue. */
163 /* Once the control is returned back to Thread A, it extracts all items from the stack. */
164 /* Verify the data's correctness. */
165
166
167 #define STACK_LEN 8
168 #define MAX_ITEMS 8
169
170 K_STACK_DEFINE(stack, STACK_LEN);
171 stack_data_t stack_data[MAX_ITEMS];
172
173
thread_entry_fn_stack(void * p1,void * p2,void * p3)174 static void thread_entry_fn_stack(void *p1, void *p2, void *p3)
175 {
176 stack_data_t *rx_data;
177 stack_data_t data[MAX_ITEMS];
178
179 /* fill data to compare */
180 for (int i = 0; i < STACK_LEN; i++) {
181 data[i] = i;
182 }
183
184 /* read data from a stack */
185 for (int i = 0; i < STACK_LEN; i++) {
186 k_stack_pop((struct k_stack *)p1, (stack_data_t *)&rx_data, K_NO_WAIT);
187 }
188
189 zassert_false(memcmp(rx_data, data, STACK_LEN),
190 "Push & Pop items does not match");
191
192 /* Push data into a stack */
193 for (int i = 0; i < STACK_LEN; i++) {
194 stack_data[i] *= i;
195 k_stack_push((struct k_stack *)p1, (stack_data_t)&stack_data[i]);
196 }
197
198 /* Give control back to Thread A */
199 k_sem_give(&sema);
200 }
201
202
ZTEST(kernel,test_stack_usage)203 ZTEST(kernel, test_stack_usage)
204 {
205 stack_data_t *rx_data;
206
207 /* Init binary semaphore */
208 k_sem_init(&sema, 0, 1);
209
210 /* Push data into a stack */
211 for (int i = 0; i < STACK_LEN; i++) {
212 stack_data[i] = i;
213 k_stack_push(&stack, (stack_data_t)&stack_data[i]);
214 }
215
216 /* Create the Thread B */
217 k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
218 thread_entry_fn_stack, &stack, NULL, NULL,
219 K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_NO_WAIT);
220
221 /* Let the thread B run */
222 k_sem_take(&sema, K_FOREVER);
223
224 /* read data from a stack */
225 for (int i = 0; i < STACK_LEN; i++) {
226 k_stack_pop(&stack, (stack_data_t *)&rx_data, K_NO_WAIT);
227 }
228
229
230 /* Verify the correctness */
231 zassert_false(memcmp(rx_data, stack_data, STACK_LEN),
232 "Push & Pop items does not match");
233
234 /* Clear the spawn thread */
235 k_thread_abort(tid);
236 }
237
238 /* MUTEX SCENARIO */
239 /* Initialize the mutex. */
240 /* Start the two Threads with the entry points. */
241 /* The entry points change variable and use lock and unlock mutex functions to */
242 /* synchronize the access to that variable. */
243 /* Join all threads. */
244 /* Verify the variable. */
245
246 #define NUMBER_OF_ITERATIONS 10000
247
248 static uint32_t mutex_data;
249 static struct k_thread tdata_2;
250 static K_THREAD_STACK_DEFINE(tstack_2, STACK_SIZE);
251
252 K_MUTEX_DEFINE(mutex);
253
thread_entry_fn_mutex(void * p1,void * p2,void * p3)254 static void thread_entry_fn_mutex(void *p1, void *p2, void *p3)
255 {
256 uint32_t i;
257
258 for (i = 0; i < NUMBER_OF_ITERATIONS; i++) {
259 k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
260 mutex_data += 1;
261 k_mutex_unlock((struct k_mutex *)p1);
262 }
263 }
264
thread_entry_fn_mutex_2(void * p1,void * p2,void * p3)265 static void thread_entry_fn_mutex_2(void *p1, void *p2, void *p3)
266 {
267 uint32_t i;
268
269 for (i = 0; i < NUMBER_OF_ITERATIONS*2; i++) {
270 k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
271 mutex_data -= 1;
272 k_mutex_unlock((struct k_mutex *)p1);
273 }
274 }
275
ZTEST(kernel,test_mutex_usage)276 ZTEST(kernel, test_mutex_usage)
277 {
278
279 /* Create the Thread A */
280 k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
281 thread_entry_fn_mutex, &mutex, &mutex_data, NULL,
282 K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER);
283
284 /* Create the Thread B */
285 k_tid_t tid2 = k_thread_create(&tdata_2, tstack_2, STACK_SIZE,
286 thread_entry_fn_mutex_2, &mutex, &mutex_data, NULL,
287 K_PRIO_PREEMPT(0), K_INHERIT_PERMS, K_FOREVER);
288
289 /* Start the Thread A */
290 k_thread_start(tid);
291 /* Start the Thread B */
292 k_thread_start(tid2);
293 /* Wait for end of Thread A */
294 k_thread_join(&tdata, K_FOREVER);
295 /* Wait for end of Thread B */
296 k_thread_join(&tdata_2, K_FOREVER);
297 /* Verify data after the end of the threads */
298 zassert_equal(mutex_data, -10000);
299
300 /* Clear the spawn threads */
301 k_thread_abort(tid);
302 k_thread_abort(tid2);
303 }
304
305
306 ZTEST_SUITE(kernel, NULL, NULL,
307 ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
308