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 #include +#include #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 #include #include +#include #include #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; }