mirror of
https://github.com/apache/nuttx.git
synced 2026-10-10 07:40:27 +00:00
arch/arm: redirect an M-profile thread to its signal action once
A signal action queued at syscall return pends PendSV for the running thread, but the same SVC can switch to another thread first. PendSV then saw that thread, the redirect was lost and the handler did not run until a later PendSV landed on the target, which could happen while it was already in arm_sigdeliver: the second redirect overwrote saved_regs, the inner delivery cleared sigdeliver and the outer one branched to address 0. ostest sighand and signest hard faulted in a protected build. The redirect is now checked against the thread being switched in, and a thread already redirected is left alone until arm_sigdeliver restores its context. Signed-off-by: Royyan Zahir <royzah@gmail.com>
This commit is contained in:
parent
3e456050d3
commit
5f5991a0f2
9 changed files with 39 additions and 27 deletions
|
|
@ -85,15 +85,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
/* Pendsv able to access running tcb with no critical section */
|
||||
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
|
||||
#endif
|
||||
up_irq_save();
|
||||
}
|
||||
|
|
@ -104,6 +95,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update scheduler parameters.
|
||||
* The arm-m architecture svc call will trigger an interrupt,
|
||||
* and the actual context switch is executed after doirq is completed,
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t ipsr = getipsr();
|
||||
|
||||
if (tcb->xcp.saved_regs != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ retry:
|
|||
|
||||
g_running_tasks[this_cpu()] = NULL;
|
||||
rtcb->xcp.regs = rtcb->xcp.saved_regs;
|
||||
rtcb->xcp.saved_regs = NULL;
|
||||
arm_fullcontextrestore();
|
||||
UNUSED(regs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,15 +85,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
/* Pendsv able to access running tcb with no critical section */
|
||||
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
up_irq_save();
|
||||
|
|
@ -105,6 +96,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update scheduler parameters.
|
||||
* The arm-m architecture svc call will trigger an interrupt,
|
||||
* and the actual context switch is executed after doirq is completed,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t ipsr = getipsr();
|
||||
|
||||
if (tcb->xcp.saved_regs != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ retry:
|
|||
}
|
||||
|
||||
rtcb->xcp.regs = rtcb->xcp.saved_regs;
|
||||
rtcb->xcp.saved_regs = NULL;
|
||||
arm_fullcontextrestore();
|
||||
UNUSED(regs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,15 +97,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
/* Dispatch the PendSV interrupt */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
#endif
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
/* Pendsv able to access running tcb with no critical section */
|
||||
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
up_irq_save();
|
||||
|
|
@ -117,6 +108,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
|||
|
||||
tcb = this_task();
|
||||
|
||||
#ifdef CONFIG_ENABLE_ALL_SIGNALS
|
||||
if (tcb->sigdeliver)
|
||||
{
|
||||
up_schedule_sigaction(tcb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update scheduler parameters.
|
||||
* The arm-m architecture svc call will trigger an interrupt,
|
||||
* and the actual context switch is executed after doirq is completed,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t ipsr = getipsr();
|
||||
|
||||
if (tcb->xcp.saved_regs != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, handle some special cases when the signal is
|
||||
* being delivered to the currently executing task.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ retry:
|
|||
}
|
||||
|
||||
rtcb->xcp.regs = rtcb->xcp.saved_regs;
|
||||
rtcb->xcp.saved_regs = NULL;
|
||||
arm_fullcontextrestore();
|
||||
UNUSED(regs);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue