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