riscv: use g_running_task store current regs
This commit fixes the regression from https://github.com/apache/nuttx/pull/13561 In order to determine whether a context switch has occurred, we can use g_running_task to store the current regs. This allows us to compare the current register state with the previously stored state to identify if a context switch has taken place. Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
57f84aaca8
commit
d1fec65e1b
@ -58,6 +58,7 @@
|
||||
|
||||
uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
|
||||
{
|
||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
||||
struct tcb_s *tcb = this_task();
|
||||
|
||||
board_autoled_on(LED_INIRQ);
|
||||
@ -71,9 +72,10 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
|
||||
{
|
||||
regs[REG_EPC] += 4;
|
||||
}
|
||||
else
|
||||
|
||||
if (*running_task != NULL)
|
||||
{
|
||||
tcb->xcp.regs = regs;
|
||||
(*running_task)->xcp.regs = regs;
|
||||
}
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
@ -97,7 +99,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
|
||||
* returning from the interrupt.
|
||||
*/
|
||||
|
||||
if (regs != tcb->xcp.regs)
|
||||
if ((*running_task) != tcb)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
@ -114,15 +116,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
|
||||
* crashes.
|
||||
*/
|
||||
|
||||
g_running_tasks[this_cpu()] = tcb;
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* current_regs may have change value. If we return any value
|
||||
* different from the input regs, then the lower level will know
|
||||
* that a context switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = tcb->xcp.regs;
|
||||
*running_task = tcb;
|
||||
}
|
||||
|
||||
/* Set current_regs to NULL to indicate that we are no longer in an
|
||||
@ -133,5 +127,5 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
|
||||
|
||||
#endif
|
||||
board_autoled_off(LED_INIRQ);
|
||||
return regs;
|
||||
return tcb->xcp.regs;
|
||||
}
|
||||
|
@ -78,6 +78,10 @@ void up_exit(int status)
|
||||
|
||||
nxsched_resume_scheduler(tcb);
|
||||
|
||||
/* g_running_tasks is not valid now */
|
||||
|
||||
g_running_tasks[this_cpu()] = NULL;
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
riscv_fullcontextrestore(tcb);
|
||||
|
@ -109,10 +109,6 @@
|
||||
#define PMP_ACCESS_DENIED (-1) /* Access set and denied */
|
||||
#define PMP_ACCESS_FULL (1) /* Access set and allowed */
|
||||
|
||||
/* Return values from riscv_swint */
|
||||
|
||||
#define SWINT_CONTEXT_SWITCH (1) /* Indicate we need context switch */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Use ASM as rv64ilp32 compiler generated address is limited */
|
||||
|
@ -162,6 +162,10 @@ retry:
|
||||
rtcb->irqcount--;
|
||||
#endif
|
||||
|
||||
/* g_running_tasks is not valid now */
|
||||
|
||||
g_running_tasks[this_cpu()] = NULL;
|
||||
|
||||
rtcb->xcp.regs = regs;
|
||||
riscv_fullcontextrestore(rtcb);
|
||||
}
|
||||
|
@ -257,7 +257,6 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
struct tcb_s *next = (struct tcb_s *)(uintptr_t)regs[REG_A2];
|
||||
|
||||
DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
|
||||
prev->xcp.regs = regs;
|
||||
riscv_savecontext(prev);
|
||||
new_regs = next->xcp.regs;
|
||||
riscv_restorecontext(next);
|
||||
@ -496,7 +495,6 @@ int riscv_swint(int irq, void *context, void *arg)
|
||||
if (regs != new_regs)
|
||||
{
|
||||
restore_critical_section(this_task(), this_cpu());
|
||||
return SWINT_CONTEXT_SWITCH;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
@ -37,9 +37,13 @@
|
||||
|
||||
void *riscv_perform_syscall(uintreg_t *regs)
|
||||
{
|
||||
struct tcb_s **running_task = &g_running_tasks[this_cpu()];
|
||||
struct tcb_s *tcb;
|
||||
int cpu;
|
||||
int ret;
|
||||
|
||||
if (*running_task != NULL)
|
||||
{
|
||||
(*running_task)->xcp.regs = regs;
|
||||
}
|
||||
|
||||
/* Set up the interrupt register set needed by swint() */
|
||||
|
||||
@ -47,9 +51,10 @@ void *riscv_perform_syscall(uintreg_t *regs)
|
||||
|
||||
/* Run the system call handler (swint) */
|
||||
|
||||
ret = riscv_swint(0, regs, NULL);
|
||||
riscv_swint(0, regs, NULL);
|
||||
tcb = this_task();
|
||||
|
||||
if (ret == SWINT_CONTEXT_SWITCH)
|
||||
if ((*running_task) != tcb)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
/* Make sure that the address environment for the previously
|
||||
@ -65,20 +70,10 @@ void *riscv_perform_syscall(uintreg_t *regs)
|
||||
* assertion logic for reporting crashes.
|
||||
*/
|
||||
|
||||
cpu = this_cpu();
|
||||
tcb = current_task(cpu);
|
||||
g_running_tasks[cpu] = tcb;
|
||||
|
||||
/* If a context switch occurred while processing the interrupt then
|
||||
* current_regs may have change value. If we return any value
|
||||
* different from the input regs, then the lower level will know
|
||||
* that a context switch occurred during interrupt processing.
|
||||
*/
|
||||
|
||||
regs = tcb->xcp.regs;
|
||||
*running_task = tcb;
|
||||
}
|
||||
|
||||
up_set_current_regs(NULL);
|
||||
|
||||
return regs;
|
||||
return tcb->xcp.regs;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user