tobudos-kernel/core/tos_event.c

241 lines
6.4 KiB
C

/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
#if TOS_CFG_EVENT_EN > 0
__API__ k_err_t tos_event_create(k_event_t *event, k_event_flag_t init_flag)
{
TOS_PTR_SANITY_CHECK(event);
event->flag = init_flag;
pend_object_init(&event->pend_obj);
TOS_OBJ_INIT(event, KNL_OBJ_TYPE_EVENT);
#if TOS_CFG_OBJ_DYNAMIC_CREATE_EN > 0u
knl_object_alloc_set_static(&event->knl_obj);
#endif
return K_ERR_NONE;
}
__API__ k_err_t tos_event_destroy(k_event_t *event)
{
TOS_CPU_CPSR_ALLOC();
TOS_PTR_SANITY_CHECK(event);
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
#if TOS_CFG_OBJ_DYNAMIC_CREATE_EN > 0u
if (!knl_object_alloc_is_static(&event->knl_obj)) {
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
}
#endif
TOS_CPU_INT_DISABLE();
pend_wakeup_all(&event->pend_obj, PEND_STATE_DESTROY);
event->flag = (k_event_flag_t)0u;
pend_object_deinit(&event->pend_obj);
TOS_OBJ_DEINIT(event);
#if TOS_CFG_OBJ_DYNAMIC_CREATE_EN > 0u
knl_object_alloc_reset(&event->knl_obj);
#endif
TOS_CPU_INT_ENABLE();
knl_sched();
return K_ERR_NONE;
}
#if TOS_CFG_OBJ_DYNAMIC_CREATE_EN > 0u
__API__ k_err_t tos_event_create_dyn(k_event_t **event, k_event_flag_t init_flag)
{
k_event_t *the_event;
TOS_IN_IRQ_CHECK();
TOS_PTR_SANITY_CHECK(event);
the_event = tos_mmheap_calloc(1, sizeof(k_event_t));
if (!the_event) {
return K_ERR_OUT_OF_MEMORY;
}
the_event->flag = init_flag;
pend_object_init(&the_event->pend_obj);
TOS_OBJ_INIT(the_event, KNL_OBJ_TYPE_EVENT);
knl_object_alloc_set_dynamic(&the_event->knl_obj);
*event = the_event;
return K_ERR_NONE;
}
__API__ k_err_t tos_event_destroy_dyn(k_event_t *event)
{
TOS_CPU_CPSR_ALLOC();
TOS_PTR_SANITY_CHECK(event);
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
if (!knl_object_alloc_is_dynamic(&event->knl_obj)) {
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
}
TOS_CPU_INT_DISABLE();
pend_wakeup_all(&event->pend_obj, PEND_STATE_DESTROY);
event->flag = (k_event_flag_t)0u;
pend_object_deinit(&event->pend_obj);
TOS_OBJ_DEINIT(event);
tos_mmheap_free(event);
TOS_CPU_INT_ENABLE();
knl_sched();
return K_ERR_NONE;
}
#endif
__STATIC__ int event_is_match(k_event_flag_t event, k_event_flag_t flag_expect, k_event_flag_t *flag_match, k_opt_t opt_pend)
{
if (opt_pend & TOS_OPT_EVENT_PEND_ALL) {
if ((event & flag_expect) == flag_expect) {
*flag_match = flag_expect;
return K_TRUE;
}
} else if (opt_pend & TOS_OPT_EVENT_PEND_ANY) {
if (event & flag_expect) {
*flag_match = event & flag_expect;
return K_TRUE;
}
}
return K_FALSE;
}
__API__ k_err_t tos_event_pend(k_event_t *event, k_event_flag_t flag_expect, k_event_flag_t *flag_match, k_tick_t timeout, k_opt_t opt_pend)
{
TOS_CPU_CPSR_ALLOC();
TOS_IN_IRQ_CHECK();
TOS_PTR_SANITY_CHECK(event);
TOS_PTR_SANITY_CHECK(flag_match);
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
if (!(opt_pend & TOS_OPT_EVENT_PEND_ALL) && !(opt_pend & TOS_OPT_EVENT_PEND_ANY)) {
return K_ERR_EVENT_PEND_OPT_INVALID;
}
if ((opt_pend & TOS_OPT_EVENT_PEND_ALL) && (opt_pend & TOS_OPT_EVENT_PEND_ANY)) {
return K_ERR_EVENT_PEND_OPT_INVALID;
}
TOS_CPU_INT_DISABLE();
if (event_is_match(event->flag, flag_expect, flag_match, opt_pend)) {
if (opt_pend & TOS_OPT_EVENT_PEND_CLR) { // destroy the bridge after get across the river
event->flag = (k_event_flag_t)0u;
}
TOS_CPU_INT_ENABLE();
return K_ERR_NONE;
}
if (timeout == TOS_TIME_NOWAIT) {
TOS_CPU_INT_ENABLE();
return K_ERR_PEND_NOWAIT;
}
if (knl_is_sched_locked()) {
TOS_CPU_INT_ENABLE();
return K_ERR_PEND_SCHED_LOCKED;
}
k_curr_task->flag_expect = flag_expect;
k_curr_task->flag_match = flag_match;
k_curr_task->opt_event_pend = opt_pend;
pend_task_block(k_curr_task, &event->pend_obj, timeout);
TOS_CPU_INT_ENABLE();
knl_sched();
k_curr_task->flag_expect = (k_event_flag_t)0u;
k_curr_task->flag_match = (k_event_flag_t *)K_NULL;
k_curr_task->opt_event_pend = (k_opt_t)0u;
return pend_state2errno(k_curr_task->pend_state);
}
__STATIC__ k_err_t event_do_post(k_event_t *event, k_event_flag_t flag, opt_event_post_t opt_post)
{
TOS_CPU_CPSR_ALLOC();
k_task_t *task, *tmp;
TOS_PTR_SANITY_CHECK(event);
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
if (opt_post == OPT_EVENT_POST_KEP) {
event->flag |= flag;
} else {
event->flag = flag;
}
TOS_CPU_INT_DISABLE();
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &event->pend_obj.list) {
if (event_is_match(event->flag, task->flag_expect, task->flag_match, task->opt_event_pend)) {
pend_task_wakeup(task, PEND_STATE_POST);
// if anyone pending the event has set the TOS_OPT_EVENT_PEND_CLR, then no wakeup for the others pendig for the event.
if (task->opt_event_pend & TOS_OPT_EVENT_PEND_CLR) {
event->flag = (k_event_flag_t)0u;
break;
}
}
}
TOS_CPU_INT_ENABLE();
knl_sched();
return K_ERR_NONE;
}
__API__ k_err_t tos_event_post(k_event_t *event, k_event_flag_t flag)
{
return event_do_post(event, flag, OPT_EVENT_POST_CLR);
}
__API__ k_err_t tos_event_post_keep(k_event_t *event, k_event_flag_t flag)
{
return event_do_post(event, flag, OPT_EVENT_POST_KEP);
}
#endif