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


The following commit(s) were added to refs/heads/master by this push:
     new 29bc8c7b155 sched/signal: use spinlock to protect signal queues
29bc8c7b155 is described below

commit 29bc8c7b155cae947fa0846e90f21ef36ac0558e
Author: hujun5 <[email protected]>
AuthorDate: Thu Mar 13 19:50:09 2025 +0800

    sched/signal: use spinlock to protect signal queues
    
    Replace global critical section with fine-grained spinlock protection for
    signal action queue (tg_sigactionq) and signal pending queue 
(tg_sigpendingq).
    Use spin_lock_irqsave/spin_unlock_irqrestore with group->tg_lock for proper
    synchronization, reducing interrupt latency and improving SMP scalability.
    
    Signed-off-by: hujun5 <[email protected]>
---
 sched/signal/sig_action.c              | 7 +++++--
 sched/signal/sig_cleanup.c             | 9 +++++++++
 sched/signal/sig_dispatch.c            | 9 +++++++++
 sched/signal/sig_pending.c             | 4 ++--
 sched/signal/sig_removependingsignal.c | 5 +++--
 5 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c
index 54a891e92e7..ab37db83d26 100644
--- a/sched/signal/sig_action.c
+++ b/sched/signal/sig_action.c
@@ -211,6 +211,7 @@ int nxsig_action(int signo, FAR const struct sigaction *act,
   FAR struct task_group_s *group;
   FAR sigactq_t *sigact;
   _sa_handler_t handler;
+  irqstate_t flags;
 
   /* Since sigactions can only be installed from the running thread of
    * execution, no special precautions should be necessary.
@@ -306,8 +307,6 @@ int nxsig_action(int signo, FAR const struct sigaction *act,
 
   if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0)
     {
-      irqstate_t flags;
-
       /* We do require a critical section to muck with the TCB values that
        * can be modified by the child thread.
        */
@@ -356,7 +355,9 @@ int nxsig_action(int signo, FAR const struct sigaction *act,
         {
           /* Yes.. Remove it from signal action queue */
 
+          flags = spin_lock_irqsave(&group->tg_lock);
           sq_rem((FAR sq_entry_t *)sigact, &group->tg_sigactionq);
+          spin_unlock_irqrestore(&group->tg_lock, flags);
 
           /* And deallocate it */
 
@@ -391,7 +392,9 @@ int nxsig_action(int signo, FAR const struct sigaction *act,
 
           /* Add the new sigaction to signal action queue */
 
+          flags = spin_lock_irqsave(&group->tg_lock);
           sq_addlast((FAR sq_entry_t *)sigact, &group->tg_sigactionq);
+          spin_unlock_irqrestore(&group->tg_lock, flags);
         }
 
       /* Set the new sigaction */
diff --git a/sched/signal/sig_cleanup.c b/sched/signal/sig_cleanup.c
index 9bb8d9a7337..df63a2d783f 100644
--- a/sched/signal/sig_cleanup.c
+++ b/sched/signal/sig_cleanup.c
@@ -26,6 +26,7 @@
 
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
+#include <nuttx/spinlock.h>
 
 #include "signal/signal.h"
 
@@ -82,13 +83,17 @@ void nxsig_release(FAR struct task_group_s *group)
 {
   FAR sigactq_t  *sigact;
   FAR sigpendq_t *sigpend;
+  irqstate_t flags;
 
   /* Deallocate all entries in the list of signal actions */
 
+  flags = spin_lock_irqsave(&group->tg_lock);
   while ((sigact = (FAR sigactq_t *)sq_remfirst(&group->tg_sigactionq))
          != NULL)
     {
+      spin_unlock_irqrestore(&group->tg_lock, flags);
       nxsig_release_action(sigact);
+      flags = spin_lock_irqsave(&group->tg_lock);
     }
 
   /* Deallocate all entries in the list of pending signals */
@@ -96,6 +101,10 @@ void nxsig_release(FAR struct task_group_s *group)
   while ((sigpend = (FAR sigpendq_t *)sq_remfirst(&group->tg_sigpendingq))
          != NULL)
     {
+      spin_unlock_irqrestore(&group->tg_lock, flags);
       nxsig_release_pendingsignal(sigpend);
+      flags = spin_lock_irqsave(&group->tg_lock);
     }
+
+  spin_unlock_irqrestore(&group->tg_lock, flags);
 }
diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c
index 723799c17df..d9ca78f9d21 100644
--- a/sched/signal/sig_dispatch.c
+++ b/sched/signal/sig_dispatch.c
@@ -239,6 +239,7 @@ static FAR sigpendq_t *
 nxsig_find_pendingsignal(FAR struct task_group_s *group, int signo)
 {
   FAR sigpendq_t *sigpend = NULL;
+  irqstate_t flags;
 
   DEBUGASSERT(group != NULL);
 
@@ -249,12 +250,17 @@ nxsig_find_pendingsignal(FAR struct task_group_s *group, 
int signo)
       return sigpend;
     }
 
+  /* Pending signals can be added from interrupt level. */
+
+  flags = spin_lock_irqsave(&group->tg_lock);
+
   /* Search the list for a action pending on this signal */
 
   for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head;
        (sigpend && sigpend->info.si_signo != signo);
        sigpend = sigpend->flink);
 
+  spin_unlock_irqrestore(&group->tg_lock, flags);
   return sigpend;
 }
 
@@ -296,6 +302,7 @@ static FAR sigpendq_t *nxsig_add_pendingsignal(FAR struct 
tcb_s *stcb,
 {
   FAR struct task_group_s *group;
   FAR sigpendq_t *sigpend;
+  irqstate_t flags;
 
   DEBUGASSERT(stcb != NULL && stcb->group != NULL);
   group = stcb->group;
@@ -331,7 +338,9 @@ static FAR sigpendq_t *nxsig_add_pendingsignal(FAR struct 
tcb_s *stcb,
 
           /* Add the structure to the group pending signal list */
 
+          flags = spin_lock_irqsave(&group->tg_lock);
           sq_addlast((FAR sq_entry_t *)sigpend, &group->tg_sigpendingq);
+          spin_unlock_irqrestore(&group->tg_lock, flags);
         }
     }
 
diff --git a/sched/signal/sig_pending.c b/sched/signal/sig_pending.c
index c1e5fe9aeb6..0b856464db3 100644
--- a/sched/signal/sig_pending.c
+++ b/sched/signal/sig_pending.c
@@ -94,7 +94,7 @@ sigset_t nxsig_pendingset(FAR struct tcb_s *stcb)
 
   sigemptyset(&sigpendset);
 
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave(&group->tg_lock);
   for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head;
        (sigpend); sigpend = sigpend->flink)
     {
@@ -104,7 +104,7 @@ sigset_t nxsig_pendingset(FAR struct tcb_s *stcb)
         }
     }
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(&group->tg_lock, flags);
 
   return sigpendset;
 }
diff --git a/sched/signal/sig_removependingsignal.c 
b/sched/signal/sig_removependingsignal.c
index 6f965a8bd84..a18162c6b45 100644
--- a/sched/signal/sig_removependingsignal.c
+++ b/sched/signal/sig_removependingsignal.c
@@ -36,6 +36,7 @@
 #include <nuttx/irq.h>
 #include <nuttx/arch.h>
 #include <nuttx/wdog.h>
+#include <nuttx/spinlock.h>
 #include <nuttx/kmalloc.h>
 
 #include "signal/signal.h"
@@ -61,7 +62,7 @@ FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s 
*stcb, int signo)
 
   DEBUGASSERT(group);
 
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave(&group->tg_lock);
 
   /* If stcb == NULL, the signal is for whole group. Otherwise only
    * remove the one which is to be delivered to the stcb
@@ -85,7 +86,7 @@ FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s 
*stcb, int signo)
         }
     }
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(&group->tg_lock, flags);
 
   return currsig;
 }

Reply via email to