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