feat(wait): New wait function added.
1.The wait module is used to complete the interrupt notification of the upper-level sub-module (this wait module only implements the notification function, facilitating the upper-level to replace different asynchronous implementations).
This commit is contained in:
@@ -83,4 +83,11 @@ config MR_USE_IRQ_DEFER_HOOK
|
||||
bool "Use irq defer hook"
|
||||
default n
|
||||
|
||||
# ==================================
|
||||
# WAIT
|
||||
# ==================================
|
||||
config MR_USE_WAIT
|
||||
bool "Use irq"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -87,8 +87,8 @@ typedef struct mr_irq_action {
|
||||
/* Irq descriptor type */
|
||||
typedef struct mr_irq_desc {
|
||||
mr_irq_action_t *action;
|
||||
mr_uint32_t priority;
|
||||
mr_uint32_t flags;
|
||||
mr_uint16_t priority;
|
||||
mr_uint16_t flags;
|
||||
mr_atomic_t depth;
|
||||
mr_irq_t *irq;
|
||||
} mr_irq_desc_t;
|
||||
@@ -139,7 +139,7 @@ mr_err_t mr_irq_del(mr_irq_t *irq);
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_irq_request(mr_uint32_t irq, mr_irq_entry_t *entry, void *owner,
|
||||
mr_uint32_t flags);
|
||||
mr_uint16_t flags);
|
||||
|
||||
#if defined(MR_USE_IRQ_DEFER)
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ mr_err_t mr_irq_request(mr_uint32_t irq, mr_irq_entry_t *entry, void *owner,
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_irq_defer_request(mr_uint32_t irq, mr_irq_entry_t *entry,
|
||||
void *owner, mr_uint32_t flags,
|
||||
void *owner, mr_uint16_t flags,
|
||||
mr_irq_entry_t *defer_entry);
|
||||
#endif /* defined(MR_USE_IRQ_DEFER) */
|
||||
|
||||
|
||||
158
include/mr-X/mr_wait.h
Normal file
158
include/mr-X/mr_wait.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_WAIT_H__
|
||||
#define __MR_WAIT_H__
|
||||
|
||||
#include <mr_config.h>
|
||||
#if defined(MR_USE_WAIT)
|
||||
#include <mr-X/mr_object.h>
|
||||
#include <mr-X/mr_list.h>
|
||||
#endif /* defined(MR_USE_WAIT) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Wait
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(MR_USE_WAIT)
|
||||
/* Wait event definition */
|
||||
#define MR_WAIT_IN (0x10000000U)
|
||||
#define MR_WAIT_OUT (0x20000000U)
|
||||
#define MR_WAIT_ERR (0x40000000U)
|
||||
#define MR_WAIT_EDGE (0x80000000U)
|
||||
|
||||
/* Waitable type */
|
||||
typedef struct mr_waitable {
|
||||
mr_object_t parent;
|
||||
mr_uint32_t last;
|
||||
mr_list_t list;
|
||||
mr_ptr_t check;
|
||||
mr_ptr_t param;
|
||||
} mr_waitable_t;
|
||||
|
||||
/* Wait check type */
|
||||
typedef mr_uint32_t(mr_waitable_check_t)(mr_waitable_t *waitable, void *param);
|
||||
|
||||
/* Waiter type */
|
||||
typedef struct mr_waiter {
|
||||
mr_object_t parent;
|
||||
mr_uint32_t event;
|
||||
mr_list_t list;
|
||||
mr_ptr_t entry;
|
||||
mr_ptr_t param;
|
||||
} mr_waiter_t;
|
||||
|
||||
/* Wait entry type */
|
||||
typedef void(mr_waiter_entry_t)(mr_waiter_t *waiter, void *param,
|
||||
mr_uint32_t event);
|
||||
|
||||
/**
|
||||
* @brief This function initializes a waitable.
|
||||
*
|
||||
* @param waitable The waitable.
|
||||
* @param check The waitable check.
|
||||
* @param param The check parameter.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waitable_init(mr_waitable_t *waitable, mr_waitable_check_t *check,
|
||||
void *param);
|
||||
|
||||
/**
|
||||
* @brief This function creates a waitable.
|
||||
*
|
||||
* @param check The waitable check.
|
||||
* @param param The check parameter.
|
||||
* @return The waitable on success, NULL on failure.
|
||||
*/
|
||||
mr_waitable_t *mr_waitable_create(mr_waitable_check_t *check, void *param);
|
||||
|
||||
/**
|
||||
* @brief This function deletes a waitable.
|
||||
*
|
||||
* @param waitable The waitable.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waitable_del(mr_waitable_t *waitable);
|
||||
|
||||
/**
|
||||
* @brief This function completes a waitable.
|
||||
*
|
||||
* @param waitable The waitable.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waitable_complete(mr_waitable_t *waitable);
|
||||
|
||||
/**
|
||||
* @brief This function initializes a waiter.
|
||||
*
|
||||
* @param waiter The waiter.
|
||||
* @param entry The wait entry.
|
||||
* @param param The entry parameter.
|
||||
* @param event The wait event('IN||OUT||ERR').
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waiter_init(mr_waiter_t *waiter, mr_waiter_entry_t *entry,
|
||||
void *param, mr_uint32_t event);
|
||||
|
||||
/**
|
||||
* @brief This function creates a waiter.
|
||||
*
|
||||
* @param entry The wait entry.
|
||||
* @param param The entry parameter.
|
||||
* @param event The wait event('IN||OUT||ERR').
|
||||
* @return The waiter on success, NULL on failure.
|
||||
*/
|
||||
mr_waiter_t *mr_waiter_create(mr_waiter_entry_t *entry, void *param,
|
||||
mr_uint32_t event);
|
||||
|
||||
/**
|
||||
* @brief This function deletes a waiter.
|
||||
*
|
||||
* @param waiter The waiter.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waiter_del(mr_waiter_t *waiter);
|
||||
|
||||
/**
|
||||
* @brief This function checks if a waiter is waiting.
|
||||
*
|
||||
* @param waiter The waiter.
|
||||
* @return MR_TRUE if the waiter is waiting, false otherwise.
|
||||
*/
|
||||
#define MR_WAITER_IS_WAITING(_waiter) (!mr_list_is_empty(&(_waiter)->list))
|
||||
|
||||
/**
|
||||
* @brief This function waits for a waitable.
|
||||
*
|
||||
* @param waiter The waiter.
|
||||
* @param waitable The waitable.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waiter_wait(mr_waiter_t *waiter, mr_waitable_t *waitable);
|
||||
|
||||
/**
|
||||
* @brief This function cancels a waiter.
|
||||
*
|
||||
* @param waiter The waiter.
|
||||
* @return 0 on success, a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_waiter_cancel(mr_waiter_t *waiter);
|
||||
#endif /* defined(MR_USE_WAIT) */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_WAIT_H__ */
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <mr-X/mr_spinlock.h>
|
||||
#include <mr-X/mr_timer.h>
|
||||
#include <mr-X/mr_version.h>
|
||||
#include <mr-X/mr_wait.h>
|
||||
#include <mr-X/mr_workqueue.h>
|
||||
|
||||
/** @} */
|
||||
|
||||
10
kernel/irq.c
10
kernel/irq.c
@@ -37,7 +37,7 @@ static mr_irq_defer_hook_t __hook = {.wakeup = MR_NULL, .suspend = MR_NULL};
|
||||
/* Irq priority default definition */
|
||||
#define IRQ_PRIORITY_DEFAULT (0)
|
||||
/* Irq flags definition */
|
||||
#define IRQ_FLAG_TYPE_MASK (0x0f)
|
||||
#define IRQ_FLAG_TYPE_MASK (0x0fU)
|
||||
/* Irq action pending definition */
|
||||
#define IRQ_ACTION_PENDING (1U << 31)
|
||||
|
||||
@@ -296,7 +296,7 @@ static void irq_depth_enable(mr_uint32_t irq, mr_irq_desc_t *desc) {
|
||||
desc->irq->ops->enable(irq, desc->irq->param);
|
||||
}
|
||||
|
||||
static mr_err_t irq_request(mr_uint32_t irq, mr_uint32_t flags,
|
||||
static mr_err_t irq_request(mr_uint32_t irq, mr_uint16_t flags,
|
||||
mr_irq_action_t *action) {
|
||||
mr_irq_action_t **a;
|
||||
mr_irq_desc_t *desc;
|
||||
@@ -361,7 +361,7 @@ _exit:
|
||||
}
|
||||
|
||||
static mr_err_t irq_defer_request(mr_uint32_t irq, mr_irq_entry_t *entry,
|
||||
mr_ptr_t owner, mr_uint32_t flags,
|
||||
mr_ptr_t owner, mr_uint16_t flags,
|
||||
mr_irq_entry_t *defer_entry) {
|
||||
mr_irq_action_t *action;
|
||||
mr_err_t ret;
|
||||
@@ -382,7 +382,7 @@ static mr_err_t irq_defer_request(mr_uint32_t irq, mr_irq_entry_t *entry,
|
||||
}
|
||||
|
||||
mr_err_t mr_irq_request(mr_uint32_t irq, mr_irq_entry_t *entry, void *owner,
|
||||
mr_uint32_t flags) {
|
||||
mr_uint16_t flags) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT(irq < MR_CFG_IRQ_TABLE_SIZE);
|
||||
MR_ASSERT((entry != MR_NULL) && (owner != MR_NULL));
|
||||
@@ -393,7 +393,7 @@ mr_err_t mr_irq_request(mr_uint32_t irq, mr_irq_entry_t *entry, void *owner,
|
||||
}
|
||||
|
||||
mr_err_t mr_irq_defer_request(mr_uint32_t irq, mr_irq_entry_t *entry,
|
||||
void *owner, mr_uint32_t flags,
|
||||
void *owner, mr_uint16_t flags,
|
||||
mr_irq_entry_t *defer_entry) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT(irq < MR_CFG_IRQ_TABLE_SIZE);
|
||||
|
||||
397
kernel/wait.c
Normal file
397
kernel/wait.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <mr-X/mr_wait.h>
|
||||
#if defined(MR_USE_WAIT)
|
||||
#include <mr-X/mr_spinlock.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
|
||||
/* Waitable clazz(static & dynamic) */
|
||||
static void able_obj_release1(mr_object_t *obj);
|
||||
static void able_obj_release2(mr_object_t *obj);
|
||||
static const mr_clazz_t __able_clazz1
|
||||
= MR_CLAZZ_INIT("waitable", able_obj_release1);
|
||||
static const mr_clazz_t __able_clazz2
|
||||
= MR_CLAZZ_INIT("waitable", able_obj_release2);
|
||||
|
||||
/* Waiter clazz(static & dynamic) */
|
||||
static void wait_obj_release1(mr_object_t *obj);
|
||||
static void wait_obj_release2(mr_object_t *obj);
|
||||
static const mr_clazz_t __wait_clazz1
|
||||
= MR_CLAZZ_INIT("waiter", wait_obj_release1);
|
||||
static const mr_clazz_t __wait_clazz2
|
||||
= MR_CLAZZ_INIT("waiter", wait_obj_release2);
|
||||
|
||||
/* Wait lock */
|
||||
static mr_spinlock_t __lock = MR_SPINLOCK_INIT();
|
||||
|
||||
/* Wait event mask definition */
|
||||
#define WAIT_TYPE_MASK (0x70000000U)
|
||||
#define WAIT_MASK (0x7fffffffU)
|
||||
|
||||
static mr_err_t waitable_init(mr_waitable_t *waitable, const mr_clazz_t *class,
|
||||
mr_ptr_t check, mr_ptr_t param) {
|
||||
/* Init waitable */
|
||||
mr_list_init(&waitable->list);
|
||||
waitable->check = check;
|
||||
waitable->param = param;
|
||||
waitable->last = 0;
|
||||
|
||||
/* Init object */
|
||||
return mr_object_init((mr_object_t *)waitable, class);
|
||||
}
|
||||
|
||||
mr_err_t mr_waitable_init(mr_waitable_t *waitable, mr_waitable_check_t *check,
|
||||
void *param) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waitable != MR_NULL) && (!MR_OBJECT_IS_INITED(waitable)));
|
||||
MR_ASSERT(check != MR_NULL);
|
||||
|
||||
/* Init waitable */
|
||||
return waitable_init(waitable, &__able_clazz1, check, param);
|
||||
}
|
||||
|
||||
mr_waitable_t *mr_waitable_create(mr_waitable_check_t *check, void *param) {
|
||||
mr_waitable_t *waitable;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check parameter */
|
||||
MR_ASSERT(check != MR_NULL);
|
||||
|
||||
/* Create waitable */
|
||||
waitable = mr_malloc(sizeof(mr_waitable_t));
|
||||
if (!waitable) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init waitable */
|
||||
ret = waitable_init(waitable, &__able_clazz2, check, param);
|
||||
if (ret != 0) {
|
||||
mr_free(waitable);
|
||||
return MR_NULL;
|
||||
}
|
||||
return waitable;
|
||||
}
|
||||
|
||||
static void waitable_remove(mr_waitable_t *waitable) {
|
||||
mr_waiter_t *waiter;
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&__lock);
|
||||
|
||||
/* Clear waiting list */
|
||||
while (!mr_list_is_empty(&waitable->list)) {
|
||||
waiter = MR_LIST_ENTRY(waitable->list.next, mr_waiter_t, list);
|
||||
|
||||
/* Remove waiter from waiting list */
|
||||
mr_list_del(&waiter->list);
|
||||
}
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_waitable_del(mr_waitable_t *waitable) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waitable != MR_NULL) && MR_OBJECT_IS_INITED(waitable));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waitable, &__able_clazz1, &__able_clazz2));
|
||||
|
||||
/* Remove waitable */
|
||||
waitable_remove(waitable);
|
||||
|
||||
/* Delete object */
|
||||
mr_object_del((mr_object_t *)waitable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mr_uint32_t waitable_check(mr_waitable_t *waitable) {
|
||||
mr_waitable_check_t *check;
|
||||
mr_uint32_t event;
|
||||
void *param;
|
||||
|
||||
/* Save waitable check and param */
|
||||
check = (mr_waitable_check_t *)waitable->check;
|
||||
param = (void *)waitable->param;
|
||||
|
||||
/* Call waitable check */
|
||||
event = check(waitable, param);
|
||||
event &= WAIT_MASK;
|
||||
return event;
|
||||
}
|
||||
|
||||
mr_err_t mr_waitable_complete(mr_waitable_t *waitable) {
|
||||
mr_uint32_t event, event_level, event_edge;
|
||||
mr_waiter_entry_t *entry;
|
||||
mr_waiter_t *waiter;
|
||||
mr_list_t oplist;
|
||||
void *param;
|
||||
int mask;
|
||||
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waitable != MR_NULL) && MR_OBJECT_IS_INITED(waitable));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waitable, &__able_clazz1, &__able_clazz2));
|
||||
|
||||
/* Reduce unnecessary check operations */
|
||||
if (mr_list_is_empty(&waitable->list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get waitable event */
|
||||
event = waitable_check(waitable);
|
||||
if ((event & WAIT_TYPE_MASK) == 0) {
|
||||
/* No waitable event(untyped events will be discarded) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Init operation list */
|
||||
mr_list_init(&oplist);
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&__lock);
|
||||
|
||||
/* Get edge and level event */
|
||||
event_edge = event & ~waitable->last;
|
||||
event_level = event;
|
||||
|
||||
/* Replace the waiting list with the operation list (to prevent node removal
|
||||
* in the middle) */
|
||||
mr_list_replace(&oplist, &waitable->list);
|
||||
|
||||
/* Check operation list */
|
||||
while (!mr_list_is_empty(&oplist)) {
|
||||
waiter = MR_LIST_ENTRY(oplist.next, mr_waiter_t, list);
|
||||
|
||||
/* Move waiter to waiting list */
|
||||
mr_list_move(&waiter->list, &waitable->list);
|
||||
|
||||
/* Check if waiter is triggered */
|
||||
event = (waiter->event & MR_WAIT_EDGE) ? event_edge : event_level;
|
||||
if (!(waiter->event & event)) {
|
||||
/* Not triggered */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Save waiter entry and param */
|
||||
entry = (mr_waiter_entry_t *)waiter->entry;
|
||||
param = (void *)waiter->param;
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
|
||||
/* Call waiter entry */
|
||||
entry(waiter, param, event);
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&__lock);
|
||||
}
|
||||
|
||||
/* Update waitable last event */
|
||||
waitable->last = event;
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mr_waitable_t *able_obj_release(mr_object_t *obj) {
|
||||
mr_waitable_t *waitable;
|
||||
|
||||
/* Get waitable */
|
||||
waitable = MR_CONTAINER_OF(obj, mr_waitable_t, parent);
|
||||
|
||||
/* Remove waitable */
|
||||
waitable_remove(waitable);
|
||||
return waitable;
|
||||
}
|
||||
|
||||
static void able_obj_release1(mr_object_t *obj) {
|
||||
/* Release waitable */
|
||||
able_obj_release(obj);
|
||||
}
|
||||
|
||||
static void able_obj_release2(mr_object_t *obj) {
|
||||
mr_waitable_t *waitable;
|
||||
|
||||
/* Release waitable */
|
||||
waitable = able_obj_release(obj);
|
||||
|
||||
/* Free waitable */
|
||||
mr_free(waitable);
|
||||
}
|
||||
|
||||
static mr_err_t waiter_init(mr_waiter_t *waiter, const mr_clazz_t *class,
|
||||
mr_ptr_t entry, mr_ptr_t param, mr_uint32_t event) {
|
||||
/* Init waiter */
|
||||
mr_list_init(&waiter->list);
|
||||
waiter->event = event;
|
||||
waiter->entry = entry;
|
||||
waiter->param = param;
|
||||
|
||||
/* Init object */
|
||||
return mr_object_init((mr_object_t *)waiter, class);
|
||||
}
|
||||
|
||||
mr_err_t mr_waiter_init(mr_waiter_t *waiter, mr_waiter_entry_t *entry,
|
||||
void *param, mr_uint32_t event) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waiter != MR_NULL) && (!MR_OBJECT_IS_INITED(waiter)));
|
||||
MR_ASSERT((entry != MR_NULL) && ((event & WAIT_TYPE_MASK) != 0));
|
||||
|
||||
/* Init waiter */
|
||||
return waiter_init(waiter, &__wait_clazz1, entry, param, event);
|
||||
}
|
||||
|
||||
mr_waiter_t *mr_waiter_create(mr_waiter_entry_t *entry, void *param,
|
||||
mr_uint32_t event) {
|
||||
mr_waiter_t *waiter;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check parameter */
|
||||
MR_ASSERT((entry != MR_NULL) && ((event & WAIT_TYPE_MASK) != 0));
|
||||
|
||||
/* Create waiter */
|
||||
waiter = mr_malloc(sizeof(mr_waiter_t));
|
||||
if (!waiter) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init waiter */
|
||||
ret = waiter_init(waiter, &__wait_clazz2, entry, param, event);
|
||||
if (ret != 0) {
|
||||
mr_free(waiter);
|
||||
return MR_NULL;
|
||||
}
|
||||
return waiter;
|
||||
}
|
||||
|
||||
static void waiter_remove(mr_waiter_t *waiter) {
|
||||
int mask;
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&__lock);
|
||||
|
||||
/* Remove waiter from waiting list */
|
||||
mr_list_del(&waiter->list);
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
}
|
||||
|
||||
mr_err_t mr_waiter_del(mr_waiter_t *waiter) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waiter != MR_NULL) && MR_OBJECT_IS_INITED(waiter));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waiter, &__wait_clazz1, &__wait_clazz2));
|
||||
|
||||
/* Remove waiter */
|
||||
waiter_remove(waiter);
|
||||
|
||||
/* Delete object */
|
||||
mr_object_del((mr_object_t *)waiter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr_err_t mr_waiter_wait(mr_waiter_t *waiter, mr_waitable_t *waitable) {
|
||||
mr_waiter_entry_t *entry;
|
||||
mr_uint32_t event;
|
||||
mr_err_t ret;
|
||||
void *param;
|
||||
int mask;
|
||||
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waiter != MR_NULL) && MR_OBJECT_IS_INITED(waiter));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waiter, &__wait_clazz1, &__wait_clazz2));
|
||||
MR_ASSERT((waitable != MR_NULL) && MR_OBJECT_IS_INITED(waitable));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waitable, &__able_clazz1, &__able_clazz2));
|
||||
|
||||
/* Lock */
|
||||
mask = mr_spinlock_lock_irqsave(&__lock);
|
||||
|
||||
/* Check if waiter is waiting */
|
||||
if (MR_WAITER_IS_WAITING(waiter)) {
|
||||
ret = -MR_EBUSY;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Add waiter to waitable waiting list */
|
||||
mr_list_add(&waitable->list, &waiter->list);
|
||||
|
||||
/* Check if waiter is waiting for edge event */
|
||||
if (waiter->event & MR_WAIT_EDGE) {
|
||||
/* Edge triggering is not related to the previous one */
|
||||
ret = 0;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Get waitable event */
|
||||
event = waitable_check(waitable);
|
||||
if ((event & WAIT_TYPE_MASK) == 0) {
|
||||
/* No waitable event(untyped events will be discarded) */
|
||||
ret = 0;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Check if waiter is triggered */
|
||||
if (!(waiter->event & event)) {
|
||||
/* Not triggered */
|
||||
ret = 0;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Save waiter entry and param */
|
||||
entry = (mr_waiter_entry_t *)waiter->entry;
|
||||
param = (void *)waiter->param;
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
|
||||
/* Call waiter entry */
|
||||
entry(waiter, param, event);
|
||||
return 0;
|
||||
_exit:
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock_irqrestore(&__lock, mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_err_t mr_waiter_cancel(mr_waiter_t *waiter) {
|
||||
/* Check parameter */
|
||||
MR_ASSERT((waiter != MR_NULL) && MR_OBJECT_IS_INITED(waiter));
|
||||
MR_ASSERT(MR_OBJECT_CLAZZ_IS_OR(waiter, &__wait_clazz1, &__wait_clazz2));
|
||||
|
||||
/* Remove waiter */
|
||||
waiter_remove(waiter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mr_waiter_t *wait_obj_release(mr_object_t *obj) {
|
||||
mr_waiter_t *waiter;
|
||||
|
||||
/* Get waiter */
|
||||
waiter = MR_CONTAINER_OF(obj, mr_waiter_t, parent);
|
||||
|
||||
/* Remove waiter */
|
||||
waiter_remove(waiter);
|
||||
return waiter;
|
||||
}
|
||||
|
||||
static void wait_obj_release1(mr_object_t *obj) {
|
||||
/* Release waiter */
|
||||
wait_obj_release(obj);
|
||||
}
|
||||
|
||||
static void wait_obj_release2(mr_object_t *obj) {
|
||||
mr_waiter_t *waiter;
|
||||
|
||||
/* Release waiter */
|
||||
waiter = wait_obj_release(obj);
|
||||
|
||||
/* Free waiter */
|
||||
mr_free(waiter);
|
||||
}
|
||||
#endif /* defined(MR_USE_WAIT) */
|
||||
Reference in New Issue
Block a user