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 <hujun5@xiaomi.com>
This commit is contained in:
hujun5
2025-03-13 19:50:09 +08:00
committed by Alan C. Assis
parent 657ac8317e
commit 29bc8c7b15
5 changed files with 28 additions and 6 deletions
+5 -2
View File
@@ -211,6 +211,7 @@ int nxsig_action(int signo, FAR const struct sigaction *act,
FAR struct task_group_s *group; FAR struct task_group_s *group;
FAR sigactq_t *sigact; FAR sigactq_t *sigact;
_sa_handler_t handler; _sa_handler_t handler;
irqstate_t flags;
/* Since sigactions can only be installed from the running thread of /* Since sigactions can only be installed from the running thread of
* execution, no special precautions should be necessary. * 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) 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 /* We do require a critical section to muck with the TCB values that
* can be modified by the child thread. * 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 */ /* Yes.. Remove it from signal action queue */
flags = spin_lock_irqsave(&group->tg_lock);
sq_rem((FAR sq_entry_t *)sigact, &group->tg_sigactionq); sq_rem((FAR sq_entry_t *)sigact, &group->tg_sigactionq);
spin_unlock_irqrestore(&group->tg_lock, flags);
/* And deallocate it */ /* 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 */ /* 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); sq_addlast((FAR sq_entry_t *)sigact, &group->tg_sigactionq);
spin_unlock_irqrestore(&group->tg_lock, flags);
} }
/* Set the new sigaction */ /* Set the new sigaction */
+9
View File
@@ -26,6 +26,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/spinlock.h>
#include "signal/signal.h" #include "signal/signal.h"
@@ -82,13 +83,17 @@ void nxsig_release(FAR struct task_group_s *group)
{ {
FAR sigactq_t *sigact; FAR sigactq_t *sigact;
FAR sigpendq_t *sigpend; FAR sigpendq_t *sigpend;
irqstate_t flags;
/* Deallocate all entries in the list of signal actions */ /* 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)) while ((sigact = (FAR sigactq_t *)sq_remfirst(&group->tg_sigactionq))
!= NULL) != NULL)
{ {
spin_unlock_irqrestore(&group->tg_lock, flags);
nxsig_release_action(sigact); nxsig_release_action(sigact);
flags = spin_lock_irqsave(&group->tg_lock);
} }
/* Deallocate all entries in the list of pending signals */ /* 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)) while ((sigpend = (FAR sigpendq_t *)sq_remfirst(&group->tg_sigpendingq))
!= NULL) != NULL)
{ {
spin_unlock_irqrestore(&group->tg_lock, flags);
nxsig_release_pendingsignal(sigpend); nxsig_release_pendingsignal(sigpend);
flags = spin_lock_irqsave(&group->tg_lock);
} }
spin_unlock_irqrestore(&group->tg_lock, flags);
} }
+9
View File
@@ -239,6 +239,7 @@ static FAR sigpendq_t *
nxsig_find_pendingsignal(FAR struct task_group_s *group, int signo) nxsig_find_pendingsignal(FAR struct task_group_s *group, int signo)
{ {
FAR sigpendq_t *sigpend = NULL; FAR sigpendq_t *sigpend = NULL;
irqstate_t flags;
DEBUGASSERT(group != NULL); DEBUGASSERT(group != NULL);
@@ -249,12 +250,17 @@ nxsig_find_pendingsignal(FAR struct task_group_s *group, int signo)
return sigpend; 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 */ /* Search the list for a action pending on this signal */
for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head; for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head;
(sigpend && sigpend->info.si_signo != signo); (sigpend && sigpend->info.si_signo != signo);
sigpend = sigpend->flink); sigpend = sigpend->flink);
spin_unlock_irqrestore(&group->tg_lock, flags);
return sigpend; 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 struct task_group_s *group;
FAR sigpendq_t *sigpend; FAR sigpendq_t *sigpend;
irqstate_t flags;
DEBUGASSERT(stcb != NULL && stcb->group != NULL); DEBUGASSERT(stcb != NULL && stcb->group != NULL);
group = stcb->group; 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 */ /* 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); sq_addlast((FAR sq_entry_t *)sigpend, &group->tg_sigpendingq);
spin_unlock_irqrestore(&group->tg_lock, flags);
} }
} }
+2 -2
View File
@@ -94,7 +94,7 @@ sigset_t nxsig_pendingset(FAR struct tcb_s *stcb)
sigemptyset(&sigpendset); sigemptyset(&sigpendset);
flags = enter_critical_section(); flags = spin_lock_irqsave(&group->tg_lock);
for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head; for (sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head;
(sigpend); sigpend = sigpend->flink) (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; return sigpendset;
} }
+3 -2
View File
@@ -36,6 +36,7 @@
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/wdog.h> #include <nuttx/wdog.h>
#include <nuttx/spinlock.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include "signal/signal.h" #include "signal/signal.h"
@@ -61,7 +62,7 @@ FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s *stcb, int signo)
DEBUGASSERT(group); DEBUGASSERT(group);
flags = enter_critical_section(); flags = spin_lock_irqsave(&group->tg_lock);
/* If stcb == NULL, the signal is for whole group. Otherwise only /* If stcb == NULL, the signal is for whole group. Otherwise only
* remove the one which is to be delivered to the stcb * 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; return currsig;
} }