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();

Reply via email to