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