arch/arm: update running task when context switch occurred

The text describes an issue related to the running task in code.
The running task is only used when calling the _assert function
to indicate the task that was running before an exception occurred.
However, the current code only updates the running task during
irq_dispatch, which is suitable for ARM-M architecture but not
for ARM-A or ARM-R architecture, because their context switches
are not done through irq handler. Therefore, if the following
process is followed, the value of the running task will be incorrect:

1. task1 is running, this_task()=task1
2. do_irq is executed, setting running task()=task1
3. task1 switches to task2
4. task2 is running and generates a data abort
5. In the data abort, the _assert function is called,
   and the running task obtained is still task1, but
   the actual task that generated the exception is task2.

Signed-off-by: zhangyuan21 <zhangyuan21@xiaomi.com>
This commit is contained in:
zhangyuan21 2023-04-11 05:44:52 +08:00 committed by Masayuki Ishikawa
parent 899be58905
commit c00498c164
4 changed files with 31 additions and 3 deletions

View File

@ -33,6 +33,7 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include "arm_internal.h" #include "arm_internal.h"
#include "sched/sched.h"
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
@ -173,6 +174,12 @@ uint32_t *arm_syscall(uint32_t *regs)
if (regs != CURRENT_REGS) if (regs != CURRENT_REGS)
{ {
/* Record the new "running" task. g_running_tasks[] is only used by
* assertion logic for reporting crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section(); restore_critical_section();
regs = (uint32_t *)CURRENT_REGS; regs = (uint32_t *)CURRENT_REGS;
} }

View File

@ -39,6 +39,7 @@
#include "addrenv.h" #include "addrenv.h"
#include "arm.h" #include "arm.h"
#include "arm_internal.h" #include "arm_internal.h"
#include "sched/sched.h"
#include "signal/signal.h" #include "signal/signal.h"
/**************************************************************************** /****************************************************************************
@ -604,6 +605,12 @@ uint32_t *arm_syscall(uint32_t *regs)
if (regs != CURRENT_REGS) if (regs != CURRENT_REGS)
{ {
/* Record the new "running" task. g_running_tasks[] is only used by
* assertion logic for reporting crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section(); restore_critical_section();
regs = (uint32_t *)CURRENT_REGS; regs = (uint32_t *)CURRENT_REGS;
} }

View File

@ -35,6 +35,7 @@
#include "arm.h" #include "arm.h"
#include "arm_internal.h" #include "arm_internal.h"
#include "sched/sched.h"
#include "signal/signal.h" #include "signal/signal.h"
/**************************************************************************** /****************************************************************************
@ -581,6 +582,12 @@ uint32_t *arm_syscall(uint32_t *regs)
if (regs != CURRENT_REGS) if (regs != CURRENT_REGS)
{ {
/* Record the new "running" task. g_running_tasks[] is only used by
* assertion logic for reporting crashes.
*/
g_running_tasks[this_cpu()] = this_task();
restore_critical_section(); restore_critical_section();
regs = (uint32_t *)CURRENT_REGS; regs = (uint32_t *)CURRENT_REGS;
} }

View File

@ -35,11 +35,12 @@
#include <nuttx/sched.h> #include <nuttx/sched.h>
#include <nuttx/addrenv.h> #include <nuttx/addrenv.h>
#include "arch/irq.h"
#include "signal/signal.h"
#include "addrenv.h" #include "addrenv.h"
#include "arch/irq.h"
#include "arm64_internal.h" #include "arm64_internal.h"
#include "arm64_fatal.h" #include "arm64_fatal.h"
#include "sched/sched.h"
#include "signal/signal.h"
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@ -214,7 +215,13 @@ uint64_t *arm64_syscall_switch(uint64_t * regs)
addrenv_switch(NULL); addrenv_switch(NULL);
#endif #endif
/* Restore the cpu lock */ /* Record the new "running" task. 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(); restore_critical_section();
} }