arm-v6/7/8m: sigaction forward to pendsv
For exception directly, tcb->xcp.regs should not be used. Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
parent
55822753be
commit
af3c159cff
6 changed files with 63 additions and 15 deletions
|
@ -57,7 +57,7 @@ void exception_direct(void)
|
||||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
{
|
{
|
||||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
||||||
FAR struct tcb_s *tcb;
|
struct tcb_s *tcb = *running_task;
|
||||||
|
|
||||||
/* This judgment proves that (*running_task)->xcp.regs
|
/* This judgment proves that (*running_task)->xcp.regs
|
||||||
* is invalid, and we can safely overwrite it.
|
* is invalid, and we can safely overwrite it.
|
||||||
|
@ -65,7 +65,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
||||||
{
|
{
|
||||||
(*running_task)->xcp.regs = regs;
|
tcb->xcp.regs = regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
board_autoled_on(LED_INIRQ);
|
board_autoled_on(LED_INIRQ);
|
||||||
|
@ -84,6 +84,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
irq_dispatch(irq, regs);
|
irq_dispatch(irq, regs);
|
||||||
#endif
|
#endif
|
||||||
|
if (tcb->sigdeliver)
|
||||||
|
{
|
||||||
|
/* Pendsv able to access running tcb with no critical section */
|
||||||
|
|
||||||
|
up_schedule_sigaction(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
up_irq_save();
|
up_irq_save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
#include "irq/irq.h"
|
#include "irq/irq.h"
|
||||||
|
#include "nvic.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
|
@ -80,13 +81,14 @@
|
||||||
|
|
||||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = running_task();
|
struct tcb_s *rtcb = running_task();
|
||||||
|
uint32_t ipsr = getipsr();
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
/* First, handle some special cases when the signal is
|
||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && !up_interrupt_context())
|
if (tcb == rtcb && ipsr == 0)
|
||||||
{
|
{
|
||||||
/* In this case just deliver the signal now.
|
/* In this case just deliver the signal now.
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
* REVISIT: Signal handle will run in a critical section!
|
||||||
|
@ -95,7 +97,15 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
(tcb->sigdeliver)(tcb);
|
(tcb->sigdeliver)(tcb);
|
||||||
tcb->sigdeliver = NULL;
|
tcb->sigdeliver = NULL;
|
||||||
}
|
}
|
||||||
else
|
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
|
{
|
||||||
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||||
|
}
|
||||||
|
else /* ipsr == NVIC_IRQ_PENDSV || tcb != rtcb */
|
||||||
{
|
{
|
||||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||||
* registers (and perhaps also the LR). These will be restored
|
* registers (and perhaps also the LR). These will be restored
|
||||||
|
|
|
@ -57,7 +57,7 @@ void exception_direct(void)
|
||||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
{
|
{
|
||||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
||||||
FAR struct tcb_s *tcb;
|
struct tcb_s *tcb = *running_task;
|
||||||
|
|
||||||
/* This judgment proves that (*running_task)->xcp.regs
|
/* This judgment proves that (*running_task)->xcp.regs
|
||||||
* is invalid, and we can safely overwrite it.
|
* is invalid, and we can safely overwrite it.
|
||||||
|
@ -65,7 +65,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
||||||
{
|
{
|
||||||
(*running_task)->xcp.regs = regs;
|
tcb->xcp.regs = regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
board_autoled_on(LED_INIRQ);
|
board_autoled_on(LED_INIRQ);
|
||||||
|
@ -84,6 +84,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
irq_dispatch(irq, regs);
|
irq_dispatch(irq, regs);
|
||||||
#endif
|
#endif
|
||||||
|
if (tcb->sigdeliver)
|
||||||
|
{
|
||||||
|
/* Pendsv able to access running tcb with no critical section */
|
||||||
|
|
||||||
|
up_schedule_sigaction(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
up_irq_save();
|
up_irq_save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
#include "irq/irq.h"
|
#include "irq/irq.h"
|
||||||
|
#include "nvic.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
|
@ -81,13 +82,14 @@
|
||||||
|
|
||||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = running_task();
|
struct tcb_s *rtcb = running_task();
|
||||||
|
uint32_t ipsr = getipsr();
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
/* First, handle some special cases when the signal is
|
||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && !up_interrupt_context())
|
if (tcb == rtcb && ipsr == 0)
|
||||||
{
|
{
|
||||||
/* In this case just deliver the signal now.
|
/* In this case just deliver the signal now.
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
* REVISIT: Signal handle will run in a critical section!
|
||||||
|
@ -96,7 +98,15 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
(tcb->sigdeliver)(tcb);
|
(tcb->sigdeliver)(tcb);
|
||||||
tcb->sigdeliver = NULL;
|
tcb->sigdeliver = NULL;
|
||||||
}
|
}
|
||||||
else
|
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
|
{
|
||||||
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||||
|
}
|
||||||
|
else /* ipsr == NVIC_IRQ_PENDSV || tcb != rtcb */
|
||||||
{
|
{
|
||||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||||
* registers (and perhaps also the LR). These will be restored
|
* registers (and perhaps also the LR). These will be restored
|
||||||
|
|
|
@ -68,7 +68,7 @@ void exception_direct(void)
|
||||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
{
|
{
|
||||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
||||||
FAR struct tcb_s *tcb;
|
struct tcb_s *tcb = *running_task;
|
||||||
|
|
||||||
/* This judgment proves that (*running_task)->xcp.regs
|
/* This judgment proves that (*running_task)->xcp.regs
|
||||||
* is invalid, and we can safely overwrite it.
|
* is invalid, and we can safely overwrite it.
|
||||||
|
@ -76,7 +76,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context))
|
||||||
{
|
{
|
||||||
(*running_task)->xcp.regs = regs;
|
tcb->xcp.regs = regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
board_autoled_on(LED_INIRQ);
|
board_autoled_on(LED_INIRQ);
|
||||||
|
@ -95,6 +95,12 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||||
|
|
||||||
irq_dispatch(irq, regs);
|
irq_dispatch(irq, regs);
|
||||||
#endif
|
#endif
|
||||||
|
if (tcb->sigdeliver)
|
||||||
|
{
|
||||||
|
/* Pendsv able to access running tcb with no critical section */
|
||||||
|
|
||||||
|
up_schedule_sigaction(tcb);
|
||||||
|
}
|
||||||
|
|
||||||
up_irq_save();
|
up_irq_save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
#include "irq/irq.h"
|
#include "irq/irq.h"
|
||||||
|
#include "nvic.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
|
@ -81,13 +82,14 @@
|
||||||
|
|
||||||
void up_schedule_sigaction(struct tcb_s *tcb)
|
void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = running_task();
|
struct tcb_s *rtcb = running_task();
|
||||||
|
uint32_t ipsr = getipsr();
|
||||||
|
|
||||||
/* First, handle some special cases when the signal is
|
/* First, handle some special cases when the signal is
|
||||||
* being delivered to the currently executing task.
|
* being delivered to the currently executing task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tcb == rtcb && !up_interrupt_context())
|
if (tcb == rtcb && ipsr == 0)
|
||||||
{
|
{
|
||||||
/* In this case just deliver the signal now.
|
/* In this case just deliver the signal now.
|
||||||
* REVISIT: Signal handle will run in a critical section!
|
* REVISIT: Signal handle will run in a critical section!
|
||||||
|
@ -96,7 +98,15 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
||||||
(tcb->sigdeliver)(tcb);
|
(tcb->sigdeliver)(tcb);
|
||||||
tcb->sigdeliver = NULL;
|
tcb->sigdeliver = NULL;
|
||||||
}
|
}
|
||||||
else
|
else if (tcb == rtcb && ipsr != NVIC_IRQ_PENDSV)
|
||||||
|
{
|
||||||
|
/* Context switch should be done in pendsv, for exception directly
|
||||||
|
* last regs is not saved tcb->xcp.regs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
|
||||||
|
}
|
||||||
|
else /* ipsr == NVIC_IRQ_PENDSV || tcb != rtcb */
|
||||||
{
|
{
|
||||||
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
/* Save the return PC, CPSR and either the BASEPRI or PRIMASK
|
||||||
* registers (and perhaps also the LR). These will be restored
|
* registers (and perhaps also the LR). These will be restored
|
||||||
|
|
Loading…
Reference in a new issue