arch: update g_running_tasks when context switch occurred

When supporting high-priority interrupts, updating the
g_running_tasks within a high-priority interrupt may be
cause problems. The g_running_tasks should only be updated
when it is determined that a task context switch has occurred.

Signed-off-by: zhangyuan21 <zhangyuan21@xiaomi.com>
This commit is contained in:
zhangyuan21 2023-07-13 17:49:30 +08:00 committed by Xiang Xiao
parent 34c56139aa
commit 8f39ba6ae4
26 changed files with 211 additions and 53 deletions

View File

@ -32,6 +32,7 @@
#include <nuttx/addrenv.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
@ -79,7 +80,6 @@ void arm_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#ifdef CONFIG_ARCH_ADDRENV
/* Check for a context switch. If a context switch occurred, then
* CURRENT_REGS will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -89,6 +89,7 @@ void arm_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
@ -96,9 +97,16 @@ void arm_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(NULL);
}
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
* interrupt handler.
*/

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
@ -81,6 +82,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section();
regs = (uint32_t *)CURRENT_REGS;
}

View File

@ -33,6 +33,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
#include "gic.h"
@ -70,15 +71,11 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#ifdef CONFIG_ARCH_ADDRENV
/* Check for a context switch. If a context switch occurred, then
* CURRENT_REGS will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then establish the correct
* address environment before returning from the interrupt.
*/
/* Restore the cpu lock */
if (regs != CURRENT_REGS)
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
@ -86,13 +83,15 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
*/
addrenv_switch(NULL);
}
#endif
/* Restore the cpu lock */
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
if (regs != CURRENT_REGS)
{
restore_critical_section();
regs = (uint32_t *)CURRENT_REGS;
}

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
@ -81,6 +82,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section();
regs = (uint32_t *)CURRENT_REGS;
}

View File

@ -31,6 +31,7 @@
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
@ -63,6 +64,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section();
regs = (uint32_t *)CURRENT_REGS;
}

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "arm_internal.h"
#include "exc_return.h"
@ -82,6 +83,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section();
regs = (uint32_t *)CURRENT_REGS;
}

View File

@ -92,6 +92,13 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
/* Restore the cpu lock */
restore_critical_section();

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "avr_internal.h"
@ -87,6 +88,16 @@ uint8_t *avr_doirq(uint8_t irq, uint8_t *regs)
* switch occurred during interrupt processing.
*/
if (regs != (uint8_t *)g_current_regs)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
regs = (uint8_t *)g_current_regs; /* Cast removes volatile attribute */
/* Restore the previous value of g_current_regs. NULL would indicate that

View File

@ -32,6 +32,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "avr_internal.h"
@ -74,7 +75,6 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry.
* If an interrupt level context switch has occurred, then restore
@ -99,8 +99,14 @@ uint32_t *avr_doirq(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -78,6 +78,13 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section();
regs = CURRENT_REGS;
}

View File

@ -32,6 +32,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "hc_internal.h"
@ -74,7 +75,6 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -99,8 +99,14 @@ uint8_t *hc_doirq(int irq, uint8_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -32,6 +32,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "mips_internal.h"
@ -80,7 +81,6 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -105,8 +105,14 @@ uint32_t *mips_doirq(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -35,6 +35,7 @@
#include <arch/irq.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "lm32.h"
@ -65,7 +66,6 @@ uint32_t *lm32_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -90,8 +90,14 @@ uint32_t *lm32_doirq(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -35,6 +35,7 @@
#include <arch/irq.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "minerva.h"
@ -64,7 +65,6 @@ uint32_t *minerva_doirq(int irq, uint32_t * regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -74,13 +74,13 @@ uint32_t *minerva_doirq(int irq, uint32_t * regs)
if (regs != g_current_regs)
{
# ifdef CONFIG_ARCH_FPU
#ifdef CONFIG_ARCH_FPU
/* Restore floating point registers */
up_restorefpu((uint32_t *) g_current_regs);
# endif
#endif
# ifdef CONFIG_ARCH_ADDRENV
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously running
* task is closed down gracefully (data caches dump, MMU flushed) and
* set up the address environment for the new thread at the head of
@ -88,10 +88,16 @@ uint32_t *minerva_doirq(int irq, uint32_t * regs)
*/
addrenv_switch(NULL);
# endif
}
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
/* If a context switch occurred while processing the interrupt then
* g_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

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "or1k_internal.h"
@ -69,6 +70,16 @@ uint32_t *or1k_doirq(int irq, uint32_t *regs)
* switch occurred during interrupt processing.
*/
if (regs != (uint32_t *)CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
regs = (uint32_t *)CURRENT_REGS;
/* Restore the previous value of CURRENT_REGS. NULL would indicate that

View File

@ -31,6 +31,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "renesas_internal.h"
#include "group/group.h"
@ -77,7 +78,6 @@ uint32_t *renesas_doirq(int irq, uint32_t * regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry.
* If an interrupt level context switch has occurred, then restore the
@ -102,9 +102,15 @@ uint32_t *renesas_doirq(int irq, uint32_t * regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* Get the current value of regs... it may have changed because
* of a context switch performed during interrupt processing.
*/

View File

@ -32,6 +32,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "riscv_internal.h"
@ -89,9 +90,9 @@ uintptr_t *riscv_doirq(int irq, uintptr_t *regs)
* returning from the interrupt.
*/
#ifdef CONFIG_ARCH_ADDRENV
if (regs != CURRENT_REGS)
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully (data caches dump,
* MMU flushed) and set up the address environment for the new
@ -99,11 +100,15 @@ uintptr_t *riscv_doirq(int irq, uintptr_t *regs)
*/
addrenv_switch(NULL);
}
#endif
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
/* Restore the cpu lock */
restore_critical_section();

View File

@ -234,6 +234,7 @@ endif()
target_include_directories(nuttx PRIVATE ${CMAKE_BINARY_DIR}/include/nuttx)
target_include_directories(nuttx PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(sim_head PUBLIC ${NUTTX_DIR}/sched)
target_sources(sim_head PUBLIC sim_head.c sim_doirq.c)
target_sources(arch PRIVATE ${SRCS})

View File

@ -26,6 +26,7 @@
#include <stdbool.h>
#include <nuttx/arch.h>
#include <sched/sched.h>
#include "sim_internal.h"
@ -64,6 +65,16 @@ void *sim_doirq(int irq, void *context)
* context switch occurred during interrupt processing.
*/
if (regs != CURRENT_REGS)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
regs = (void *)CURRENT_REGS;
/* Restore the previous value of CURRENT_REGS. NULL would indicate

View File

@ -32,6 +32,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "sparc_internal.h"
@ -75,7 +76,6 @@ uint32_t *sparc_doirq(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* CURRENT_REGS will have a different value than it did on entry.
* If an interrupt level context switch has occurred, then restore
@ -100,8 +100,14 @@ uint32_t *sparc_doirq(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* CURRENT_REGS may have change value. If we return any value different

View File

@ -30,6 +30,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/io.h>
#include <sched/sched.h>
#include "x86_internal.h"
@ -90,7 +91,6 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -115,8 +115,14 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -77,7 +77,6 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* g_current_regs will have a different value than it did on entry. If an
* interrupt level context switch has occurred, then restore the floating
@ -102,8 +101,14 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* If a context switch occurred while processing the interrupt then
* g_current_regs may have change value. If we return any value different

View File

@ -66,7 +66,6 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
irq_dispatch(irq, regs);
#if defined(CONFIG_ARCH_ADDRENV)
/* Check for a context switch. If a context switch occurred, then
* CURRENT_REGS will have a different value than it did on entry.
*/
@ -82,8 +81,14 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
#endif
/* Restore the cpu lock */

View File

@ -30,6 +30,7 @@
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include <sched/sched.h>
#include "chip.h"
#include "z16_internal.h"
@ -84,6 +85,16 @@ FAR chipreg_t *z16_doirq(int irq, FAR chipreg_t *regs)
irq_dispatch(irq, regs);
if (regs != g_current_regs)
{
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
/* Restore the previous value of g_current_regs. NULL would indicate
* that we are no longer in an interrupt handler. It will be non-NULL
* if we are returning from a nested interrupt.

View File

@ -33,6 +33,7 @@
#include <nuttx/board.h>
#include <arch/irq.h>
#include <sched/sched.h>
#include "chip/switch.h"
#include "z80_internal.h"
@ -69,13 +70,13 @@ FAR chipreg_t *z80_doirq(uint8_t irq, FAR chipreg_t *regs)
irq_dispatch(irq, regs);
#ifdef CONFIG_ARCH_ADDRENV
/* If a context switch occurred, 'newregs' will hold the new context */
newregs = IRQ_STATE();
if (newregs != regs)
{
#ifdef CONFIG_ARCH_ADDRENV
/* Make sure that the address environment for the previously
* running task is closed down gracefully and set up the
* address environment for the new thread at the head of the
@ -83,16 +84,18 @@ FAR chipreg_t *z80_doirq(uint8_t irq, FAR chipreg_t *regs)
*/
addrenv_switch(NULL);
#endif
/* Record the new "running" task when context switch occurred.
* g_running_tasks[] is only used by assertion logic for reporting
* crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}
regs = newregs;
#else
/* If a context switch occurred, 'regs' will hold the new context */
regs = IRQ_STATE();
#endif
/* Indicate that we are no longer in interrupt processing logic */
IRQ_LEAVE(irq);

View File

@ -182,10 +182,4 @@ void irq_dispatch(int irq, FAR void *context)
kmm_checkcorruption();
}
#endif
/* Record the new "running" task. g_running_tasks[] is only used by
* assertion logic for reporting crashes.
*/
g_running_tasks[this_cpu()] = this_task();
}