mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
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:
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user