This is necessary in order for k_queue_get to work properly since that is used with buffer pools which might be used by multiple threads asking for buffers. Jira: ZEP-2553 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
360 lines
10 KiB
C
360 lines
10 KiB
C
/*
|
|
* Copyright (c) 2017 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @addtogroup t_poll_api
|
|
* @{
|
|
* @defgroup t_poll_api_basic test_poll_api_basic
|
|
* @brief TestPurpose: verify zephyr poll apis across different context
|
|
* - API coverage
|
|
* -# k_sem_init K_SEMA_DEFINE
|
|
* -# k_sem_take k_sema_give k_sema_reset
|
|
* -# k_sem_count_get
|
|
* @}
|
|
*/
|
|
|
|
#include <ztest.h>
|
|
#include <kernel.h>
|
|
|
|
/* global values and data structures */
|
|
struct fifo_msg {
|
|
void *private;
|
|
u32_t msg;
|
|
};
|
|
|
|
#define SIGNAL_RESULT 0x1ee7d00d
|
|
#define FIFO_MSG_VALUE 0xdeadbeef
|
|
|
|
/* verify k_poll() without waiting */
|
|
static struct k_sem no_wait_sem;
|
|
static struct k_fifo no_wait_fifo;
|
|
static struct k_poll_signal no_wait_signal;
|
|
|
|
void test_poll_no_wait(void)
|
|
{
|
|
struct fifo_msg msg = { NULL, FIFO_MSG_VALUE }, *msg_ptr;
|
|
|
|
k_sem_init(&no_wait_sem, 1, 1);
|
|
k_fifo_init(&no_wait_fifo);
|
|
k_poll_signal_init(&no_wait_signal);
|
|
|
|
struct k_poll_event events[] = {
|
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&no_wait_sem),
|
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&no_wait_fifo),
|
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&no_wait_signal),
|
|
};
|
|
|
|
/* test polling events that are already ready */
|
|
k_fifo_put(&no_wait_fifo, &msg);
|
|
k_poll_signal(&no_wait_signal, SIGNAL_RESULT);
|
|
|
|
zassert_equal(k_poll(events, ARRAY_SIZE(events), 0), 0, "");
|
|
|
|
zassert_equal(events[0].state, K_POLL_STATE_SEM_AVAILABLE, "");
|
|
zassert_equal(k_sem_take(&no_wait_sem, 0), 0, "");
|
|
|
|
zassert_equal(events[1].state, K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
|
|
msg_ptr = k_fifo_get(&no_wait_fifo, 0);
|
|
zassert_not_null(msg_ptr, "");
|
|
zassert_equal(msg_ptr, &msg, "");
|
|
zassert_equal(msg_ptr->msg, FIFO_MSG_VALUE, "");
|
|
|
|
zassert_equal(events[2].state, K_POLL_STATE_SIGNALED, "");
|
|
zassert_equal(no_wait_signal.signaled, 1, "");
|
|
zassert_equal(no_wait_signal.result, SIGNAL_RESULT, "");
|
|
|
|
/* verify events are not ready anymore (user has to clear them first) */
|
|
events[0].state = K_POLL_STATE_NOT_READY;
|
|
events[1].state = K_POLL_STATE_NOT_READY;
|
|
events[2].state = K_POLL_STATE_NOT_READY;
|
|
no_wait_signal.signaled = 0;
|
|
|
|
zassert_equal(k_poll(events, ARRAY_SIZE(events), 0), -EAGAIN, "");
|
|
zassert_equal(events[0].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(events[1].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(events[2].state, K_POLL_STATE_NOT_READY, "");
|
|
|
|
zassert_not_equal(k_sem_take(&no_wait_sem, 0), 0, "");
|
|
zassert_is_null(k_fifo_get(&no_wait_fifo, 0), "");
|
|
}
|
|
|
|
/* verify k_poll() that has to wait */
|
|
|
|
static K_SEM_DEFINE(wait_sem, 0, 1);
|
|
static K_FIFO_DEFINE(wait_fifo);
|
|
static struct k_poll_signal wait_signal =
|
|
K_POLL_SIGNAL_INITIALIZER(wait_signal);
|
|
|
|
struct fifo_msg wait_msg = { NULL, FIFO_MSG_VALUE };
|
|
|
|
static struct k_thread poll_wait_helper_thread;
|
|
static K_THREAD_STACK_DEFINE(poll_wait_helper_stack, KB(1));
|
|
|
|
#define TAG_0 10
|
|
#define TAG_1 11
|
|
#define TAG_2 12
|
|
|
|
struct k_poll_event wait_events[] = {
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&wait_sem, TAG_0),
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&wait_fifo, TAG_1),
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SIGNAL,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&wait_signal, TAG_2),
|
|
};
|
|
|
|
static void poll_wait_helper(void *use_fifo, void *p2, void *p3)
|
|
{
|
|
(void)p2; (void)p3;
|
|
|
|
k_sleep(250);
|
|
|
|
k_sem_give(&wait_sem);
|
|
|
|
if ((intptr_t)use_fifo) {
|
|
k_fifo_put(&wait_fifo, &wait_msg);
|
|
}
|
|
|
|
k_poll_signal(&wait_signal, SIGNAL_RESULT);
|
|
}
|
|
|
|
void test_poll_wait(void)
|
|
{
|
|
const int main_low_prio = 10;
|
|
|
|
struct fifo_msg *msg_ptr;
|
|
int rc;
|
|
|
|
int old_prio = k_thread_priority_get(k_current_get());
|
|
|
|
/*
|
|
* Wait for 3 non-ready events to become ready from a higher priority
|
|
* thread.
|
|
*/
|
|
k_thread_priority_set(k_current_get(), main_low_prio);
|
|
|
|
k_thread_create(&poll_wait_helper_thread, poll_wait_helper_stack,
|
|
K_THREAD_STACK_SIZEOF(poll_wait_helper_stack),
|
|
poll_wait_helper, (void *)1, 0, 0,
|
|
main_low_prio - 1, 0, 0);
|
|
|
|
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
|
|
|
k_thread_priority_set(k_current_get(), old_prio);
|
|
|
|
zassert_equal(rc, 0, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_SEM_AVAILABLE, "");
|
|
zassert_equal(k_sem_take(&wait_sem, 0), 0, "");
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
|
|
zassert_equal(wait_events[1].state,
|
|
K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
|
|
msg_ptr = k_fifo_get(&wait_fifo, 0);
|
|
zassert_not_null(msg_ptr, "");
|
|
zassert_equal(msg_ptr, &wait_msg, "");
|
|
zassert_equal(msg_ptr->msg, FIFO_MSG_VALUE, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_SIGNALED, "");
|
|
zassert_equal(wait_signal.signaled, 1, "");
|
|
zassert_equal(wait_signal.result, SIGNAL_RESULT, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
/* verify events are not ready anymore */
|
|
wait_events[0].state = K_POLL_STATE_NOT_READY;
|
|
wait_events[1].state = K_POLL_STATE_NOT_READY;
|
|
wait_events[2].state = K_POLL_STATE_NOT_READY;
|
|
wait_signal.signaled = 0;
|
|
|
|
zassert_equal(k_poll(wait_events, ARRAY_SIZE(wait_events),
|
|
K_SECONDS(1)), -EAGAIN, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(wait_events[1].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_NOT_READY, "");
|
|
|
|
/* tags should not have been touched */
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
/*
|
|
* Wait for 2 out of 3 non-ready events to become ready from a higher
|
|
* priority thread.
|
|
*/
|
|
k_thread_priority_set(k_current_get(), main_low_prio);
|
|
|
|
k_thread_create(&poll_wait_helper_thread, poll_wait_helper_stack,
|
|
K_THREAD_STACK_SIZEOF(poll_wait_helper_stack),
|
|
poll_wait_helper,
|
|
0, 0, 0, main_low_prio - 1, 0, 0);
|
|
|
|
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
|
|
|
k_thread_priority_set(k_current_get(), old_prio);
|
|
|
|
zassert_equal(rc, 0, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_SEM_AVAILABLE, "");
|
|
zassert_equal(k_sem_take(&wait_sem, 0), 0, "");
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
|
|
zassert_equal(wait_events[1].state, K_POLL_STATE_NOT_READY, "");
|
|
msg_ptr = k_fifo_get(&wait_fifo, K_NO_WAIT);
|
|
zassert_is_null(msg_ptr, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_SIGNALED, "");
|
|
zassert_equal(wait_signal.signaled, 1, "");
|
|
zassert_equal(wait_signal.result, SIGNAL_RESULT, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
/*
|
|
* Wait for each event to be ready from a lower priority thread, one at
|
|
* a time.
|
|
*/
|
|
|
|
wait_events[0].state = K_POLL_STATE_NOT_READY;
|
|
wait_events[1].state = K_POLL_STATE_NOT_READY;
|
|
wait_events[2].state = K_POLL_STATE_NOT_READY;
|
|
wait_signal.signaled = 0;
|
|
|
|
k_thread_create(&poll_wait_helper_thread, poll_wait_helper_stack,
|
|
K_THREAD_STACK_SIZEOF(poll_wait_helper_stack),
|
|
poll_wait_helper,
|
|
(void *)1, 0, 0, old_prio + 1, 0, 0);
|
|
|
|
/* semaphore */
|
|
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
|
|
|
zassert_equal(rc, 0, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_SEM_AVAILABLE, "");
|
|
zassert_equal(k_sem_take(&wait_sem, 0), 0, "");
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
|
|
zassert_equal(wait_events[1].state, K_POLL_STATE_NOT_READY, "");
|
|
msg_ptr = k_fifo_get(&wait_fifo, K_NO_WAIT);
|
|
zassert_is_null(msg_ptr, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
wait_events[0].state = K_POLL_STATE_NOT_READY;
|
|
|
|
/* fifo */
|
|
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
|
|
|
zassert_equal(rc, 0, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(k_sem_take(&wait_sem, 0), -EBUSY, "");
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
|
|
zassert_equal(wait_events[1].state,
|
|
K_POLL_STATE_FIFO_DATA_AVAILABLE, "");
|
|
msg_ptr = k_fifo_get(&wait_fifo, K_NO_WAIT);
|
|
zassert_not_null(msg_ptr, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
wait_events[1].state = K_POLL_STATE_NOT_READY;
|
|
|
|
/* poll signal */
|
|
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
|
|
|
zassert_equal(rc, 0, "");
|
|
|
|
zassert_equal(wait_events[0].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(k_sem_take(&wait_sem, 0), -EBUSY, "");
|
|
zassert_equal(wait_events[0].tag, TAG_0, "");
|
|
|
|
zassert_equal(wait_events[1].state, K_POLL_STATE_NOT_READY, "");
|
|
msg_ptr = k_fifo_get(&wait_fifo, K_NO_WAIT);
|
|
zassert_is_null(msg_ptr, "");
|
|
zassert_equal(wait_events[1].tag, TAG_1, "");
|
|
|
|
zassert_equal(wait_events[2].state, K_POLL_STATE_SIGNALED, "");
|
|
zassert_equal(wait_signal.signaled, 1, "");
|
|
zassert_equal(wait_signal.result, SIGNAL_RESULT, "");
|
|
zassert_equal(wait_events[2].tag, TAG_2, "");
|
|
|
|
wait_events[2].state = K_POLL_STATE_NOT_READY;
|
|
wait_signal.signaled = 0;
|
|
}
|
|
|
|
/* verify multiple pollers */
|
|
static K_SEM_DEFINE(multi_sem, 0, 1);
|
|
static K_SEM_DEFINE(multi_reply, 0, 1);
|
|
|
|
static struct k_thread multi_thread;
|
|
static K_THREAD_STACK_DEFINE(multi_stack, KB(1));
|
|
|
|
static void multi(void *p1, void *p2, void *p3)
|
|
{
|
|
(void)p1; (void)p2; (void)p3;
|
|
|
|
struct k_poll_event event;
|
|
|
|
k_poll_event_init(&event, K_POLL_TYPE_SEM_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY, &multi_sem);
|
|
|
|
(void)k_poll(&event, 1, K_FOREVER);
|
|
k_sem_take(&multi_sem, K_FOREVER);
|
|
k_sem_give(&multi_reply);
|
|
}
|
|
|
|
static K_SEM_DEFINE(multi_ready_sem, 1, 1);
|
|
|
|
void test_poll_multi(void)
|
|
{
|
|
int old_prio = k_thread_priority_get(k_current_get());
|
|
const int main_low_prio = 10;
|
|
int rc;
|
|
|
|
struct k_poll_event events[] = {
|
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&multi_sem),
|
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
&multi_ready_sem),
|
|
};
|
|
|
|
k_thread_priority_set(k_current_get(), main_low_prio);
|
|
|
|
k_thread_create(&multi_thread, multi_stack,
|
|
K_THREAD_STACK_SIZEOF(multi_stack),
|
|
multi, 0, 0, 0, main_low_prio - 1, 0, 0);
|
|
|
|
rc = k_poll(events, ARRAY_SIZE(events), K_SECONDS(1));
|
|
|
|
k_thread_priority_set(k_current_get(), old_prio);
|
|
|
|
zassert_equal(rc, 0, "");
|
|
zassert_equal(events[0].state, K_POLL_STATE_NOT_READY, "");
|
|
zassert_equal(events[1].state, K_POLL_STATE_SEM_AVAILABLE, "");
|
|
|
|
/* free multi, ensuring it awoken from k_poll() and got the sem */
|
|
k_sem_give(&multi_sem);
|
|
rc = k_sem_take(&multi_reply, K_SECONDS(1));
|
|
|
|
zassert_equal(rc, 0, "");
|
|
}
|