This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit de5973268bd499edeef05fbc936341ffb03c758c Author: wangchengdong <[email protected]> AuthorDate: Wed Oct 29 11:03:46 2025 +0800 [!] sched/event: Remove wait object dependency from event implementation The current event implementation relies on a dedicated wait object, which introduces several issues: 1. Increases memory usage 2. Complicates the event logic 3. Makes the API design less clean, as it requires a separate nxevent_tickwait_wait() function This patch removes the event’s dependency on the wait object and eliminates the nxevent_tickwait_wait() API accordingly. BREAKING CHANGE: this commit removed the nxevent_tickwait_wait function so the related docs should be updated accordingly Signed-off-by: Chengdong Wang [email protected] --- include/nuttx/event.h | 53 +++------------------- include/nuttx/sched.h | 6 +++ sched/event/event.h | 4 +- sched/event/event_init.c | 2 +- sched/event/event_post.c | 106 ++++++++++++++++++-------------------------- sched/event/event_wait.c | 97 +++++++++++++--------------------------- sched/event/event_waitirq.c | 19 +------- sched/init/nx_start.c | 7 +++ 8 files changed, 98 insertions(+), 196 deletions(-) diff --git a/include/nuttx/event.h b/include/nuttx/event.h index 569a6b951b1..7d768a97f06 100644 --- a/include/nuttx/event.h +++ b/include/nuttx/event.h @@ -29,7 +29,7 @@ #include <nuttx/config.h> -#include <nuttx/list.h> +#include <nuttx/queue.h> /**************************************************************************** * Pre-processor Definitions @@ -37,7 +37,8 @@ /* Initializers */ -#define NXEVENT_INITIALIZER(e, v) {LIST_INITIAL_VALUE((e).list), (v)} +#define EVENT_WAITLIST_INITIALIZER {NULL, NULL} +#define NXEVENT_INITIALIZER(e, v) {EVENT_WAITLIST_INITIALIZER, (v)} /* Event Wait Flags */ @@ -50,26 +51,18 @@ #define NXEVENT_POST_ALL (1 << 0) /* Bit 0: Post ALL */ #define NXEVENT_POST_SET (1 << 1) /* Bit 1: Set event after post */ +#define EVENT_WAITLIST(event) (&((event)->waitlist)) + /**************************************************************************** * Public Type Definitions ****************************************************************************/ typedef struct nxevent_s nxevent_t; -typedef struct nxevent_wait_s nxevent_wait_t; typedef unsigned long nxevent_mask_t; typedef unsigned long nxevent_flags_t; - -struct nxevent_wait_s -{ - struct list_node node; /* Wait node of current task */ - nxevent_mask_t expect; /* Expect events of wait task */ - nxevent_flags_t eflags; /* Event flags of wait task */ - FAR struct tcb_s *wtcb; /* The waiting task */ -}; - struct nxevent_s { - struct list_node list; /* Waiting list of nxevent_wait_t */ + dq_queue_t waitlist; /* Waiting list of nxevent_wait_t */ volatile nxevent_mask_t events; /* Pending Events */ }; @@ -215,40 +208,6 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events, nxevent_mask_t nxevent_wait(FAR nxevent_t *event, nxevent_mask_t events, nxevent_flags_t eflags); -/**************************************************************************** - * Name: nxevent_tickwait_wait - * - * Description: - * Wait for all of the specified events for the specified tick time. - * - * This routine waits on event object event until all of the specified - * events have been delivered to the event object, or the maximum wait time - * timeout has expired. A thread may wait on up to 32 distinctly numbered - * events that are expressed as bits in a single 32-bit word. - * - * Input Parameters: - * event - Address of the event object - * wait - Address of the event wait object - * events - Set of events to wait - * - Set events to 0 will indicate wait from any events - * eflags - Events flags - * delay - Ticks to wait from the start time until the event is - * posted. If ticks is zero, then this function is equivalent - * to nxevent_trywait(). - * - * Returned Value: - * This is an internal OS interface and should not be used by applications. - * Return of matching events upon success. - * 0 if matching events were not received within the specified time. - * - ****************************************************************************/ - -nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event, - FAR nxevent_wait_t *wait, - nxevent_mask_t events, - nxevent_flags_t eflags, - uint32_t delay); - /**************************************************************************** * Name: nxevent_tickwait * diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 53490bc7601..91b75eec63f 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -42,6 +42,7 @@ #include <nuttx/irq.h> #include <nuttx/mutex.h> #include <nuttx/semaphore.h> +#include <nuttx/event.h> #include <nuttx/queue.h> #include <nuttx/wdog.h> #include <nuttx/fs/fs.h> @@ -653,6 +654,11 @@ struct tcb_s FAR void *waitobj; /* Object thread waiting on */ +#ifdef CONFIG_SCHED_EVENTS + nxevent_mask_t expect; /* expected event mask */ + nxevent_flags_t eflags; /* event wait flags */ +#endif + /* POSIX Signal Control Fields ********************************************/ sigset_t sigprocmask; /* Signals that are blocked */ diff --git a/sched/event/event.h b/sched/event/event.h index e89a26a569f..f23ae33b1aa 100644 --- a/sched/event/event.h +++ b/sched/event/event.h @@ -30,9 +30,9 @@ #include <nuttx/config.h> #include <nuttx/irq.h> -#include <nuttx/list.h> - +#include <nuttx/queue.h> #include <nuttx/event.h> +#include <nuttx/sched.h> /**************************************************************************** * Public Function Definitions diff --git a/sched/event/event_init.c b/sched/event/event_init.c index 5d93b81f537..25f06ed75c6 100644 --- a/sched/event/event_init.c +++ b/sched/event/event_init.c @@ -49,5 +49,5 @@ void nxevent_init(FAR nxevent_t *event, nxevent_mask_t events) { event->events = events; - list_initialize(&event->list); + dq_init(EVENT_WAITLIST(event)); } diff --git a/sched/event/event_post.c b/sched/event/event_post.c index db1630cd471..03ae633142b 100644 --- a/sched/event/event_post.c +++ b/sched/event/event_post.c @@ -33,10 +33,6 @@ #include "event.h" -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -45,28 +41,18 @@ * Name: nxevent_post * * Description: - * Post one or more events to an event object. - * - * This routine posts one or more events to an event object. All tasks - * waiting on the event object event whose waiting conditions become - * met by this posting immediately unpend. - * - * Posting differs from setting in that posted events are merged together - * with the current set of events tracked by the event object. + * Post one or more events to the specified event object. This function + * wakes up any tasks that are waiting for the posted events, depending + * on their wait condition (any/all). * * Input Parameters: - * event - Address of the event object - * events - Set of events to post to event - * - Set events to 0 will be considered as any, - * waking up the waiting thread immediately. - * + * event - Pointer to the event object. + * events - Bitmask of events to post. + * eflags - Posting behavior flags, such as: + * NXEVENT_POST_SET: overwrite existing events. + * NXEVENT_POST_ALL: wake all waiting tasks. * Returned Value: - * This is an internal OS interface and should not be used by applications. - * It follows the NuttX internal error return policy: Zero (OK) is - * returned on success. A negated errno value is returned on failure. - * - * Assumptions: - * This function may be called from an interrupt handler. + * OK on success; -EINVAL if the event pointer is NULL. * ****************************************************************************/ @@ -76,9 +62,10 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events, FAR struct tcb_s *wtcb; FAR struct tcb_s *rtcb; nxevent_mask_t clear = 0; - FAR nxevent_wait_t *wait; - FAR nxevent_wait_t *tmp; + FAR dq_entry_t *entry; + FAR dq_entry_t *tmp; irqstate_t flags; + dq_queue_t *waitlist; bool waitall; bool postall; bool need_switch; @@ -99,56 +86,51 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events, event->events |= events ? events : ~0; } - need_switch = false; - rtcb = this_task(); + postall = ((eflags & NXEVENT_POST_ALL) != 0); + rtcb = this_task(); + waitlist = EVENT_WAITLIST(event); - if (!list_is_empty(&event->list)) + dq_for_every_safe(waitlist, entry, tmp) { - postall = ((eflags & NXEVENT_POST_ALL) != 0); - - list_for_every_entry_safe(&event->list, wait, tmp, - nxevent_wait_t, node) - { - waitall = ((wait->eflags & NXEVENT_WAIT_ALL) != 0); + wtcb = (FAR struct tcb_s *)entry; + waitall = ((wtcb->eflags & NXEVENT_WAIT_ALL) != 0); - if ((!waitall && ((wait->expect & event->events) != 0)) || - (waitall && ((wait->expect & event->events) == wait->expect))) - { - list_delete(&wait->node); + /* Check if this task's wait condition is satisfied */ - wtcb = wait->wtcb; + if ((!waitall && (wtcb->expect & event->events) != 0) || + (waitall && ((wtcb->expect & event->events) == wtcb->expect))) + { + dq_rem((FAR dq_entry_t *)wtcb, waitlist); - wtcb->waitobj = NULL; + /* Stop timeout watchdog */ - /* Remove the task from waiting list */ + wd_cancel(&wtcb->waitdog); + wtcb->waitobj = NULL; - dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal()); + /* Make task ready-to-run */ - wd_cancel(&wtcb->waitdog); + if (nxsched_add_readytorun(wtcb) && !need_switch) + { + /* Higher priority task is ready */ - /* Add the task to ready-to-run task list, and - * perform the context switch if one is needed - */ + need_switch = true; + } - if (nxsched_add_readytorun(wtcb) && !need_switch) - { - need_switch = true; - } + /* If waiting for any event, mark received ones */ - if (!waitall) - { - wait->expect &= event->events; - } + if (!waitall) + { + wtcb->expect &= event->events; + } - if ((wait->eflags & NXEVENT_WAIT_NOCLEAR) == 0) - { - clear |= wait->expect; - } + if ((wtcb->eflags & NXEVENT_WAIT_NOCLEAR) == 0) + { + clear |= wtcb->expect; + } - if (!postall && (event->events & ~clear) == 0) - { - break; - } + if (!postall && (event->events & ~clear) == 0) + { + break; } } diff --git a/sched/event/event_wait.c b/sched/event/event_wait.c index 01c7553d2a7..3b0af7122fe 100644 --- a/sched/event/event_wait.c +++ b/sched/event/event_wait.c @@ -55,13 +55,11 @@ static void nxevent_timeout(wdparm_t arg) { FAR struct tcb_s *wtcb; - FAR nxevent_wait_t *wait; irqstate_t flags; /* Get waiting tcb from parameter */ wtcb = (FAR struct tcb_s *)(uintptr_t)arg; - wait = wtcb->waitobj; /* We must be in a critical section in order to call up_switch_context() * below. @@ -86,7 +84,7 @@ static void nxevent_timeout(wdparm_t arg) ****************************************************************************/ /**************************************************************************** - * Name: nxevent_tickwait_wait + * Name: nxevent_tickwait * * Description: * Wait for all of the specified events for the specified tick time. @@ -98,7 +96,6 @@ static void nxevent_timeout(wdparm_t arg) * * Input Parameters: * event - Address of the event object - * wait - Address of the event wait object * events - Set of events to wait * - Set events to 0 will indicate wait from any events * eflags - Events flags @@ -113,18 +110,14 @@ static void nxevent_timeout(wdparm_t arg) * ****************************************************************************/ -nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event, - FAR nxevent_wait_t *wait, - nxevent_mask_t events, - nxevent_flags_t eflags, - uint32_t delay) +nxevent_mask_t nxevent_tickwait(FAR nxevent_t *event, nxevent_mask_t events, + nxevent_flags_t eflags, uint32_t delay) { - FAR struct tcb_s *wtcb; + FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; bool waitany; - DEBUGASSERT(event != NULL && wait != NULL && - up_interrupt_context() == false); + DEBUGASSERT(event != NULL && up_interrupt_context() == false); waitany = ((eflags & NXEVENT_WAIT_ALL) == 0); @@ -172,43 +165,48 @@ nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event, else { - /* Initialize event wait */ + /* Start the watchdog with interrupts still disabled */ - wtcb = this_task(); - wtcb->waitobj = (FAR void *)wait; - wait->expect = events; - wait->eflags = eflags; - wait->wtcb = wtcb; + wd_start(&rtcb->waitdog, delay, nxevent_timeout, (uintptr_t)rtcb); - list_add_tail(&event->list, &(wait->node)); + /* First, verify that the task is not already waiting on a + * event + */ - wd_start(&wtcb->waitdog, delay, nxevent_timeout, (uintptr_t)wtcb); + DEBUGASSERT(rtcb->waitobj == NULL); - /* Remove the tcb task from the ready-to-run list. */ + /* Save the waited on event in the TCB */ - nxsched_remove_self(wtcb); + rtcb->waitobj = event; + rtcb->expect = events; + rtcb->eflags = eflags; /* Set the errno value to zero (preserving the original errno) - * value). + * value). We reuse the per-thread errno to pass information + * between nxevent_wait_irq() and this functions. */ - wtcb->errcode = OK; + rtcb->errcode = OK; - /* Add the task to the specified blocked task list */ + /* Add the TCB to the prioritized event wait queue, after + * checking this is not the idle task - descheduling that + * isn't going to end well. + */ - wtcb->task_state = TSTATE_WAIT_EVENT; + DEBUGASSERT(!is_idle_task(rtcb)); - dq_addlast((FAR dq_entry_t *)wtcb, list_waitingforsignal()); + nxsched_remove_self(rtcb); - /* Now, perform the context switch if one is needed */ + rtcb->task_state = TSTATE_WAIT_EVENT; + nxsched_add_prioritized(rtcb, EVENT_WAITLIST(event)); - up_switch_context(this_task(), wtcb); + /* Now, perform the context switch if one is needed */ - DEBUGASSERT(!list_in_list(&(wait->node))); + up_switch_context(this_task(), rtcb); - if (wtcb->errcode == OK) + if (rtcb->errcode == OK) { - events = wait->expect; + events = rtcb->expect; } else { @@ -221,41 +219,6 @@ nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event, return events; } -/**************************************************************************** - * Name: nxevent_tickwait - * - * Description: - * Wait for all of the specified events for the specified tick time. - * - * This routine waits on event object event until all of the specified - * events have been delivered to the event object, or the maximum wait time - * timeout has expired. A thread may wait on up to 32 distinctly numbered - * events that are expressed as bits in a single 32-bit word. - * - * Input Parameters: - * event - Address of the event object - * events - Set of events to wait - * - Set events to 0 will indicate wait from any events - * eflags - Events flags - * delay - Ticks to wait from the start time until the event is - * posted. If ticks is zero, then this function is equivalent - * to nxevent_trywait(). - * - * Returned Value: - * This is an internal OS interface and should not be used by applications. - * Return of matching events upon success. - * 0 if matching events were not received within the specified time. - * - ****************************************************************************/ - -nxevent_mask_t nxevent_tickwait(FAR nxevent_t *event, nxevent_mask_t events, - nxevent_flags_t eflags, uint32_t delay) -{ - nxevent_wait_t wait; - - return nxevent_tickwait_wait(event, &wait, events, eflags, delay); -} - /**************************************************************************** * Name: nxevent_wait * diff --git a/sched/event/event_waitirq.c b/sched/event/event_waitirq.c index 6bd3dffffa1..e829586a402 100644 --- a/sched/event/event_waitirq.c +++ b/sched/event/event_waitirq.c @@ -51,27 +51,12 @@ void nxevent_wait_irq(FAR struct tcb_s *wtcb, int errcode) { - /* It is possible that an interrupt/context switch beat us to the punch - * and already changed the task's state. - */ - - DEBUGASSERT(wtcb != NULL); - FAR struct tcb_s *rtcb = this_task(); - FAR nxevent_wait_t *wait = wtcb->waitobj; - - DEBUGASSERT(wait != NULL); - - /* Remove the wait structure from the event's waiting list */ - - if (list_in_list(&(wait->node))) - { - list_delete(&(wait->node)); - } + FAR nxevent_t *event = wtcb->waitobj; /* Remove the task from the event waiting list */ - dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal()); + dq_rem((FAR dq_entry_t *)wtcb, EVENT_WAITLIST(event)); /* Indicate that the wait is over */ diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index b52a5b52a1f..374de7501e0 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -270,6 +270,13 @@ static void tasklist_initialize(void) tlist[TSTATE_WAIT_SEM].attr = TLIST_ATTR_PRIORITIZED | TLIST_ATTR_OFFSET; +#ifdef CONFIG_SCHED_EVENTS + /* TSTATE_WAIT_EVENT */ + + tlist[TSTATE_WAIT_EVENT].list = (FAR void *)offsetof(nxevent_t, waitlist); + tlist[TSTATE_WAIT_EVENT].attr = TLIST_ATTR_PRIORITIZED | + TLIST_ATTR_OFFSET; +#endif /* TSTATE_WAIT_SIG */ tlist[TSTATE_WAIT_SIG].list = list_waitingforsignal();
