From 6f444492c6d6716970217a05afe08e3001caf9a4 Mon Sep 17 00:00:00 2001 From: hujun5 Date: Thu, 21 Nov 2024 16:48:42 +0800 Subject: [PATCH] arm: remove g_running_tasks[this_cpu()] = NULL reason: We hope to keep g_running_tasks valid forever. Signed-off-by: hujun5 --- arch/arm/src/arm/arm_sigdeliver.c | 1 - arch/arm/src/arm/arm_syscall.c | 41 ++++++++++++++++-------- arch/arm/src/armv6-m/arm_doirq.c | 6 +++- arch/arm/src/armv6-m/arm_sigdeliver.c | 2 +- arch/arm/src/armv7-a/arm_sigdeliver.c | 1 - arch/arm/src/armv7-a/arm_syscall.c | 46 ++++++++++++++++----------- arch/arm/src/armv7-m/arm_doirq.c | 6 +++- arch/arm/src/armv7-m/arm_sigdeliver.c | 1 - arch/arm/src/armv7-r/arm_sigdeliver.c | 1 - arch/arm/src/armv7-r/arm_syscall.c | 45 +++++++++++++++----------- arch/arm/src/armv8-m/arm_doirq.c | 6 +++- arch/arm/src/armv8-m/arm_sigdeliver.c | 2 +- arch/arm/src/armv8-r/arm_sigdeliver.c | 1 - arch/arm/src/armv8-r/arm_syscall.c | 45 +++++++++++++++----------- arch/arm/src/common/arm_exit.c | 2 +- 15 files changed, 127 insertions(+), 79 deletions(-) diff --git a/arch/arm/src/arm/arm_sigdeliver.c b/arch/arm/src/arm/arm_sigdeliver.c index a76152b535439..a0ab5f36fb7c4 100644 --- a/arch/arm/src/arm/arm_sigdeliver.c +++ b/arch/arm/src/arm/arm_sigdeliver.c @@ -97,7 +97,6 @@ void arm_sigdeliver(void) board_autoled_off(LED_SIGNAL); - g_running_tasks[this_cpu()] = NULL; rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); } diff --git a/arch/arm/src/arm/arm_syscall.c b/arch/arm/src/arm/arm_syscall.c index 7443e27c1dfc8..4e47f4a089216 100644 --- a/arch/arm/src/arm/arm_syscall.c +++ b/arch/arm/src/arm/arm_syscall.c @@ -56,18 +56,16 @@ uint32_t *arm_syscall(uint32_t *regs) { struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb = this_task(); + bool switch_context = false; uint32_t cmd; /* Nested interrupts are not supported */ DEBUGASSERT(!up_interrupt_context()); - if (*running_task != NULL) - { - (*running_task)->xcp.regs = regs; - } - - /* Set irq flag */ + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ up_set_interrupt_context(true); @@ -75,12 +73,34 @@ uint32_t *arm_syscall(uint32_t *regs) cmd = regs[REG_R0]; + /* if cmd == SYS_restore_context (*running_task)->xcp.regs is valid + * should not be overwriten + */ + + if (cmd != SYS_restore_context) + { + (*running_task)->xcp.regs = regs; + } + /* Handle the SVCall according to the command in R0 */ switch (cmd) { case SYS_restore_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(tcb); + break; case SYS_switch_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(*running_task); + nxsched_resume_scheduler(tcb); + *running_task = tcb; break; default: @@ -92,7 +112,7 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - if (*running_task != tcb) + if (switch_context) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -103,13 +123,6 @@ uint32_t *arm_syscall(uint32_t *regs) addrenv_switch(NULL); #endif - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(*running_task); - nxsched_resume_scheduler(tcb); - - *running_task = tcb; - /* Restore the cpu lock */ restore_critical_section(tcb, this_cpu()); diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c index 9c9e78d3cfd00..e3e6383e48a71 100644 --- a/arch/arm/src/armv6-m/arm_doirq.c +++ b/arch/arm/src/armv6-m/arm_doirq.c @@ -59,7 +59,11 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb; - if (*running_task != NULL) + /* This judgment proves that (*running_task)->xcp.regs + * is invalid, and we can safely overwrite it. + */ + + if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context)) { (*running_task)->xcp.regs = regs; } diff --git a/arch/arm/src/armv6-m/arm_sigdeliver.c b/arch/arm/src/armv6-m/arm_sigdeliver.c index 5fd3f44463ba3..73ad65e14ad73 100644 --- a/arch/arm/src/armv6-m/arm_sigdeliver.c +++ b/arch/arm/src/armv6-m/arm_sigdeliver.c @@ -162,7 +162,7 @@ void arm_sigdeliver(void) leave_critical_section((uint16_t)regs[REG_PRIMASK]); rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; + rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c index 5c0e058a4e6af..5de0caa880af6 100644 --- a/arch/arm/src/armv7-a/arm_sigdeliver.c +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -161,7 +161,6 @@ void arm_sigdeliver(void) rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index f31e4031553ab..540ba4864bc06 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -161,6 +161,7 @@ uint32_t *arm_syscall(uint32_t *regs) { struct tcb_s **running_task = &g_running_tasks[this_cpu()]; struct tcb_s *tcb = this_task(); + bool switch_context = false; uint32_t cmd; #ifdef CONFIG_BUILD_KERNEL uint32_t cpsr; @@ -170,12 +171,9 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(!up_interrupt_context()); - if (*running_task != NULL) - { - (*running_task)->xcp.regs = regs; - } - - /* Set irq flag */ + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ up_set_interrupt_context(true); @@ -183,6 +181,15 @@ uint32_t *arm_syscall(uint32_t *regs) cmd = regs[REG_R0]; + /* if cmd == SYS_restore_context (*running_task)->xcp.regs is valid + * should not be overwriten + */ + + if (cmd != SYS_restore_context) + { + (*running_task)->xcp.regs = regs; + } + /* The SVCall software interrupt is called with R0 = system call command * and R1..R7 = variable number of arguments depending on the system call. */ @@ -255,8 +262,22 @@ uint32_t *arm_syscall(uint32_t *regs) } break; #endif + case SYS_restore_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(tcb); + break; case SYS_switch_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(*running_task); + nxsched_resume_scheduler(tcb); + *running_task = tcb; break; /* R0=SYS_task_start: This a user task start @@ -522,7 +543,7 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - if (*running_task != tcb) + if (switch_context) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -534,17 +555,6 @@ uint32_t *arm_syscall(uint32_t *regs) addrenv_switch(NULL); #endif - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(*running_task); - nxsched_resume_scheduler(tcb); - - /* Record the new "running" task. g_running_tasks[] is only used by - * assertion logic for reporting crashes. - */ - - *running_task = tcb; - /* Restore the cpu lock */ restore_critical_section(tcb, this_cpu()); diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c index 9989437e4752c..dcbdd9dc12a8f 100644 --- a/arch/arm/src/armv7-m/arm_doirq.c +++ b/arch/arm/src/armv7-m/arm_doirq.c @@ -59,7 +59,11 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb; - if (*running_task != NULL) + /* This judgment proves that (*running_task)->xcp.regs + * is invalid, and we can safely overwrite it. + */ + + if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context)) { (*running_task)->xcp.regs = regs; } diff --git a/arch/arm/src/armv7-m/arm_sigdeliver.c b/arch/arm/src/armv7-m/arm_sigdeliver.c index 5642e82623e92..3d617ea46a5e4 100644 --- a/arch/arm/src/armv7-m/arm_sigdeliver.c +++ b/arch/arm/src/armv7-m/arm_sigdeliver.c @@ -175,7 +175,6 @@ void arm_sigdeliver(void) rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv7-r/arm_sigdeliver.c b/arch/arm/src/armv7-r/arm_sigdeliver.c index 009ad90657d87..bd715470cd519 100644 --- a/arch/arm/src/armv7-r/arm_sigdeliver.c +++ b/arch/arm/src/armv7-r/arm_sigdeliver.c @@ -158,7 +158,6 @@ void arm_sigdeliver(void) rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c index 315a6f42d4723..1761e5915c9bb 100644 --- a/arch/arm/src/armv7-r/arm_syscall.c +++ b/arch/arm/src/armv7-r/arm_syscall.c @@ -158,6 +158,7 @@ uint32_t *arm_syscall(uint32_t *regs) { struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb = this_task(); + bool switch_context = false; uint32_t cmd; #ifdef CONFIG_BUILD_PROTECTED uint32_t cpsr; @@ -167,12 +168,9 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(!up_interrupt_context()); - if (*running_task != NULL) - { - (*running_task)->xcp.regs = regs; - } - - /* Set irq flag */ + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ up_set_interrupt_context(true); @@ -180,6 +178,15 @@ uint32_t *arm_syscall(uint32_t *regs) cmd = regs[REG_R0]; + /* if cmd == SYS_restore_context (*running_task)->xcp.regs is valid + * should not be overwriten + */ + + if (cmd != SYS_restore_context) + { + (*running_task)->xcp.regs = regs; + } + /* The SVCall software interrupt is called with R0 = system call command * and R1..R7 = variable number of arguments depending on the system call. */ @@ -254,7 +261,20 @@ uint32_t *arm_syscall(uint32_t *regs) #endif case SYS_restore_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(tcb); + break; case SYS_switch_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(*running_task); + nxsched_resume_scheduler(tcb); + *running_task = tcb; break; /* R0=SYS_task_start: This a user task start @@ -520,19 +540,8 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - if (*running_task != tcb) + if (switch_context) { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(*running_task); - nxsched_resume_scheduler(tcb); - - /* Record the new "running" task. g_running_tasks[] is only used by - * assertion logic for reporting crashes. - */ - - *running_task = tcb; - /* Restore the cpu lock */ restore_critical_section(tcb, this_cpu()); diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c index 3cd28ae2989f3..55183573a54fb 100644 --- a/arch/arm/src/armv8-m/arm_doirq.c +++ b/arch/arm/src/armv8-m/arm_doirq.c @@ -70,7 +70,11 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb; - if (*running_task != NULL) + /* This judgment proves that (*running_task)->xcp.regs + * is invalid, and we can safely overwrite it. + */ + + if (!(NVIC_IRQ_SVCALL == irq && regs[REG_R0] == SYS_restore_context)) { (*running_task)->xcp.regs = regs; } diff --git a/arch/arm/src/armv8-m/arm_sigdeliver.c b/arch/arm/src/armv8-m/arm_sigdeliver.c index aff8738235c16..43d72e35a8da8 100644 --- a/arch/arm/src/armv8-m/arm_sigdeliver.c +++ b/arch/arm/src/armv8-m/arm_sigdeliver.c @@ -174,7 +174,7 @@ void arm_sigdeliver(void) #endif rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; + rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv8-r/arm_sigdeliver.c b/arch/arm/src/armv8-r/arm_sigdeliver.c index 5e4015e986a55..17fbc7b19839e 100644 --- a/arch/arm/src/armv8-r/arm_sigdeliver.c +++ b/arch/arm/src/armv8-r/arm_sigdeliver.c @@ -156,7 +156,6 @@ void arm_sigdeliver(void) rtcb->irqcount--; #endif - g_running_tasks[this_cpu()] = NULL; rtcb->xcp.regs = rtcb->xcp.saved_regs; arm_fullcontextrestore(); UNUSED(regs); diff --git a/arch/arm/src/armv8-r/arm_syscall.c b/arch/arm/src/armv8-r/arm_syscall.c index e478aafecf618..3b2033ee52d3b 100644 --- a/arch/arm/src/armv8-r/arm_syscall.c +++ b/arch/arm/src/armv8-r/arm_syscall.c @@ -158,6 +158,7 @@ uint32_t *arm_syscall(uint32_t *regs) { struct tcb_s **running_task = &g_running_tasks[this_cpu()]; FAR struct tcb_s *tcb = this_task(); + bool switch_context = false; uint32_t cmd; #ifdef CONFIG_BUILD_PROTECTED uint32_t cpsr; @@ -167,12 +168,9 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(!up_interrupt_context()); - if (*running_task != NULL) - { - (*running_task)->xcp.regs = regs; - } - - /* Set irq flag */ + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ up_set_interrupt_context(true); @@ -180,6 +178,15 @@ uint32_t *arm_syscall(uint32_t *regs) cmd = regs[REG_R0]; + /* if cmd == SYS_restore_context (*running_task)->xcp.regs is valid + * should not be overwriten + */ + + if (cmd != SYS_restore_context) + { + (*running_task)->xcp.regs = regs; + } + /* The SVCall software interrupt is called with R0 = system call command * and R1..R7 = variable number of arguments depending on the system call. */ @@ -254,7 +261,20 @@ uint32_t *arm_syscall(uint32_t *regs) #endif case SYS_restore_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(tcb); + break; case SYS_switch_context: + switch_context = true; + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(*running_task); + nxsched_resume_scheduler(tcb); + *running_task = tcb; break; /* R0=SYS_task_start: This a user task start @@ -520,19 +540,8 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - if (*running_task != tcb) + if (switch_context) { - /* Update scheduler parameters */ - - nxsched_suspend_scheduler(*running_task); - nxsched_resume_scheduler(tcb); - - /* Record the new "running" task. g_running_tasks[] is only used by - * assertion logic for reporting crashes. - */ - - *running_task = tcb; - /* Restore the cpu lock */ restore_critical_section(tcb, this_cpu()); diff --git a/arch/arm/src/common/arm_exit.c b/arch/arm/src/common/arm_exit.c index fa49dc5fed785..1b6cafbf80432 100644 --- a/arch/arm/src/common/arm_exit.c +++ b/arch/arm/src/common/arm_exit.c @@ -60,7 +60,7 @@ void up_exit(int status) /* Scheduler parameters will update inside syscall */ - g_running_tasks[this_cpu()] = NULL; + g_running_tasks[this_cpu()] = this_task(); /* Then switch contexts */