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 735e4890708013c611b4c63c64d3fc1bb3436cdb
Author: wangchengdong <[email protected]>
AuthorDate: Wed Oct 29 10:37:51 2025 +0800

    [!] sched/event: Replace semaphore with direct scheduler operations in event
    
        The current event implementation uses semaphores for wait and post
        operations. Since semaphores are relatively heavy-weight and intended
        for resource-based synchronization, this is suboptimal.
    
        So this patch replaced the semaphore-based mechanism with direct
        scheduler operations to improve performance and reduce memory footprint.
    
        This patch also introduce a new task state TSTATE_WAIT_EVENT to indicate
        the task is waiting for a event.
    
        BREAKING CHANGE:  This commit introduced a new task state 
TSTATE_WAIT_EVENT
        so apps/nshlib/, procfs/ and tools/pynuttx/nxgdb/ are needed to be 
updated accordingly.
    
    Signed-off-by: Chengdong Wang [email protected]
---
 include/nuttx/event.h    |   3 +-
 include/nuttx/sched.h    |   3 ++
 sched/event/event_post.c |  40 ++++++++++++---
 sched/event/event_wait.c | 125 ++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 140 insertions(+), 31 deletions(-)

diff --git a/include/nuttx/event.h b/include/nuttx/event.h
index 365443c8664..569a6b951b1 100644
--- a/include/nuttx/event.h
+++ b/include/nuttx/event.h
@@ -30,7 +30,6 @@
 #include <nuttx/config.h>
 
 #include <nuttx/list.h>
-#include <nuttx/semaphore.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -65,7 +64,7 @@ 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 */
-  sem_t                   sem;     /* Wait sem of current task */
+  FAR struct tcb_s        *wtcb;   /* The waiting task */
 };
 
 struct nxevent_s
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 34308781ce1..53490bc7601 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -253,6 +253,9 @@ enum tstate_e
   TSTATE_TASK_INACTIVE,       /* BLOCKED      - Initialized but not yet 
activated */
   TSTATE_WAIT_SEM,            /* BLOCKED      - Waiting for a semaphore */
   TSTATE_WAIT_SIG,            /* BLOCKED      - Waiting for a signal */
+#ifdef CONFIG_SCHED_EVENTS
+  TSTATE_WAIT_EVENT,          /* BLOCKED      - Waiting for a event */
+#endif
 #if !defined(CONFIG_DISABLE_MQUEUE) || !defined(CONFIG_DISABLE_MQUEUE_SYSV)
   TSTATE_WAIT_MQNOTEMPTY,     /* BLOCKED      - Waiting for a MQ to become not 
empty. */
   TSTATE_WAIT_MQNOTFULL,      /* BLOCKED      - Waiting for a MQ to become not 
full. */
diff --git a/sched/event/event_post.c b/sched/event/event_post.c
index 07b9f0b4f23..c717d58eec7 100644
--- a/sched/event/event_post.c
+++ b/sched/event/event_post.c
@@ -24,7 +24,12 @@
  * Included Files
  ****************************************************************************/
 
-#include <nuttx/sched.h>
+#include <nuttx/config.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/clock.h>
+
+#include "sched/sched.h"
 
 #include "event.h"
 
@@ -68,13 +73,15 @@
 int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events,
                  nxevent_flags_t eflags)
 {
+  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;
   irqstate_t flags;
   bool waitall;
   bool postall;
-  int ret = 0;
+  bool need_switch;
 
   if (event == NULL)
     {
@@ -92,6 +99,9 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t events,
       event->events |= events ? events : ~0;
     }
 
+  need_switch = false;
+  rtcb = this_task();
+
   if (!list_is_empty(&event->list))
     {
       postall = ((eflags & NXEVENT_POST_ALL) != 0);
@@ -106,10 +116,21 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t 
events,
             {
               list_delete(&wait->node);
 
-              ret = nxsem_post(&wait->sem);
-              if (ret < 0)
+              wtcb = wait->wtcb;
+
+              /* Remove the task from waiting list */
+
+              dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal());
+
+              wd_cancel(&wtcb->waitdog);
+
+              /* Add the task to ready-to-run task list, and
+               * perform the context switch if one is needed
+               */
+
+              if (nxsched_add_readytorun(wtcb) && !need_switch)
                 {
-                  continue;
+                  need_switch = true;
                 }
 
               if (!waitall)
@@ -135,7 +156,14 @@ int nxevent_post(FAR nxevent_t *event, nxevent_mask_t 
events,
         }
     }
 
+  if (need_switch)
+    {
+      /* Switch context to the highest priority ready-to-run task */
+
+      up_switch_context(this_task(), rtcb);
+    }
+
   leave_critical_section(flags);
 
-  return ret;
+  return OK;
 }
diff --git a/sched/event/event_wait.c b/sched/event/event_wait.c
index 04d62cee249..b9e1b7c971c 100644
--- a/sched/event/event_wait.c
+++ b/sched/event/event_wait.c
@@ -24,10 +24,87 @@
  * Included Files
  ****************************************************************************/
 
-#include <nuttx/sched.h>
+#include <nuttx/config.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/clock.h>
+
+#include "sched/sched.h"
 
 #include "event.h"
 
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxevent_timeout
+ *
+ * Description:
+ *   A timeout elapsed while waiting for timeout.
+ *
+ * Assumptions:
+ *   This function executes in the context of the timer interrupt handler.
+ *   Local interrupts are assumed to be disabled on entry.
+ *
+ * Input Parameters:
+ *   arg - Parameter to pass to wdentry.
+ *
+ ****************************************************************************/
+
+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 */
+
+  wait = (FAR nxevent_wait_t *)(uintptr_t)arg;
+  wtcb = wait->wtcb;
+
+  /* We must be in a critical section in order to call up_switch_context()
+   * below.
+   */
+
+  flags = enter_critical_section();
+
+  /* There may be a race condition -- make sure the task is
+   * still waiting for a signal
+   */
+
+  if (wtcb->task_state == TSTATE_WAIT_EVENT)
+    {
+      /* Remove the wait from the event's waiting list */
+
+      if (list_in_list(&(wait->node)))
+        {
+          list_delete(&(wait->node));
+        }
+
+      /* Mark the errno value for the thread. */
+
+      wtcb->errcode = ETIMEDOUT;
+
+      FAR struct tcb_s *rtcb = this_task();
+
+      /* Remove the task from waiting list */
+
+      dq_rem((FAR dq_entry_t *)wtcb, list_waitingforsignal());
+
+      /* Add the task to ready-to-run task list, and
+       * perform the context switch if one is needed
+       */
+
+      if (nxsched_add_readytorun(wtcb))
+        {
+          up_switch_context(this_task(), rtcb);
+        }
+    }
+
+  leave_critical_section(flags);
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -66,9 +143,9 @@ nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event,
                                      nxevent_flags_t eflags,
                                      uint32_t delay)
 {
+  FAR struct tcb_s *wtcb;
   irqstate_t flags;
   bool waitany;
-  int ret;
 
   DEBUGASSERT(event != NULL && wait != NULL &&
               up_interrupt_context() == false);
@@ -121,41 +198,43 @@ nxevent_mask_t nxevent_tickwait_wait(FAR nxevent_t *event,
     {
       /* Initialize event wait */
 
-      nxsem_init(&(wait->sem), 0, 0);
+      wtcb = this_task();
       wait->expect = events;
       wait->eflags = eflags;
+      wait->wtcb = wtcb;
 
       list_add_tail(&event->list, &(wait->node));
-      leave_critical_section(flags);
 
-      /* Wait for the event */
+      wd_start(&wtcb->waitdog, delay, nxevent_timeout, (uintptr_t)&wait);
 
-      if (delay == UINT32_MAX)
-        {
-          ret = nxsem_wait_uninterruptible(&(wait->sem));
-        }
-      else
-        {
-          ret = nxsem_tickwait_uninterruptible(&(wait->sem), delay);
-        }
+      /* Remove the tcb task from the ready-to-run list. */
+
+      nxsched_remove_self(wtcb);
+
+      /* Set the errno value to zero (preserving the original errno)
+       * value).
+       */
 
-      /* Destroy local variables */
+      wtcb->errcode = OK;
 
-      nxsem_destroy(&(wait->sem));
+      /* Add the task to the specified blocked task list */
 
-      flags = enter_critical_section();
-      if (ret == 0)
+      wtcb->task_state = TSTATE_WAIT_EVENT;
+
+      dq_addlast((FAR dq_entry_t *)wtcb, list_waitingforsignal());
+
+      /* Now, perform the context switch if one is needed */
+
+      up_switch_context(this_task(), wtcb);
+
+      DEBUGASSERT(!list_in_list(&(wait->node)));
+
+      if (wtcb->errcode == OK)
         {
           events = wait->expect;
-          DEBUGASSERT(!list_in_list(&(wait->node)));
         }
       else
         {
-          if (list_in_list(&(wait->node)))
-            {
-              list_delete(&(wait->node));
-            }
-
           events = 0;
         }
     }

Reply via email to