1 /*
2 * Copyright (c) 2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/ztest_error_hook.h>
9
10 /* Macro declarations */
11
12 #define DELAY K_MSEC(50)
13 #define SHORT_TIMEOUT K_MSEC(100)
14 #define LONG_TIMEOUT K_MSEC(1000)
15
16 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
17
18 static struct k_thread treceiver;
19 static struct k_thread textra1;
20 static struct k_thread textra2;
21
22 static K_THREAD_STACK_DEFINE(sreceiver, STACK_SIZE);
23 static K_THREAD_STACK_DEFINE(sextra1, STACK_SIZE);
24 static K_THREAD_STACK_DEFINE(sextra2, STACK_SIZE);
25
26 static K_EVENT_DEFINE(test_event);
27 static K_EVENT_DEFINE(sync_event);
28 static struct k_event init_event;
29 static struct k_event deliver_event;
30
31 static K_SEM_DEFINE(receiver_sem, 0, 1);
32 static K_SEM_DEFINE(sync_sem, 0, 1);
33
34 volatile static uint32_t test_events;
35
36 /**
37 * @defgroup kernel_sys_events_tests Semaphore
38 * @ingroup all_tests
39 * @{
40 * @}
41 */
42
entry_extra1(void * p1,void * p2,void * p3)43 static void entry_extra1(void *p1, void *p2, void *p3)
44 {
45 uint32_t events;
46
47 events = k_event_wait_all(&sync_event, 0x33, true, K_FOREVER);
48
49 k_event_post(&test_event, events);
50 }
51
entry_extra2(void * p1,void * p2,void * p3)52 static void entry_extra2(void *p1, void *p2, void *p3)
53 {
54 uint32_t events;
55
56 events = k_event_wait(&sync_event, 0x3300, true, K_FOREVER);
57
58 k_event_post(&test_event, events);
59 }
60
61 /**
62 * Test the k_event_init() API.
63 *
64 * This is a white-box test to verify that the k_event_init() API initializes
65 * the fields of a k_event structure as expected.
66 */
67
ZTEST(sys_events,test_k_event_init)68 ZTEST(sys_events, test_k_event_init)
69 {
70 k_event_init(&init_event);
71
72 zassert_true(init_event.events == 0);
73 }
74
receive_existing_events(void)75 static void receive_existing_events(void)
76 {
77 /*
78 * Sync point 1-1 : test_event contains events 0x1234.
79 * Test for events 0x2448 (no waiting)--expect an error
80 */
81
82 k_sem_take(&sync_sem, K_FOREVER);
83 test_events = k_event_wait(&test_event, 0x2448, false, K_NO_WAIT);
84 k_sem_give(&receiver_sem);
85
86 /*
87 * Sync point 1-2 : test_event still contains event 0x1234.
88 * Test for events 0x2448 (with waiting)--expect an error
89 */
90
91 k_sem_take(&sync_sem, K_FOREVER);
92 test_events = k_event_wait(&test_event, 0x2448, false, SHORT_TIMEOUT);
93 k_sem_give(&receiver_sem);
94
95 /*
96 * Sync point 1-3: test_event still contains event 0x1234.
97 * Test for events 0x1235 (no waiting)--expect an error
98 */
99
100 k_sem_take(&sync_sem, K_FOREVER);
101 test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
102 k_sem_give(&receiver_sem);
103
104 /*
105 * Sync point 1-4: test_event still contains event 0x1234.
106 * Test for events 0x1235 (no waiting)--expect an error
107 */
108
109 k_sem_take(&sync_sem, K_FOREVER);
110 test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
111 k_sem_give(&receiver_sem);
112
113 /*
114 * Sync point 1-5: test_event still contains event 0x1234.
115 * Test for events 0x0235. Expect 0x0234 to be returned.
116 */
117
118 k_sem_take(&sync_sem, K_FOREVER);
119 test_events = k_event_wait(&test_event, 0x0235, false, K_NO_WAIT);
120 k_sem_give(&receiver_sem);
121
122 /*
123 * Sync point 1-6: test_event still contains event 0x1234.
124 * Test for events 0x1234. Expect 0x1234 to be returned.
125 */
126
127 k_sem_take(&sync_sem, K_FOREVER);
128 test_events = k_event_wait_all(&test_event, 0x1234, false, K_NO_WAIT);
129 k_sem_give(&receiver_sem);
130 }
131
reset_on_receive(void)132 static void reset_on_receive(void)
133 {
134 /* Sync point 2-1 - with reset */
135
136 k_sem_take(&sync_sem, K_FOREVER);
137 test_events = k_event_wait_all(&test_event, 0x1234, true,
138 SHORT_TIMEOUT);
139 k_sem_give(&receiver_sem);
140
141 /* Sync point 2-2 - with reset */
142
143 k_sem_take(&sync_sem, K_FOREVER);
144 test_events = k_event_wait(&test_event, 0x120000, true, SHORT_TIMEOUT);
145 k_sem_give(&receiver_sem);
146
147 /* Sync point 2-3 - with reset */
148
149 k_sem_take(&sync_sem, K_FOREVER);
150 test_events = k_event_wait_all(&test_event, 0x248001, true,
151 SHORT_TIMEOUT);
152 k_sem_give(&receiver_sem);
153
154 /* Sync point 2-4 - with reset */
155
156 k_sem_take(&sync_sem, K_FOREVER);
157 test_events = k_event_wait(&test_event, 0x123458, true,
158 SHORT_TIMEOUT);
159 k_sem_give(&receiver_sem);
160 }
161
162 /**
163 * receiver helper task
164 */
165
receiver(void * p1,void * p2,void * p3)166 static void receiver(void *p1, void *p2, void *p3)
167 {
168 receive_existing_events();
169
170 reset_on_receive();
171 }
172
173 /**
174 * Works with receive_existing_events() to test the waiting for events
175 * when some events have already been sent. No additional events are sent
176 * to the event object during this block of testing.
177 */
test_receive_existing_events(void)178 static void test_receive_existing_events(void)
179 {
180 int rv;
181
182 /*
183 * Sync point 1-1.
184 * K_NO_WAIT, k_event_wait(), no matches
185 */
186
187 k_sem_give(&sync_sem);
188 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
189 zassert_true(rv == 0);
190 zassert_true(test_events == 0);
191
192 /*
193 * Sync point 1-2.
194 * Short timeout, k_event_wait(), no expected matches
195 */
196
197 k_sem_give(&sync_sem);
198 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
199 zassert_true(rv == 0);
200 zassert_true(test_events == 0);
201
202 /*
203 * Sync point 1-3.
204 * K_NO_WAIT, k_event_wait_all(), incomplete match
205 */
206
207 k_sem_give(&sync_sem);
208 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
209 zassert_true(rv == 0);
210 zassert_true(test_events == 0);
211
212 /*
213 * Sync point 1-4.
214 * Short timeout, k_event_wait_all(), incomplete match
215 */
216
217 k_sem_give(&sync_sem);
218 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
219 zassert_true(rv == 0);
220 zassert_true(test_events == 0);
221
222 /*
223 * Sync point 1-5.
224 * Short timeout, k_event_wait_all(), incomplete match
225 */
226
227 k_sem_give(&sync_sem);
228 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
229 zassert_true(rv == 0);
230 zassert_true(test_events == 0x234);
231
232 /*
233 * Sync point 1-6.
234 * Short timeout, k_event_wait_all(), incomplete match
235 */
236
237 k_sem_give(&sync_sem);
238 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
239 zassert_true(rv == 0);
240 zassert_true(test_events == 0x1234);
241 }
242
243 /**
244 * Works with reset_on_receive() to verify that the events stored in the
245 * event object are reset at the appropriate times.
246 */
247
test_reset_on_receive(void)248 static void test_reset_on_receive(void)
249 {
250 int rv;
251
252 /*
253 * Sync point 2-1. Clear events before receive.
254 * Short timeout, k_event_wait_all(), incomplete match
255 */
256
257 k_sem_give(&sync_sem);
258 k_sleep(DELAY); /* Give receiver thread time to run */
259 k_event_post(&test_event, 0x123);
260 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
261 zassert_true(rv == 0);
262 zassert_true(test_events == 0);
263 zassert_true(test_event.events == 0x123);
264
265 /*
266 * Sync point 2-2. Clear events before receive.
267 * Short timeout, k_event_wait(), no matches
268 */
269
270 k_sem_give(&sync_sem);
271 k_sleep(DELAY);
272 k_event_post(&test_event, 0x248);
273 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
274 zassert_true(rv == 0);
275 zassert_true(test_events == 0);
276 zassert_true(test_event.events == 0x248);
277
278 /*
279 * Sync point 2-3. Clear events before receive.
280 * Short timeout, k_event_wait_all(), complete match
281 */
282
283 k_sem_give(&sync_sem);
284 k_sleep(DELAY);
285 k_event_post(&test_event, 0x248021);
286 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
287 zassert_true(rv == 0);
288 zassert_true(test_events == 0x248001);
289 zassert_true(test_event.events == 0x248021);
290
291 /*
292 * Sync point 2-4. Clear events before receive.
293 * Short timeout, k_event_wait(), partial match
294 */
295
296 k_sem_give(&sync_sem);
297 k_sleep(DELAY);
298 k_event_post(&test_event, 0x123456);
299 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
300 zassert_true(rv == 0);
301 zassert_true(test_events == 0x123450);
302 zassert_true(test_event.events == 0x123456);
303
304 k_event_set(&test_event, 0x0); /* Clear events */
305
306 k_sem_give(&sync_sem);
307 }
308
test_wake_multiple_threads(void)309 void test_wake_multiple_threads(void)
310 {
311 uint32_t events;
312
313 /*
314 * The extra threads are expected to be waiting on <sync_event>
315 * Wake them both up.
316 */
317
318 k_event_set(&sync_event, 0xfff);
319
320 /*
321 * The extra threads send back the events they received. Wait
322 * for all of them.
323 */
324
325 events = k_event_wait_all(&test_event, 0x333, false, SHORT_TIMEOUT);
326
327 zassert_true(events == 0x333);
328 }
329
330 /**
331 * Test basic k_event_post() and k_event_set() APIs.
332 *
333 * Tests the basic k_event_post() and k_event_set() API. This does not
334 * involve waking or receiving events.
335 */
336
ZTEST(sys_events,test_event_deliver)337 ZTEST(sys_events, test_event_deliver)
338 {
339 uint32_t events;
340
341 k_event_init(&deliver_event);
342
343 zassert_true(deliver_event.events == 0);
344
345 /*
346 * Verify k_event_post() and k_event_set() update the
347 * events stored in the deliver_event object as expected.
348 */
349
350 events = 0xAAAA;
351 k_event_post(&deliver_event, events);
352 zassert_true(deliver_event.events == events);
353
354 events |= 0x55555ABC;
355 k_event_post(&deliver_event, events);
356 zassert_true(deliver_event.events == events);
357
358 events = 0xAAAA0000;
359 k_event_set(&deliver_event, events);
360 zassert_true(deliver_event.events == events);
361 }
362
363 /**
364 * Test delivery and reception of events.
365 *
366 * Testing both the delivery and reception of events involves the use of
367 * multiple threads and uses the following event related APIs:
368 * k_event_post(), k_event_set(), k_event_wait() and k_event_wait_all().
369 */
370
ZTEST(sys_events,test_event_receive)371 ZTEST(sys_events, test_event_receive)
372 {
373
374 /* Create helper threads */
375
376 k_event_set(&test_event, 0x1234);
377
378 (void) k_thread_create(&treceiver, sreceiver, STACK_SIZE,
379 receiver, NULL, NULL, NULL,
380 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
381
382 (void) k_thread_create(&textra1, sextra1, STACK_SIZE,
383 entry_extra1, NULL, NULL, NULL,
384 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
385
386 (void) k_thread_create(&textra2, sextra2, STACK_SIZE,
387 entry_extra2, NULL, NULL, NULL,
388 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
389
390 test_receive_existing_events();
391
392 test_reset_on_receive();
393
394 test_wake_multiple_threads();
395 }
396
sys_events_setup(void)397 void *sys_events_setup(void)
398 {
399 k_thread_access_grant(k_current_get(), &treceiver, &textra1, &textra2,
400 &test_event, &sync_event,
401 &init_event, &deliver_event,
402 &receiver_sem, &sync_sem);
403
404 return NULL;
405 }
406
407 ZTEST_SUITE(sys_events, NULL, sys_events_setup,
408 ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
409