1 /*
2 * Copyright (c) 2017 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9
10 /* global values and data structures */
11 struct fifo_msg {
12 void *private;
13 uint32_t msg;
14 };
15
16 #define SIGNAL_RESULT 0x1ee7d00d
17 #define FIFO_MSG_VALUE 0xdeadbeef
18 #define MSGQ_MSG_SIZE 4
19 #define MSGQ_MAX_MSGS 16
20 #define MSGQ_MSG_VALUE {'a', 'b', 'c', 'd'}
21 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
22
23 /* verify k_poll() without waiting */
24 static struct k_sem no_wait_sem;
25 static struct k_fifo no_wait_fifo;
26 static struct k_poll_signal no_wait_signal;
27 static struct k_poll_signal test_signal;
28 #ifndef CONFIG_USERSPACE
29 static struct k_msgq no_wait_msgq;
30 #endif
31 static struct k_sem zero_events_sem;
32 static struct k_thread test_thread;
33 static struct k_thread test_loprio_thread;
34 K_THREAD_STACK_DEFINE(test_stack, STACK_SIZE);
35 K_THREAD_STACK_DEFINE(test_loprio_stack, STACK_SIZE);
36 K_MSGQ_DEFINE(msgq_high_prio_thread, sizeof(unsigned int), 4, 4);
37 static K_THREAD_STACK_DEFINE(high_prio_stack_area, 4096);
38 static struct k_thread high_prio_data;
39 static volatile bool wake_up_by_poll = true;
40
41 /**
42 * @brief Test cases to verify poll
43 *
44 * @defgroup kernel_poll_tests Poll tests
45 *
46 * @ingroup all_tests
47 *
48 * @{
49 * @}
50 */
51
52 /**
53 * @brief Test poll events with no wait
54 *
55 * @ingroup kernel_poll_tests
56 *
57 * @see K_POLL_EVENT_INITIALIZER(), k_poll_signal_init(),
58 * k_poll_signal_raise(), k_poll_signal_check()
59 */
ZTEST_USER(poll_api_1cpu,test_poll_no_wait)60 ZTEST_USER(poll_api_1cpu, test_poll_no_wait)
61 {
62 struct fifo_msg msg = { NULL, FIFO_MSG_VALUE }, *msg_ptr;
63 unsigned int signaled;
64 char msgq_recv_buf[MSGQ_MSG_SIZE] = {0};
65 char msgq_msg[MSGQ_MSG_SIZE] = MSGQ_MSG_VALUE;
66 int result;
67 struct k_msgq *mq;
68 #ifdef CONFIG_USERSPACE
69 mq = k_object_alloc(K_OBJ_MSGQ);
70 zassert_not_null(mq, "");
71 #else
72 mq = &no_wait_msgq;
73 #endif
74
75 k_sem_init(&no_wait_sem, 1, 1);
76 k_fifo_init(&no_wait_fifo);
77 k_poll_signal_init(&no_wait_signal);
78
79 k_msgq_alloc_init(mq, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
80
81 struct k_poll_event events[] = {
82 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
83 K_POLL_MODE_NOTIFY_ONLY,
84 &no_wait_sem),
85 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
86 K_POLL_MODE_NOTIFY_ONLY,
87 &no_wait_fifo),
88 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
89 K_POLL_MODE_NOTIFY_ONLY,
90 &no_wait_signal),
91 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_IGNORE,
92 K_POLL_MODE_NOTIFY_ONLY,
93 NULL),
94 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
95 K_POLL_MODE_NOTIFY_ONLY,
96 mq),
97 };
98
99 #ifdef CONFIG_USERSPACE
100 /* Test that k_poll() syscall handler safely handles being
101 * fed garbage
102 *
103 * TODO: Where possible migrate these to the main k_poll()
104 * implementation
105 */
106
107 zassert_equal(k_poll(events, INT_MAX, K_NO_WAIT), -EINVAL);
108 zassert_equal(k_poll(events, 4096, K_NO_WAIT), -ENOMEM);
109
110 /* Allow zero events */
111 zassert_equal(k_poll(events, 0, K_NO_WAIT), -EAGAIN);
112
113 struct k_poll_event bad_events[] = {
114 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
115 K_POLL_NUM_MODES,
116 &no_wait_sem),
117 };
118 zassert_equal(k_poll(bad_events, ARRAY_SIZE(bad_events), K_NO_WAIT),
119 -EINVAL,
120 NULL);
121
122 /* can't use the initializer to misconstruct this */
123 struct k_poll_event bad_events2[] = {
124 { .type = 0xFU,
125 .state = K_POLL_STATE_NOT_READY,
126 .mode = K_POLL_MODE_NOTIFY_ONLY,
127 .obj = &no_wait_sem,
128 },
129 };
130 zassert_equal(k_poll(bad_events2, ARRAY_SIZE(bad_events), K_NO_WAIT),
131 -EINVAL,
132 NULL);
133 #endif /* CONFIG_USERSPACE */
134
135 /* test polling events that are already ready */
136 zassert_false(k_fifo_alloc_put(&no_wait_fifo, &msg));
137 k_poll_signal_raise(&no_wait_signal, SIGNAL_RESULT);
138 zassert_false(k_msgq_put(mq, msgq_msg, K_NO_WAIT));
139
140 zassert_equal(k_poll(events, ARRAY_SIZE(events), K_NO_WAIT), 0, "");
141
142 zassert_equal(events[0].state, K_POLL_STATE_SEM_AVAILABLE, "");
143 zassert_equal(k_sem_take(&no_wait_sem, K_NO_WAIT), 0, "");
144
145 zassert_equal(events[1].state, K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
146 msg_ptr = k_fifo_get(&no_wait_fifo, K_NO_WAIT);
147 zassert_not_null(msg_ptr, "");
148 zassert_equal(msg_ptr, &msg, "");
149 zassert_equal(msg_ptr->msg, FIFO_MSG_VALUE, "");
150
151 zassert_equal(events[2].state, K_POLL_STATE_SIGNALED, "");
152 k_poll_signal_check(&no_wait_signal, &signaled, &result);
153 zassert_not_equal(signaled, 0, "");
154 zassert_equal(result, SIGNAL_RESULT, "");
155
156 zassert_equal(events[3].state, K_POLL_STATE_NOT_READY, "");
157
158 zassert_equal(events[4].state, K_POLL_STATE_MSGQ_DATA_AVAILABLE, "");
159 zassert_false(k_msgq_get(mq, msgq_recv_buf, K_NO_WAIT));
160 zassert_false(memcmp(msgq_msg, msgq_recv_buf, MSGQ_MSG_SIZE), "");
161
162 /* verify events are not ready anymore (user has to clear them first) */
163 events[0].state = K_POLL_STATE_NOT_READY;
164 events[1].state = K_POLL_STATE_NOT_READY;
165 events[2].state = K_POLL_STATE_NOT_READY;
166 events[3].state = K_POLL_STATE_NOT_READY;
167 events[4].state = K_POLL_STATE_NOT_READY;
168 k_poll_signal_reset(&no_wait_signal);
169
170 zassert_equal(k_poll(events, ARRAY_SIZE(events), K_NO_WAIT), -EAGAIN,
171 "");
172 zassert_equal(events[0].state, K_POLL_STATE_NOT_READY, "");
173 zassert_equal(events[1].state, K_POLL_STATE_NOT_READY, "");
174 zassert_equal(events[2].state, K_POLL_STATE_NOT_READY, "");
175 zassert_equal(events[3].state, K_POLL_STATE_NOT_READY, "");
176 zassert_equal(events[4].state, K_POLL_STATE_NOT_READY, "");
177
178 zassert_not_equal(k_sem_take(&no_wait_sem, K_NO_WAIT), 0, "");
179 zassert_is_null(k_fifo_get(&no_wait_fifo, K_NO_WAIT), "");
180 zassert_not_equal(k_msgq_get(mq, msgq_recv_buf, K_NO_WAIT), 0,
181 "");
182 }
183
184 /* verify k_poll() that has to wait */
185 static struct k_msgq wait_msgq;
186 static struct k_msgq *wait_msgq_ptr;
187
188 static K_SEM_DEFINE(wait_sem, 0, 1);
189 static K_FIFO_DEFINE(wait_fifo);
190 static struct k_poll_signal wait_signal =
191 K_POLL_SIGNAL_INITIALIZER(wait_signal);
192
193 struct fifo_msg wait_msg = { NULL, FIFO_MSG_VALUE };
194
195 #define TAG_0 10
196 #define TAG_1 11
197 #define TAG_2 12
198 #define TAG_3 13
199
200 struct k_poll_event wait_events[] = {
201 K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
202 K_POLL_MODE_NOTIFY_ONLY,
203 &wait_sem, TAG_0),
204 K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
205 K_POLL_MODE_NOTIFY_ONLY,
206 &wait_fifo, TAG_1),
207 K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SIGNAL,
208 K_POLL_MODE_NOTIFY_ONLY,
209 &wait_signal, TAG_2),
210 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_IGNORE,
211 K_POLL_MODE_NOTIFY_ONLY,
212 NULL),
213 K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
214 K_POLL_MODE_NOTIFY_ONLY,
215 &wait_msgq, TAG_3),
216 };
217
218 #define USE_FIFO (1 << 0)
219 #define USE_MSGQ (1 << 1)
220
poll_wait_helper(void * use_queuelike,void * msgq,void * p3)221 static void poll_wait_helper(void *use_queuelike, void *msgq, void *p3)
222 {
223 (void)p3;
224
225 k_sleep(K_MSEC(250));
226
227 k_sem_give(&wait_sem);
228
229 uintptr_t flags = (uintptr_t)use_queuelike;
230
231 if (flags & USE_FIFO) {
232 k_fifo_alloc_put(&wait_fifo, &wait_msg);
233 }
234
235 k_poll_signal_raise(&wait_signal, SIGNAL_RESULT);
236
237 if (flags & USE_MSGQ) {
238 char m[] = MSGQ_MSG_VALUE;
239
240 k_msgq_put(msgq, &m[0], K_FOREVER);
241 }
242 }
243
244 /* check results for multiple events */
check_results(struct k_poll_event * events,uint32_t event_type,bool is_available)245 void check_results(struct k_poll_event *events, uint32_t event_type,
246 bool is_available)
247 {
248 struct fifo_msg *msg_ptr;
249 char msgq_recv_buf[MSGQ_MSG_SIZE] = {0};
250 char msg[] = MSGQ_MSG_VALUE;
251
252 switch (event_type) {
253 case K_POLL_TYPE_SEM_AVAILABLE:
254 if (is_available) {
255 zassert_equal(events->state, K_POLL_STATE_SEM_AVAILABLE,
256 "");
257 zassert_equal(k_sem_take(&wait_sem, K_NO_WAIT), 0, "");
258 zassert_equal(events->tag, TAG_0, "");
259 /* reset to not ready */
260 events->state = K_POLL_STATE_NOT_READY;
261 } else {
262 zassert_equal(events->state, K_POLL_STATE_NOT_READY,
263 "");
264 zassert_equal(k_sem_take(&wait_sem, K_NO_WAIT), -EBUSY,
265 "");
266 zassert_equal(events->tag, TAG_0, "");
267 }
268 break;
269 case K_POLL_TYPE_DATA_AVAILABLE:
270 if (is_available) {
271 zassert_equal(events->state,
272 K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
273 msg_ptr = k_fifo_get(&wait_fifo, K_NO_WAIT);
274 zassert_not_null(msg_ptr, "");
275 zassert_equal(msg_ptr, &wait_msg, "");
276 zassert_equal(msg_ptr->msg, FIFO_MSG_VALUE, "");
277 zassert_equal(events->tag, TAG_1, "");
278 /* reset to not ready */
279 events->state = K_POLL_STATE_NOT_READY;
280 } else {
281 zassert_equal(events->state, K_POLL_STATE_NOT_READY,
282 "");
283 }
284 break;
285 case K_POLL_TYPE_SIGNAL:
286 if (is_available) {
287 zassert_equal(wait_events[2].state,
288 K_POLL_STATE_SIGNALED, "");
289 zassert_equal(wait_signal.signaled, 1, "");
290 zassert_equal(wait_signal.result, SIGNAL_RESULT, "");
291 zassert_equal(wait_events[2].tag, TAG_2, "");
292 /* reset to not ready */
293 events->state = K_POLL_STATE_NOT_READY;
294 wait_signal.signaled = 0U;
295 } else {
296 zassert_equal(events->state, K_POLL_STATE_NOT_READY,
297 "");
298 }
299 break;
300 case K_POLL_TYPE_IGNORE:
301 zassert_equal(wait_events[3].state, K_POLL_STATE_NOT_READY, "");
302 break;
303 case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
304 if (is_available) {
305 zassert_equal(events->state,
306 K_POLL_STATE_MSGQ_DATA_AVAILABLE, "");
307
308 zassert_false(k_msgq_get(wait_msgq_ptr, msgq_recv_buf,
309 K_NO_WAIT), "");
310 zassert_false(memcmp(msg, msgq_recv_buf,
311 MSGQ_MSG_SIZE), "");
312 zassert_equal(events->tag, TAG_3, "");
313 /* reset to not ready */
314 events->state = K_POLL_STATE_NOT_READY;
315 } else {
316 zassert_equal(events->state, K_POLL_STATE_NOT_READY,
317 "");
318 }
319 break;
320
321 default:
322 __ASSERT(false, "invalid event type (0x%x)\n", event_type);
323 break;
324 }
325 }
326
327 /**
328 * @brief Test polling with wait
329 *
330 * @ingroup kernel_poll_tests
331 *
332 * @details
333 * Test Objective:
334 * - Test the poll operation which enables waiting concurrently
335 * for one/two/all conditions to be fulfilled.
336 * - set a single timeout argument indicating
337 * the maximum amount of time a thread shall wait.
338 *
339 * Testing techniques:
340 * - function and block box testing.
341 * - Interface testing.
342 * - Dynamic analysis and testing.
343 *
344 * Prerequisite Conditions:
345 * - CONFIG_TEST_USERSPACE
346 * - CONFIG_DYNAMIC_OBJECTS
347 * - CONFIG_POLL
348 *
349 * Input Specifications:
350 * - N/A
351 *
352 * Test Procedure:
353 * -# Use FIFO/semaphore/signal/message queue object to define poll event.
354 * -# Initialize the FIFO/semaphore/signal/message queue object.
355 * -# Create a thread to put FIFO,
356 * give semaphore, raise signal, and put message queue.
357 * -# Check the result when signal is raised,
358 * semaphore is given, fifo is filled, and message is received.
359 * -# Check the result when no event is satisfied.
360 * -# Check the result when only semaphore is given.
361 * -# Check the result when only FIFO is filled.
362 * -# Check the result when only signal is raised.
363 * -# Check the result when only message is received.
364 *
365 * Expected Test Result:
366 * - FIFO/semaphore/signal/message queue events available/waitable in poll.
367 *
368 * Pass/Fail Criteria:
369 * - Successful if check points in test procedure are all passed, otherwise failure.
370 *
371 * Assumptions and Constraints:
372 * - N/A
373 *
374 * @see k_poll_signal_init(), k_poll()
375 */
ZTEST(poll_api_1cpu,test_poll_wait)376 ZTEST(poll_api_1cpu, test_poll_wait)
377 {
378 const int main_low_prio = 10;
379
380 #ifdef CONFIG_USERSPACE
381 wait_msgq_ptr = k_object_alloc(K_OBJ_MSGQ);
382 k_msgq_alloc_init(wait_msgq_ptr, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
383
384 k_poll_event_init(&wait_events[4],
385 K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
386 K_POLL_MODE_NOTIFY_ONLY,
387 wait_msgq_ptr);
388 wait_events[4].tag = TAG_3;
389 #else
390 wait_msgq_ptr = &wait_msgq;
391 k_msgq_alloc_init(wait_msgq_ptr, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
392 #endif
393 int rc;
394
395 int old_prio = k_thread_priority_get(k_current_get());
396
397 k_poll_signal_init(&wait_signal);
398 /*
399 * Wait for 4 non-ready events to become ready from a higher priority
400 * thread.
401 */
402 k_thread_priority_set(k_current_get(), main_low_prio);
403
404 k_tid_t tid1 = k_thread_create(&test_thread, test_stack,
405 K_THREAD_STACK_SIZEOF(test_stack),
406 poll_wait_helper, (void *)(USE_FIFO | USE_MSGQ), wait_msgq_ptr, 0,
407 main_low_prio - 1, K_USER | K_INHERIT_PERMS,
408 K_NO_WAIT);
409
410 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_NO_WAIT);
411 zassert_equal(rc, -EAGAIN, "should return EAGAIN with K_NO_WAIT");
412
413 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
414
415 k_thread_priority_set(k_current_get(), old_prio);
416
417 zassert_equal(rc, 0, "");
418 /* all events should be available. */
419
420 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
421 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, true);
422 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
423 check_results(&wait_events[3], K_POLL_TYPE_IGNORE, true);
424 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, true);
425
426 /* verify events are not ready anymore */
427 zassert_equal(k_poll(wait_events, ARRAY_SIZE(wait_events),
428 K_SECONDS(1)), -EAGAIN, "");
429 /* all events should not be available. */
430
431 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
432 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
433 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
434 check_results(&wait_events[3], K_POLL_TYPE_IGNORE, false);
435 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
436
437 /*
438 * Wait for 2 out of 4 non-ready events to become ready from a higher
439 * priority thread.
440 */
441 k_thread_priority_set(k_current_get(), main_low_prio);
442
443 k_tid_t tid2 = k_thread_create(&test_thread, test_stack,
444 K_THREAD_STACK_SIZEOF(test_stack),
445 poll_wait_helper,
446 0, 0, 0, main_low_prio - 1, 0, K_NO_WAIT);
447
448 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
449
450 k_thread_priority_set(k_current_get(), old_prio);
451
452 zassert_equal(rc, 0, "");
453
454 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
455 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
456 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
457 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
458
459 /*
460 * Wait for each event to be ready from a lower priority thread, one at
461 * a time.
462 */
463 k_tid_t tid3 = k_thread_create(&test_thread, test_stack,
464 K_THREAD_STACK_SIZEOF(test_stack),
465 poll_wait_helper,
466 (void *)(USE_FIFO | USE_MSGQ), wait_msgq_ptr, 0, old_prio + 1,
467 K_USER | K_INHERIT_PERMS, K_NO_WAIT);
468 /* semaphore */
469 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
470 zassert_equal(rc, 0, "");
471
472 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
473 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
474 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
475 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
476
477 /* fifo */
478 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
479
480 zassert_equal(rc, 0, "");
481
482 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
483 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, true);
484 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
485 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
486
487 /* poll signal */
488 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
489
490 zassert_equal(rc, 0, "");
491
492 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
493 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
494 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
495 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
496
497 /* message queue */
498 rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
499
500 zassert_equal(rc, 0, "");
501
502 check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
503 check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
504 check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
505 check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, true);
506
507 k_thread_abort(tid1);
508 k_thread_abort(tid2);
509 k_thread_abort(tid3);
510 }
511
512 /* verify k_poll() that waits on object which gets cancellation */
513
514 static struct k_fifo cancel_fifo;
515 static struct k_fifo non_cancel_fifo;
516
poll_cancel_helper(void * p1,void * p2,void * p3)517 static void poll_cancel_helper(void *p1, void *p2, void *p3)
518 {
519 (void)p1; (void)p2; (void)p3;
520
521 static struct fifo_msg msg;
522
523 k_sleep(K_MSEC(100));
524
525 k_fifo_cancel_wait(&cancel_fifo);
526
527 k_fifo_alloc_put(&non_cancel_fifo, &msg);
528 }
529
530 /**
531 * @brief Test polling of cancelled fifo
532 *
533 * @details Test the FIFO(queue) data available/cancelable events
534 * as events in poll.
535 *
536 * @ingroup kernel_poll_tests
537 *
538 * @see k_poll(), k_fifo_cancel_wait(), k_fifo_alloc_put
539 */
test_poll_cancel(bool is_main_low_prio)540 void test_poll_cancel(bool is_main_low_prio)
541 {
542 const int main_low_prio = 10;
543 int old_prio = k_thread_priority_get(k_current_get());
544 int rc;
545
546 struct k_poll_event cancel_events[] = {
547 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
548 K_POLL_MODE_NOTIFY_ONLY,
549 &cancel_fifo),
550 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
551 K_POLL_MODE_NOTIFY_ONLY,
552 &non_cancel_fifo),
553 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_IGNORE,
554 K_POLL_MODE_NOTIFY_ONLY,
555 NULL),
556 };
557
558 k_fifo_init(&cancel_fifo);
559 k_fifo_init(&non_cancel_fifo);
560
561 if (is_main_low_prio) {
562 k_thread_priority_set(k_current_get(), main_low_prio);
563 }
564
565 k_tid_t tid = k_thread_create(&test_thread, test_stack,
566 K_THREAD_STACK_SIZEOF(test_stack),
567 poll_cancel_helper, (void *)1, 0, 0,
568 main_low_prio - 1, K_USER | K_INHERIT_PERMS,
569 K_NO_WAIT);
570
571 rc = k_poll(cancel_events, ARRAY_SIZE(cancel_events), K_SECONDS(1));
572
573 k_thread_priority_set(k_current_get(), old_prio);
574
575 zassert_equal(rc, -EINTR, "");
576
577 zassert_equal(cancel_events[0].state,
578 K_POLL_STATE_CANCELLED, "");
579
580 if (is_main_low_prio) {
581 /* If poller thread is lower priority than threads which
582 * generate poll events, it may get multiple poll events
583 * at once.
584 */
585 zassert_equal(cancel_events[1].state,
586 K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
587 } else {
588 /* Otherwise, poller thread will be woken up on first
589 * event triggered.
590 */
591 zassert_equal(cancel_events[1].state,
592 K_POLL_STATE_NOT_READY, "");
593 }
594
595 k_thread_abort(tid);
596 }
597
ZTEST(poll_api_1cpu,test_poll_cancel_main_low_prio)598 ZTEST(poll_api_1cpu, test_poll_cancel_main_low_prio)
599 {
600 test_poll_cancel(true);
601 }
602
ZTEST(poll_api_1cpu,test_poll_cancel_main_high_prio)603 ZTEST(poll_api_1cpu, test_poll_cancel_main_high_prio)
604 {
605 test_poll_cancel(false);
606 }
607
608 /* verify multiple pollers */
609 static K_SEM_DEFINE(multi_sem, 0, 1);
610
multi_lowprio(void * p1,void * p2,void * p3)611 static void multi_lowprio(void *p1, void *p2, void *p3)
612 {
613 (void)p1; (void)p2; (void)p3;
614
615 struct k_poll_event event;
616 int rc;
617
618 k_poll_event_init(&event, K_POLL_TYPE_SEM_AVAILABLE,
619 K_POLL_MODE_NOTIFY_ONLY, &multi_sem);
620
621 (void)k_poll(&event, 1, K_FOREVER);
622 rc = k_sem_take(&multi_sem, K_FOREVER);
623 zassert_equal(rc, 0, "");
624 }
625
626 static K_SEM_DEFINE(multi_reply, 0, 1);
627
multi(void * p1,void * p2,void * p3)628 static void multi(void *p1, void *p2, void *p3)
629 {
630 (void)p1; (void)p2; (void)p3;
631
632 struct k_poll_event event;
633
634 k_poll_event_init(&event, K_POLL_TYPE_SEM_AVAILABLE,
635 K_POLL_MODE_NOTIFY_ONLY, &multi_sem);
636
637 (void)k_poll(&event, 1, K_FOREVER);
638 k_sem_take(&multi_sem, K_FOREVER);
639 k_sem_give(&multi_reply);
640 }
641
642 static K_SEM_DEFINE(multi_ready_sem, 1, 1);
643
644 /**
645 * @brief Test polling of multiple events
646 *
647 * @details
648 * - Test the multiple semaphore events as waitable events in poll.
649 *
650 * @ingroup kernel_poll_tests
651 *
652 * @see K_POLL_EVENT_INITIALIZER(), k_poll(), k_poll_event_init()
653 */
ZTEST(poll_api,test_poll_multi)654 ZTEST(poll_api, test_poll_multi)
655 {
656 int old_prio = k_thread_priority_get(k_current_get());
657 const int main_low_prio = 10;
658 int rc;
659
660 struct k_poll_event events[] = {
661 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
662 K_POLL_MODE_NOTIFY_ONLY,
663 &multi_sem),
664 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
665 K_POLL_MODE_NOTIFY_ONLY,
666 &multi_ready_sem),
667 };
668
669 k_thread_priority_set(k_current_get(), main_low_prio);
670
671 k_tid_t tid1 = k_thread_create(&test_thread, test_stack,
672 K_THREAD_STACK_SIZEOF(test_stack),
673 multi, 0, 0, 0, main_low_prio - 1,
674 K_USER | K_INHERIT_PERMS, K_NO_WAIT);
675
676 /*
677 * create additional thread to add multiple(more than one)
678 * pending threads in events list to improve code coverage.
679 */
680 k_tid_t tid2 = k_thread_create(&test_loprio_thread, test_loprio_stack,
681 K_THREAD_STACK_SIZEOF(test_loprio_stack),
682 multi_lowprio, 0, 0, 0, main_low_prio + 1,
683 K_USER | K_INHERIT_PERMS, K_NO_WAIT);
684
685 /* Allow lower priority thread to add poll event in the list */
686 k_sleep(K_MSEC(250));
687 rc = k_poll(events, ARRAY_SIZE(events), K_SECONDS(1));
688
689 zassert_equal(rc, 0, "");
690 zassert_equal(events[0].state, K_POLL_STATE_NOT_READY, "");
691 zassert_equal(events[1].state, K_POLL_STATE_SEM_AVAILABLE, "");
692
693 /*
694 * free polling threads, ensuring it awoken from k_poll()
695 * and got the sem
696 */
697 k_sem_give(&multi_sem);
698 k_sem_give(&multi_sem);
699 rc = k_sem_take(&multi_reply, K_SECONDS(1));
700
701 zassert_equal(rc, 0, "");
702
703 /* wait for polling threads to complete execution */
704 k_thread_priority_set(k_current_get(), old_prio);
705 k_sleep(K_MSEC(250));
706
707 k_thread_abort(tid1);
708 k_thread_abort(tid2);
709 }
710
711 static struct k_poll_signal signal;
712
threadstate(void * p1,void * p2,void * p3)713 static void threadstate(void *p1, void *p2, void *p3)
714 {
715 (void)p2; (void)p3;
716
717 k_sleep(K_MSEC(250));
718 /* Update polling thread state explicitly to improve code coverage */
719 k_thread_suspend(p1);
720 /* Enable polling thread by signalling */
721 k_poll_signal_raise(&signal, SIGNAL_RESULT);
722 k_thread_resume(p1);
723 }
724
725 /**
726 * @brief Test polling of events by manipulating polling thread state
727 *
728 * @details
729 * - manipulating thread state to consider case where no polling thread
730 * is available during event signalling.
731 * - defined a signal poll as waitable events in poll and
732 * verify the result after signal raised
733 *
734 * @ingroup kernel_poll_tests
735 *
736 * @see K_POLL_EVENT_INITIALIZER(), k_poll(), k_poll_signal_init(),
737 * k_poll_signal_check(), k_poll_signal_raise()
738 */
ZTEST(poll_api_1cpu,test_poll_threadstate)739 ZTEST(poll_api_1cpu, test_poll_threadstate)
740 {
741 unsigned int signaled;
742 const int main_low_prio = 10;
743 int result;
744
745 k_poll_signal_init(&signal);
746
747 struct k_poll_event event;
748
749 k_poll_event_init(&event, K_POLL_TYPE_SIGNAL,
750 K_POLL_MODE_NOTIFY_ONLY, &signal);
751
752 int old_prio = k_thread_priority_get(k_current_get());
753
754 k_thread_priority_set(k_current_get(), main_low_prio);
755 k_tid_t ztest_tid = k_current_get();
756
757 k_tid_t tid = k_thread_create(&test_thread, test_stack,
758 K_THREAD_STACK_SIZEOF(test_stack), threadstate,
759 ztest_tid, 0, 0, main_low_prio - 1, K_INHERIT_PERMS,
760 K_NO_WAIT);
761
762 /* wait for spawn thread to take action */
763 zassert_equal(k_poll(&event, 1, K_SECONDS(1)), 0, "");
764 zassert_equal(event.state, K_POLL_STATE_SIGNALED, "");
765 k_poll_signal_check(&signal, &signaled, &result);
766 zassert_not_equal(signaled, 0, "");
767 zassert_equal(result, SIGNAL_RESULT, "");
768
769 event.state = K_POLL_STATE_NOT_READY;
770 k_poll_signal_reset(&signal);
771 /* teardown */
772 k_thread_priority_set(k_current_get(), old_prio);
773
774 k_thread_abort(tid);
775 }
776
poll_test_grant_access(void)777 void poll_test_grant_access(void)
778 {
779 k_thread_access_grant(k_current_get(), &no_wait_sem, &no_wait_fifo,
780 &no_wait_signal, &wait_sem, &wait_fifo,
781 &cancel_fifo, &non_cancel_fifo,
782 &wait_signal, &test_thread, &test_signal,
783 &test_stack, &multi_sem, &multi_reply);
784 }
785
786
high_prio_main(void * param1,void * param2,void * param3)787 static void high_prio_main(void *param1, void *param2, void *param3)
788 {
789 static struct k_poll_event poll_events[1];
790
791 /* Setup wake-up for message queue */
792 k_poll_event_init(&poll_events[0], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY,
793 &msgq_high_prio_thread);
794 (void)k_poll(poll_events, 1, K_FOREVER);
795
796 zassert_equal(poll_events[0].state, K_POLL_STATE_MSGQ_DATA_AVAILABLE);
797 zassert_equal(wake_up_by_poll, true);
798 }
799
ZTEST(poll_api_1cpu,test_poll_msgq)800 ZTEST(poll_api_1cpu, test_poll_msgq)
801 {
802 int low_prio_thread_priority = 1;
803 int high_prio_thread_priority = -2;
804 unsigned int data_to_high_prio = 0x1234;
805
806 k_thread_priority_set(k_current_get(), low_prio_thread_priority);
807
808 /* Create high priority thread */
809 (void)k_thread_create(&high_prio_data, high_prio_stack_area,
810 K_THREAD_STACK_SIZEOF(high_prio_stack_area), high_prio_main, NULL,
811 NULL, NULL, high_prio_thread_priority, 0, K_NO_WAIT);
812 k_sleep(K_MSEC(1));
813 /* Send message to high-priority thread */
814 (void)k_msgq_put(&msgq_high_prio_thread, &data_to_high_prio, K_NO_WAIT);
815
816 /* low priority thread should not execute here before wake up high priority task */
817 wake_up_by_poll = false;
818 }
819
ZTEST(poll_api_1cpu,test_poll_zero_events)820 ZTEST(poll_api_1cpu, test_poll_zero_events)
821 {
822 struct k_poll_event event;
823
824 k_sem_init(&zero_events_sem, 1, 1);
825
826 k_poll_event_init(&event, K_POLL_TYPE_SEM_AVAILABLE,
827 K_POLL_MODE_NOTIFY_ONLY, &zero_events_sem);
828
829 zassert_equal(k_poll(&event, 0, K_MSEC(50)), -EAGAIN);
830 }
831