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