This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 19b4911d7fdb9d6d596c9221f3d88a6fb37cf9a5
Author: hujun5 <[email protected]>
AuthorDate: Tue Sep 24 16:46:08 2024 +0800

    arch: remove up_current_regs in common code
    
    reason:
    
    When entering an exception or interrupt, there are two sets of registers:
    one is the "running regs", which we need to save,
    and the other is the "ready to running regs", which we may soon use.
    For consistency in logic, we can always store the "running regs" in the 
regs field of g_running_tasks,
    otherwise it may lead to errors in the storage location of the "running 
regs."
    
    When we need to access the "running regs," we should uniformly retrieve 
them from the regs field of g_running_tasks.
    
    As the next step, we will rename the set_current_regs/up_current_regs 
functions
    for each architecture to more appropriate names, solely for the purpose of 
identifying interrupts.
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm/src/arm/arm_sigdeliver.c                  |  2 +
 arch/arm/src/arm/arm_syscall.c                     | 32 ++++++----------
 arch/arm/src/armv6-m/arm_doirq.c                   | 16 ++++----
 arch/arm/src/armv6-m/arm_svcall.c                  |  9 +++--
 arch/arm/src/armv7-a/arm_sigdeliver.c              |  2 +
 arch/arm/src/armv7-a/arm_syscall.c                 | 23 +++++-------
 arch/arm/src/armv7-m/arm_doirq.c                   | 16 ++++----
 arch/arm/src/armv7-m/arm_svcall.c                  |  9 +++--
 arch/arm/src/armv7-r/arm_sigdeliver.c              |  2 +
 arch/arm/src/armv7-r/arm_syscall.c                 | 25 +++++--------
 arch/arm/src/armv8-m/arm_doirq.c                   | 16 ++++----
 arch/arm/src/armv8-m/arm_svcall.c                  |  9 +++--
 arch/arm/src/armv8-r/arm_sigdeliver.c              |  2 +
 arch/arm/src/armv8-r/arm_syscall.c                 | 24 +++++-------
 arch/arm64/src/common/arm64_sigdeliver.c           |  2 +
 arch/arm64/src/common/arm64_syscall.c              | 43 +++++++---------------
 arch/avr/src/avr/avr_doirq.c                       |  7 ++++
 arch/avr/src/avr32/avr_doirq.c                     |  7 ++++
 arch/ceva/src/common/ceva_doirq.c                  |  9 ++++-
 arch/ceva/src/common/ceva_exit.c                   |  2 +
 arch/hc/src/common/hc_doirq.c                      |  7 ++++
 arch/mips/src/mips32/mips_doirq.c                  |  7 ++++
 arch/mips/src/pic32mx/pic32mx_decodeirq.c          |  6 +++
 arch/mips/src/pic32mx/pic32mx_exception.c          |  6 +++
 arch/mips/src/pic32mz/pic32mz_decodeirq.c          |  7 ++++
 arch/mips/src/pic32mz/pic32mz_exception.c          |  6 +++
 arch/misoc/src/lm32/lm32_doirq.c                   |  7 ++++
 arch/misoc/src/minerva/minerva_doirq.c             |  7 ++++
 arch/or1k/src/common/or1k_doirq.c                  |  7 ++++
 arch/renesas/src/common/renesas_doirq.c            |  7 ++++
 arch/risc-v/src/common/riscv_doirq.c               |  4 +-
 .../src/common/supervisor/riscv_perform_syscall.c  |  4 +-
 arch/sim/src/sim/sim_doirq.c                       |  7 ++++
 arch/sparc/src/sparc_v8/sparc_v8_doirq.c           |  7 ++++
 arch/tricore/src/common/tricore_doirq.c            |  7 ++++
 arch/x86/src/qemu/qemu_handlers.c                  | 10 ++++-
 arch/x86_64/src/intel64/intel64_handlers.c         | 15 +++++++-
 arch/xtensa/src/common/xtensa_assert.c             |  7 ++++
 arch/xtensa/src/common/xtensa_irqdispatch.c        | 20 +++++-----
 arch/xtensa/src/common/xtensa_swint.c              | 14 +++----
 arch/z16/src/common/z16_doirq.c                    |  6 +++
 arch/z16/src/z16f/z16f_sysexec.c                   |  6 +++
 arch/z80/src/common/z80_doirq.c                    |  7 ++++
 fs/procfs/fs_procfstcbinfo.c                       | 12 +++---
 include/nuttx/sched.h                              |  8 ++++
 libs/libc/gdbstub/lib_gdbstub.c                    |  2 +-
 sched/init/nx_start.c                              |  2 +-
 sched/misc/assert.c                                |  4 +-
 sched/misc/coredump.c                              |  2 +-
 sched/sched/sched.h                                |  6 ---
 tools/gdb/thread.py                                |  2 +-
 51 files changed, 305 insertions(+), 171 deletions(-)

diff --git a/arch/arm/src/arm/arm_sigdeliver.c 
b/arch/arm/src/arm/arm_sigdeliver.c
index 22589d1e6e..b55e820604 100644
--- a/arch/arm/src/arm/arm_sigdeliver.c
+++ b/arch/arm/src/arm/arm_sigdeliver.c
@@ -97,5 +97,7 @@ void arm_sigdeliver(void)
   /* Then restore the correct state for this thread of execution. */
 
   board_autoled_off(LED_SIGNAL);
+
+  g_running_tasks[this_cpu()] = NULL;
   arm_fullcontextrestore(regs);
 }
diff --git a/arch/arm/src/arm/arm_syscall.c b/arch/arm/src/arm/arm_syscall.c
index 8a5849e4d2..a69cc31941 100644
--- a/arch/arm/src/arm/arm_syscall.c
+++ b/arch/arm/src/arm/arm_syscall.c
@@ -54,19 +54,23 @@
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
-  int cpu;
 
   /* Nested interrupts are not supported */
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
 
-  tcb->xcp.regs = regs;
   up_set_current_regs(regs);
 
   /* The SYSCALL command is in R0 on entry.  Parameters follow in R1..R7 */
@@ -118,11 +122,6 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       case SYS_switch_context:
-        {
-          DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
-        }
         break;
 
       default:
@@ -134,7 +133,7 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (regs != tcb->xcp.regs)
+  if (*running_task != tcb)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -145,25 +144,16 @@ uint32_t *arm_syscall(uint32_t *regs)
 
       addrenv_switch(NULL);
 #endif
-
-      /* Record the new "running" task.  g_running_tasks[] is only used by
-       * assertion logic for reporting crashes.
-       */
-
-      cpu = this_cpu();
-      tcb = current_task(cpu);
-
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      nxsched_suspend_scheduler(*running_task);
       nxsched_resume_scheduler(tcb);
 
-      g_running_tasks[cpu] = tcb;
+      *running_task = tcb;
 
       /* Restore the cpu lock */
 
-      restore_critical_section(tcb, cpu);
-      regs = up_current_regs();
+      restore_critical_section(tcb, this_cpu());
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c
index fea1620bd2..125431bbce 100644
--- a/arch/arm/src/armv6-m/arm_doirq.c
+++ b/arch/arm/src/armv6-m/arm_doirq.c
@@ -56,7 +56,13 @@ void exception_direct(void)
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb;
+
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
@@ -80,13 +86,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 #endif
 
       up_irq_save();
-      g_running_tasks[this_cpu()]->xcp.regs = regs;
     }
   else
     {
-      /* Dispatch irq */
-
-      tcb->xcp.regs = regs;
       irq_dispatch(irq, regs);
     }
 
@@ -100,7 +102,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   /* Update scheduler parameters */
 
-  nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+  nxsched_suspend_scheduler(*running_task);
   nxsched_resume_scheduler(tcb);
 
   /* Record the new "running" task when context switch occurred.
@@ -108,7 +110,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    * crashes.
    */
 
-  g_running_tasks[this_cpu()] = tcb;
+  *running_task = tcb;
   regs = tcb->xcp.regs;
 #endif
 
diff --git a/arch/arm/src/armv6-m/arm_svcall.c 
b/arch/arm/src/armv6-m/arm_svcall.c
index 90d07eae60..411138b3e1 100644
--- a/arch/arm/src/armv6-m/arm_svcall.c
+++ b/arch/arm/src/armv6-m/arm_svcall.c
@@ -119,6 +119,7 @@ int arm_svcall(int irq, void *context, void *arg)
 {
   struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
+  uint32_t *new_regs = regs;
   uint32_t cmd;
 
   cmd = regs[REG_R0];
@@ -167,6 +168,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
+          new_regs = (uint32_t *)regs[REG_R1];
           tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
@@ -191,8 +193,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_switch_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
+          new_regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -446,12 +447,12 @@ int arm_svcall(int irq, void *context, void *arg)
    * switch.
    */
 
-  if (regs != tcb->xcp.regs)
+  if (regs != new_regs)
     {
       restore_critical_section(tcb, this_cpu());
 
 #ifdef CONFIG_DEBUG_SYSCALL_INFO
-      regs = (uint32_t *)tcb->xcp.regs;
+      regs = new_regs;
 
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c 
b/arch/arm/src/armv7-a/arm_sigdeliver.c
index 98ac0e115b..1867aa8844 100644
--- a/arch/arm/src/armv7-a/arm_sigdeliver.c
+++ b/arch/arm/src/armv7-a/arm_sigdeliver.c
@@ -160,5 +160,7 @@ retry:
   leave_critical_section(regs[REG_CPSR]);
   rtcb->irqcount--;
 #endif
+
+  g_running_tasks[this_cpu()] = NULL;
   arm_fullcontextrestore(regs);
 }
diff --git a/arch/arm/src/armv7-a/arm_syscall.c 
b/arch/arm/src/armv7-a/arm_syscall.c
index 93167f2a39..dc420295ad 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -159,9 +159,9 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
   struct tcb_s *tcb = this_task();
   uint32_t cmd;
-  int cpu;
 #ifdef CONFIG_BUILD_KERNEL
   uint32_t cpsr;
 #endif
@@ -170,7 +170,10 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
-  tcb->xcp.regs = regs;
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
@@ -296,11 +299,6 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       case SYS_switch_context:
-        {
-          DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
-        }
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -566,7 +564,7 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (regs != tcb->xcp.regs)
+  if (*running_task != tcb)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -578,23 +576,20 @@ uint32_t *arm_syscall(uint32_t *regs)
       addrenv_switch(NULL);
 #endif
 
-      cpu = this_cpu();
-      tcb = current_task(cpu);
-
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      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.
        */
 
-      g_running_tasks[cpu] = tcb;
+      *running_task = tcb;
 
       /* Restore the cpu lock */
 
-      restore_critical_section(tcb, cpu);
+      restore_critical_section(tcb, this_cpu());
       regs = tcb->xcp.regs;
     }
 
diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c
index a14b24e6a4..d433f83d1c 100644
--- a/arch/arm/src/armv7-m/arm_doirq.c
+++ b/arch/arm/src/armv7-m/arm_doirq.c
@@ -56,7 +56,13 @@ void exception_direct(void)
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb;
+
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
@@ -80,13 +86,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 #endif
 
       up_irq_save();
-      g_running_tasks[this_cpu()]->xcp.regs = regs;
     }
   else
     {
-      /* Dispatch irq */
-
-      tcb->xcp.regs = regs;
       irq_dispatch(irq, regs);
     }
 
@@ -100,7 +102,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   /* Update scheduler parameters */
 
-  nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+  nxsched_suspend_scheduler(*running_task);
   nxsched_resume_scheduler(tcb);
 
   /* Record the new "running" task when context switch occurred.
@@ -108,7 +110,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    * crashes.
    */
 
-  g_running_tasks[this_cpu()] = tcb;
+  *running_task = tcb;
   regs = tcb->xcp.regs;
 #endif
 
diff --git a/arch/arm/src/armv7-m/arm_svcall.c 
b/arch/arm/src/armv7-m/arm_svcall.c
index 4d3e59bed5..da5122e8bb 100644
--- a/arch/arm/src/armv7-m/arm_svcall.c
+++ b/arch/arm/src/armv7-m/arm_svcall.c
@@ -127,6 +127,7 @@ int arm_svcall(int irq, void *context, void *arg)
 {
   struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
+  uint32_t *new_regs = regs;
   uint32_t cmd;
 
   cmd = regs[REG_R0];
@@ -176,6 +177,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
+          new_regs = (uint32_t *)regs[REG_R1];
           tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
@@ -200,8 +202,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_switch_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
+          new_regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -456,12 +457,12 @@ int arm_svcall(int irq, void *context, void *arg)
    * switch.
    */
 
-  if (regs != tcb->xcp.regs)
+  if (regs != new_regs)
     {
       restore_critical_section(tcb, this_cpu());
 
 #ifdef CONFIG_DEBUG_SYSCALL_INFO
-      regs = (uint32_t *)tcb->xcp.regs;
+      regs = new_regs;
 
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
diff --git a/arch/arm/src/armv7-r/arm_sigdeliver.c 
b/arch/arm/src/armv7-r/arm_sigdeliver.c
index 706f6ad555..5a63458b9b 100644
--- a/arch/arm/src/armv7-r/arm_sigdeliver.c
+++ b/arch/arm/src/armv7-r/arm_sigdeliver.c
@@ -157,5 +157,7 @@ retry:
   leave_critical_section(regs[REG_CPSR]);
   rtcb->irqcount--;
 #endif
+
+  g_running_tasks[this_cpu()] = NULL;
   arm_fullcontextrestore(regs);
 }
diff --git a/arch/arm/src/armv7-r/arm_syscall.c 
b/arch/arm/src/armv7-r/arm_syscall.c
index 12cc3d161f..b4f3a5047b 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -156,10 +156,9 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
-
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
-  int cpu;
 #ifdef CONFIG_BUILD_PROTECTED
   uint32_t cpsr;
 #endif
@@ -168,7 +167,10 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
-  tcb->xcp.regs = regs;
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
@@ -294,11 +296,6 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       case SYS_switch_context:
-        {
-          DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
-        }
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -564,24 +561,22 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (regs != tcb->xcp.regs)
+  if (*running_task != tcb)
     {
-      cpu = this_cpu();
-
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      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.
        */
 
-      g_running_tasks[cpu] = tcb;
+      *running_task = tcb;
 
       /* Restore the cpu lock */
 
-      restore_critical_section(tcb, cpu);
+      restore_critical_section(tcb, this_cpu());
       regs = tcb->xcp.regs;
     }
 
diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c
index 469251a09a..a1ca38afa4 100644
--- a/arch/arm/src/armv8-m/arm_doirq.c
+++ b/arch/arm/src/armv8-m/arm_doirq.c
@@ -67,7 +67,13 @@ void exception_direct(void)
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb;
+
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
@@ -91,13 +97,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 #endif
 
       up_irq_save();
-      g_running_tasks[this_cpu()]->xcp.regs = regs;
     }
   else
     {
-      /* Dispatch irq */
-
-      tcb->xcp.regs = regs;
       irq_dispatch(irq, regs);
     }
 
@@ -111,7 +113,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   /* Update scheduler parameters */
 
-  nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+  nxsched_suspend_scheduler(*running_task);
   nxsched_resume_scheduler(tcb);
 
   /* Record the new "running" task when context switch occurred.
@@ -119,7 +121,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    * crashes.
    */
 
-  g_running_tasks[this_cpu()] = tcb;
+  *running_task = tcb;
   regs = tcb->xcp.regs;
 #endif
 
diff --git a/arch/arm/src/armv8-m/arm_svcall.c 
b/arch/arm/src/armv8-m/arm_svcall.c
index 4c470957ec..fda01dd16f 100644
--- a/arch/arm/src/armv8-m/arm_svcall.c
+++ b/arch/arm/src/armv8-m/arm_svcall.c
@@ -127,6 +127,7 @@ int arm_svcall(int irq, void *context, void *arg)
 {
   struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
+  uint32_t *new_regs = regs;
   uint32_t cmd;
 
   cmd = regs[REG_R0];
@@ -176,6 +177,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
+          new_regs = (uint32_t *)regs[REG_R1];
           tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
@@ -200,8 +202,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_switch_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
+          new_regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -456,12 +457,12 @@ int arm_svcall(int irq, void *context, void *arg)
    * switch.
    */
 
-  if (regs != tcb->xcp.regs)
+  if (regs != new_regs)
     {
       restore_critical_section(tcb, this_cpu());
 
 #ifdef CONFIG_DEBUG_SYSCALL_INFO
-      regs = (uint32_t *)tcb->xcp.regs;
+      regs = new_regs;
 
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
diff --git a/arch/arm/src/armv8-r/arm_sigdeliver.c 
b/arch/arm/src/armv8-r/arm_sigdeliver.c
index a6837079a3..e4a8ad5935 100644
--- a/arch/arm/src/armv8-r/arm_sigdeliver.c
+++ b/arch/arm/src/armv8-r/arm_sigdeliver.c
@@ -155,5 +155,7 @@ retry:
   leave_critical_section(regs[REG_CPSR]);
   rtcb->irqcount--;
 #endif
+
+  g_running_tasks[this_cpu()] = NULL;
   arm_fullcontextrestore(regs);
 }
diff --git a/arch/arm/src/armv8-r/arm_syscall.c 
b/arch/arm/src/armv8-r/arm_syscall.c
index 0c796bf1b1..ab3f6cae88 100644
--- a/arch/arm/src/armv8-r/arm_syscall.c
+++ b/arch/arm/src/armv8-r/arm_syscall.c
@@ -156,9 +156,9 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
-  int cpu;
 #ifdef CONFIG_BUILD_PROTECTED
   uint32_t cpsr;
 #endif
@@ -167,7 +167,10 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
-  tcb->xcp.regs = regs;
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
 
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
@@ -293,11 +296,6 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       case SYS_switch_context:
-        {
-          DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
-          *(uint32_t **)regs[REG_R1] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
-        }
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -563,24 +561,22 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (regs != tcb->xcp.regs)
+  if (*running_task != tcb)
     {
-      cpu = this_cpu();
-
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      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.
        */
 
-      g_running_tasks[cpu] = tcb;
+      *running_task = tcb;
 
       /* Restore the cpu lock */
 
-      restore_critical_section(tcb, cpu);
+      restore_critical_section(tcb, this_cpu());
       regs = tcb->xcp.regs;
     }
 
diff --git a/arch/arm64/src/common/arm64_sigdeliver.c 
b/arch/arm64/src/common/arm64_sigdeliver.c
index 5ef6b592cd..3161f8859c 100644
--- a/arch/arm64/src/common/arm64_sigdeliver.c
+++ b/arch/arm64/src/common/arm64_sigdeliver.c
@@ -160,5 +160,7 @@ retry:
   leave_critical_section(flags);
   rtcb->irqcount--;
 #endif
+
+  g_running_tasks[this_cpu()] = NULL;
   arm64_fullcontextrestore(rtcb);
 }
diff --git a/arch/arm64/src/common/arm64_syscall.c 
b/arch/arm64/src/common/arm64_syscall.c
index 780286892f..f969c4eb5d 100644
--- a/arch/arm64/src/common/arm64_syscall.c
+++ b/arch/arm64/src/common/arm64_syscall.c
@@ -154,14 +154,19 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t 
parm1,
 
 uint64_t *arm64_syscall(uint64_t *regs)
 {
-  uint64_t            *ret_regs = regs;
-  uint64_t             cmd;
-  struct tcb_s        *tcb;
-  int cpu;
+  int cpu = this_cpu();
+  struct tcb_s **running_task = &g_running_tasks[cpu];
+  struct tcb_s *tcb = this_task();
+  uint64_t cmd;
 #ifdef CONFIG_BUILD_KERNEL
   uint64_t             spsr;
 #endif
 
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   /* Nested interrupts are not supported */
 
   DEBUGASSERT(regs);
@@ -186,17 +191,6 @@ uint64_t *arm64_syscall(uint64_t *regs)
        */
 
       case SYS_restore_context:
-        {
-          /* Replace 'regs' with the pointer to the register set in
-           * regs[REG_R1].  On return from the system call, that register
-           * set will determine the restored context.
-           */
-
-          tcb = (struct tcb_s *)regs[REG_X1];
-          ret_regs = tcb->xcp.regs;
-
-          DEBUGASSERT(ret_regs);
-        }
         break;
 
       /* x0 = SYS_switch_context:  This a switch context command:
@@ -216,15 +210,6 @@ uint64_t *arm64_syscall(uint64_t *regs)
        */
 
       case SYS_switch_context:
-        {
-          struct tcb_s *rtcb = (struct tcb_s *)regs[REG_X1];
-          tcb = (struct tcb_s *)regs[REG_X2];
-
-          DEBUGASSERT(regs[REG_X1] != 0 && regs[REG_X2] != 0);
-          rtcb->xcp.regs = regs;
-
-          ret_regs = tcb->xcp.regs;
-        }
         break;
 
 #ifdef CONFIG_BUILD_KERNEL
@@ -331,15 +316,13 @@ uint64_t *arm64_syscall(uint64_t *regs)
       default:
         {
           svcerr("ERROR: Bad SYS call: 0x%" PRIx64 "\n", cmd);
-          ret_regs = 0;
           return 0;
         }
         break;
     }
 
-  if ((uint64_t *)regs != ret_regs)
+  if (*running_task != tcb)
     {
-      cpu = this_cpu();
       tcb = current_task(cpu);
 
 #ifdef CONFIG_ARCH_ADDRENV
@@ -354,19 +337,19 @@ uint64_t *arm64_syscall(uint64_t *regs)
 
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      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.
        */
 
-      g_running_tasks[cpu] = tcb;
+      *running_task = tcb;
 
       /* Restore the cpu lock */
 
       restore_critical_section(tcb, cpu);
     }
 
-  return ret_regs;
+  return tcb->xcp.regs;
 }
diff --git a/arch/avr/src/avr/avr_doirq.c b/arch/avr/src/avr/avr_doirq.c
index c25e8b68d1..0bc80302c1 100644
--- a/arch/avr/src/avr/avr_doirq.c
+++ b/arch/avr/src/avr/avr_doirq.c
@@ -57,6 +57,13 @@
 
 uint8_t *avr_doirq(uint8_t irq, uint8_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      avr_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/avr/src/avr32/avr_doirq.c b/arch/avr/src/avr32/avr_doirq.c
index 37d05289df..3798248c62 100644
--- a/arch/avr/src/avr32/avr_doirq.c
+++ b/arch/avr/src/avr32/avr_doirq.c
@@ -58,6 +58,13 @@
 
 uint32_t *avr_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      avr_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/ceva/src/common/ceva_doirq.c 
b/arch/ceva/src/common/ceva_doirq.c
index c977dc138e..f513159616 100644
--- a/arch/ceva/src/common/ceva_doirq.c
+++ b/arch/ceva/src/common/ceva_doirq.c
@@ -59,6 +59,13 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
     }
   else
     {
+      struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+      if (*running_task != NULL)
+        {
+          (*running_task)->xcp.regs = regs;
+        }
+
       /* Current regs non-zero indicates that we are processing an interrupt;
        * current_regs is also used to manage interrupt level context
        * switches.
@@ -80,7 +87,7 @@ uint32_t *ceva_doirq(int irq, uint32_t *regs)
         {
           /* Update scheduler parameters */
 
-          nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+          nxsched_suspend_scheduler(*running_task);
           nxsched_resume_scheduler(this_task());
 
           /* Record the new "running" task when context switch occurred.
diff --git a/arch/ceva/src/common/ceva_exit.c b/arch/ceva/src/common/ceva_exit.c
index 08d60544c1..b096ff491f 100644
--- a/arch/ceva/src/common/ceva_exit.c
+++ b/arch/ceva/src/common/ceva_exit.c
@@ -78,6 +78,8 @@ void _exit(int status)
 
   sched_resume_scheduler(tcb);
 
+  g_running_tasks[this_cpu()] = tcb;
+
   /* Then switch contexts */
 
   ceva_fullcontextrestore(tcb->xcp.regs);
diff --git a/arch/hc/src/common/hc_doirq.c b/arch/hc/src/common/hc_doirq.c
index 838358ebd3..2142687a45 100644
--- a/arch/hc/src/common/hc_doirq.c
+++ b/arch/hc/src/common/hc_doirq.c
@@ -58,6 +58,13 @@
 
 uint8_t *hc_doirq(int irq, uint8_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      hc_copystate((*running_task)->xcp.regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/mips/src/mips32/mips_doirq.c 
b/arch/mips/src/mips32/mips_doirq.c
index 36c3151ccc..8a08dc8c0c 100644
--- a/arch/mips/src/mips32/mips_doirq.c
+++ b/arch/mips/src/mips32/mips_doirq.c
@@ -58,6 +58,13 @@
 
 uint32_t *mips_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      mips_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/mips/src/pic32mx/pic32mx_decodeirq.c 
b/arch/mips/src/pic32mx/pic32mx_decodeirq.c
index 49f0c8b00d..3b653f8ea8 100644
--- a/arch/mips/src/pic32mx/pic32mx_decodeirq.c
+++ b/arch/mips/src/pic32mx/pic32mx_decodeirq.c
@@ -70,12 +70,18 @@
 
 uint32_t *pic32mx_decodeirq(uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
 #ifdef CONFIG_PIC32MX_NESTED_INTERRUPTS
   uint32_t *savestate;
 #endif
   uint32_t regval;
   int irq;
 
+  if (*running_task != NULL)
+    {
+      mips_copystate((*running_task)->xcp.regs, regs);
+    }
+
   /* If the board supports LEDs, turn on an LED now to indicate that we are
    * processing an interrupt.
    */
diff --git a/arch/mips/src/pic32mx/pic32mx_exception.c 
b/arch/mips/src/pic32mx/pic32mx_exception.c
index 98f8c6dfbd..85f8bf8c95 100644
--- a/arch/mips/src/pic32mx/pic32mx_exception.c
+++ b/arch/mips/src/pic32mx/pic32mx_exception.c
@@ -53,11 +53,17 @@
 
 uint32_t *pic32mx_exception(uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
 #ifdef CONFIG_DEBUG_FEATURES
   uint32_t cause;
   uint32_t epc;
 #endif
 
+  if (*running_task != NULL)
+    {
+      mips_copystate((*running_task)->xcp.regs, regs);
+    }
+
   /* If the board supports LEDs, turn on an LED now to indicate that we are
    * processing an interrupt.
    */
diff --git a/arch/mips/src/pic32mz/pic32mz_decodeirq.c 
b/arch/mips/src/pic32mz/pic32mz_decodeirq.c
index d64ff57c21..4c742e2646 100644
--- a/arch/mips/src/pic32mz/pic32mz_decodeirq.c
+++ b/arch/mips/src/pic32mz/pic32mz_decodeirq.c
@@ -69,6 +69,13 @@
 
 uint32_t *pic32mz_decodeirq(uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      mips_copystate((*running_task)->xcp.regs, regs);
+    }
+
 #ifdef CONFIG_PIC32MZ_NESTED_INTERRUPTS
   uint32_t *savestate;
 #endif
diff --git a/arch/mips/src/pic32mz/pic32mz_exception.c 
b/arch/mips/src/pic32mz/pic32mz_exception.c
index 4cca474cdb..d16da4c1c3 100644
--- a/arch/mips/src/pic32mz/pic32mz_exception.c
+++ b/arch/mips/src/pic32mz/pic32mz_exception.c
@@ -52,11 +52,17 @@
 
 uint32_t *pic32mz_exception(uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
 #ifdef CONFIG_DEBUG_FEATURES
   uint32_t cause;
   uint32_t epc;
 #endif
 
+  if (*running_task != NULL)
+    {
+      mips_copystate((*running_task)->xcp.regs, regs);
+    }
+
   /* If the board supports LEDs, turn on an LED now to indicate that we are
    * processing an interrupt.
    */
diff --git a/arch/misoc/src/lm32/lm32_doirq.c b/arch/misoc/src/lm32/lm32_doirq.c
index 3472df00be..079429b4d8 100644
--- a/arch/misoc/src/lm32/lm32_doirq.c
+++ b/arch/misoc/src/lm32/lm32_doirq.c
@@ -45,6 +45,13 @@
 
 uint32_t *lm32_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      lm32_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 
   /* Current regs non-zero indicates that we are processing an interrupt;
diff --git a/arch/misoc/src/minerva/minerva_doirq.c 
b/arch/misoc/src/minerva/minerva_doirq.c
index 0a4cca5d7e..815e1c242c 100644
--- a/arch/misoc/src/minerva/minerva_doirq.c
+++ b/arch/misoc/src/minerva/minerva_doirq.c
@@ -45,6 +45,13 @@
 
 uint32_t *minerva_doirq(int irq, uint32_t * regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      minerva_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 
   /* Current regs non-zero indicates that we are processing an interrupt;
diff --git a/arch/or1k/src/common/or1k_doirq.c 
b/arch/or1k/src/common/or1k_doirq.c
index 42bb4f6a03..ecd6e33a43 100644
--- a/arch/or1k/src/common/or1k_doirq.c
+++ b/arch/or1k/src/common/or1k_doirq.c
@@ -41,6 +41,13 @@
 
 uint32_t *or1k_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      or1k_copyfullstate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/renesas/src/common/renesas_doirq.c 
b/arch/renesas/src/common/renesas_doirq.c
index 06af0e84c4..a6503087c4 100644
--- a/arch/renesas/src/common/renesas_doirq.c
+++ b/arch/renesas/src/common/renesas_doirq.c
@@ -58,6 +58,13 @@
 
 uint32_t *renesas_doirq(int irq, uint32_t * regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      renesas_copystate((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/risc-v/src/common/riscv_doirq.c 
b/arch/risc-v/src/common/riscv_doirq.c
index bbb1db9fb0..dd8e094cd9 100644
--- a/arch/risc-v/src/common/riscv_doirq.c
+++ b/arch/risc-v/src/common/riscv_doirq.c
@@ -99,7 +99,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
    * returning from the interrupt.
    */
 
-  if ((*running_task) != tcb)
+  if (*running_task != tcb)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -113,7 +113,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
 
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+      nxsched_suspend_scheduler(*running_task);
       nxsched_resume_scheduler(tcb);
 
       /* Record the new "running" task when context switch occurred.
diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c 
b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
index aa36a12c65..00fd5f54b2 100644
--- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
+++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
@@ -54,7 +54,7 @@ void *riscv_perform_syscall(uintreg_t *regs)
   riscv_swint(0, regs, NULL);
   tcb = this_task();
 
-  if ((*running_task) != tcb)
+  if (*running_task != tcb)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -67,7 +67,7 @@ void *riscv_perform_syscall(uintreg_t *regs)
 #endif
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+      nxsched_suspend_scheduler(*running_task);
       nxsched_resume_scheduler(tcb);
 
       /* Record the new "running" task.  g_running_tasks[] is only used by
diff --git a/arch/sim/src/sim/sim_doirq.c b/arch/sim/src/sim/sim_doirq.c
index 5adcf15cdf..5d75d76bf2 100644
--- a/arch/sim/src/sim/sim_doirq.c
+++ b/arch/sim/src/sim/sim_doirq.c
@@ -63,6 +63,13 @@ void *sim_doirq(int irq, void *context)
   sim_saveusercontext(regs, ret);
   if (ret == 0)
     {
+      struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+      if (*running_task != NULL)
+        {
+          sim_copyfullstate((*running_task)->xcp.regs, regs);
+        }
+
       up_set_current_regs(regs);
 
       /* Deliver the IRQ */
diff --git a/arch/sparc/src/sparc_v8/sparc_v8_doirq.c 
b/arch/sparc/src/sparc_v8/sparc_v8_doirq.c
index f596139c34..05e1ed7705 100644
--- a/arch/sparc/src/sparc_v8/sparc_v8_doirq.c
+++ b/arch/sparc/src/sparc_v8/sparc_v8_doirq.c
@@ -58,6 +58,13 @@
 
 uint32_t *sparc_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      trap_flush_task((*running_task)->xcp.regs, regs);
+    }
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
diff --git a/arch/tricore/src/common/tricore_doirq.c 
b/arch/tricore/src/common/tricore_doirq.c
index f3ed8151ea..975ad21fef 100644
--- a/arch/tricore/src/common/tricore_doirq.c
+++ b/arch/tricore/src/common/tricore_doirq.c
@@ -44,12 +44,19 @@
 
 IFX_INTERRUPT_INTERNAL(tricore_doirq, 0, 255)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
 #else
   Ifx_CPU_ICR icr;
   uintptr_t *regs;
 
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   icr.U = __mfcr(CPU_ICR);
   regs = (uintptr_t *)__mfcr(CPU_PCXI);
 
diff --git a/arch/x86/src/qemu/qemu_handlers.c 
b/arch/x86/src/qemu/qemu_handlers.c
index 091d75ff74..ab9093d996 100644
--- a/arch/x86/src/qemu/qemu_handlers.c
+++ b/arch/x86/src/qemu/qemu_handlers.c
@@ -76,6 +76,7 @@ static void idt_outb(uint8_t val, uint16_t addr)
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
 static uint32_t *common_handler(int irq, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
   board_autoled_on(LED_INIRQ);
 
   /* Current regs non-zero indicates that we are processing an interrupt;
@@ -87,6 +88,11 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
   DEBUGASSERT(up_current_regs() == NULL);
   up_set_current_regs(regs);
 
+  if (*running_task != NULL)
+    {
+      x86_savestate((*running_task)->xcp.regs);
+    }
+
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
@@ -118,7 +124,7 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
 
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
+      nxsched_suspend_scheduler(*running_task);
       nxsched_resume_scheduler(this_task());
 
       /* Record the new "running" task when context switch occurred.
@@ -126,7 +132,7 @@ static uint32_t *common_handler(int irq, uint32_t *regs)
        * crashes.
        */
 
-      g_running_tasks[this_cpu()] = this_task();
+      *running_task = this_task();
     }
 
   /* If a context switch occurred while processing the interrupt then
diff --git a/arch/x86_64/src/intel64/intel64_handlers.c 
b/arch/x86_64/src/intel64/intel64_handlers.c
index c17f8fc8c2..2d234b21bc 100644
--- a/arch/x86_64/src/intel64/intel64_handlers.c
+++ b/arch/x86_64/src/intel64/intel64_handlers.c
@@ -62,9 +62,15 @@
 #ifndef CONFIG_SUPPRESS_INTERRUPTS
 static uint64_t *common_handler(int irq, uint64_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
   struct tcb_s *tcb;
   int cpu;
 
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * g_current_regs is also used to manage interrupt level context switches.
    *
@@ -99,7 +105,7 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
       /* Update scheduler parameters */
 
       cpu = this_cpu();
-      nxsched_suspend_scheduler(g_running_tasks[cpu]);
+      nxsched_suspend_scheduler(*running_task);
       nxsched_resume_scheduler(this_task());
 
       /* Record the new "running" task when context switch occurred.
@@ -146,6 +152,13 @@ static uint64_t *common_handler(int irq, uint64_t *regs)
 
 uint64_t *isr_handler(uint64_t *regs, uint64_t irq)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   board_autoled_on(LED_INIRQ);
 
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
diff --git a/arch/xtensa/src/common/xtensa_assert.c 
b/arch/xtensa/src/common/xtensa_assert.c
index 0b51bd603a..e3a6abbff2 100644
--- a/arch/xtensa/src/common/xtensa_assert.c
+++ b/arch/xtensa/src/common/xtensa_assert.c
@@ -65,6 +65,13 @@
 
 void xtensa_panic(int xptcode, uint32_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      (*running_task)->xcp.regs = regs;
+    }
+
   up_set_current_regs(regs);
 
   /* We get here when a un-dispatch-able, irrecoverable exception occurs */
diff --git a/arch/xtensa/src/common/xtensa_irqdispatch.c 
b/arch/xtensa/src/common/xtensa_irqdispatch.c
index c3023994c8..46e848c777 100644
--- a/arch/xtensa/src/common/xtensa_irqdispatch.c
+++ b/arch/xtensa/src/common/xtensa_irqdispatch.c
@@ -44,7 +44,8 @@
 
 uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
 {
-  struct tcb_s *tcb = this_task();
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  struct tcb_s *tcb;
 
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   board_autoled_on(LED_INIRQ);
@@ -64,11 +65,9 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
 
   up_set_current_regs(regs);
 
-  if (irq != XTENSA_IRQ_SWINT)
+  if (*running_task != NULL)
     {
-      /* we are not trigger by syscall */
-
-      tcb->xcp.regs = regs;
+      (*running_task)->xcp.regs = regs;
     }
 
   /* Deliver the IRQ */
@@ -80,7 +79,7 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
    * current_regs will have a different value than it did on entry.
    */
 
-  if (regs != tcb->xcp.regs)
+  if (*running_task != tcb)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -94,16 +93,15 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
 
       /* Update scheduler parameters */
 
-      nxsched_suspend_scheduler(g_running_tasks[this_cpu()]);
-      nxsched_resume_scheduler(this_task());
+      nxsched_suspend_scheduler(*running_task);
+      nxsched_resume_scheduler(tcb);
 
       /* 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()] = tcb;
-      regs = tcb->xcp.regs;
+      *running_task = tcb;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
@@ -114,5 +112,5 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
 #endif
 
   board_autoled_off(LED_INIRQ);
-  return regs;
+  return tcb->xcp.regs;
 }
diff --git a/arch/xtensa/src/common/xtensa_swint.c 
b/arch/xtensa/src/common/xtensa_swint.c
index 943a772430..fc48a03f3e 100644
--- a/arch/xtensa/src/common/xtensa_swint.c
+++ b/arch/xtensa/src/common/xtensa_swint.c
@@ -59,12 +59,12 @@ int xtensa_swint(int irq, void *context, void *arg)
 {
   uint32_t *regs = (uint32_t *)context;
   struct tcb_s *tcb = this_task();
+  uintptr_t *new_regs = regs;
   uint32_t cmd;
 
   DEBUGASSERT(regs != NULL);
 
   cmd = regs[REG_A2];
-  tcb->xcp.regs = regs;
 
   /* The syscall software interrupt is called with A2 = system call command
    * and A3..A9 = variable number of arguments depending on the system call.
@@ -119,6 +119,7 @@ int xtensa_swint(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_A3] != 0);
+          new_regs = (uint32_t *)regs[REG_A3];
           tcb->xcp.regs = (uint32_t *)regs[REG_A3];
         }
         break;
@@ -142,9 +143,8 @@ int xtensa_swint(int irq, void *context, void *arg)
 
       case SYS_switch_context:
         {
-          DEBUGASSERT(regs[REG_A3] != 0 && regs[REG_A4] != 0);
-          *(uint32_t **)regs[REG_A3] = regs;
-          tcb->xcp.regs = (uint32_t *)regs[REG_A4];
+          DEBUGASSERT(regs[REG_A4] != 0);
+          new_regs = (uint32_t *)regs[REG_A4];
         }
         break;
 
@@ -432,10 +432,10 @@ int xtensa_swint(int irq, void *context, void *arg)
    */
 
 #ifdef CONFIG_DEBUG_SYSCALL_INFO
-  if (regs != tcb->xcp.regs)
+  if (regs != new_regs)
     {
       svcinfo("SYSCALL Return: Context switch!\n");
-      up_dump_register(tcb->xcp.regs);
+      up_dump_register(new_regs);
     }
   else
     {
@@ -443,7 +443,7 @@ int xtensa_swint(int irq, void *context, void *arg)
     }
 #endif
 
-  if (regs != tcb->xcp.regs)
+  if (regs != new_regs)
     {
       restore_critical_section(this_task(), this_cpu());
     }
diff --git a/arch/z16/src/common/z16_doirq.c b/arch/z16/src/common/z16_doirq.c
index 233f778858..a9ed9605e3 100644
--- a/arch/z16/src/common/z16_doirq.c
+++ b/arch/z16/src/common/z16_doirq.c
@@ -58,8 +58,14 @@ FAR chipreg_t *z16_doirq(int irq, FAR chipreg_t *regs)
 #else
   if ((unsigned)irq < NR_IRQS)
     {
+      struct tcb_s **running_task = &g_running_tasks[this_cpu()];
       FAR chipreg_t *savestate;
 
+      if (*running_task != NULL)
+        {
+          z16_copystate((*running_task)->xcp.regs, regs)
+        }
+
       /* Nested interrupts are not supported in this implementation.  If
        * you want to implement nested interrupts, you would have to (1)
        * change the way that g_current_regs is handled and (2) the design
diff --git a/arch/z16/src/z16f/z16f_sysexec.c b/arch/z16/src/z16f/z16f_sysexec.c
index 916aa679f6..5d38d2a410 100644
--- a/arch/z16/src/z16f/z16f_sysexec.c
+++ b/arch/z16/src/z16f/z16f_sysexec.c
@@ -47,8 +47,14 @@
 
 void z16f_sysexec(FAR chipreg_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
   uint16_t excp;
 
+  if (*running_task != NULL)
+    {
+      z16_copystate((*running_task)->xcp.regs, regs)
+    }
+
   /* Save that register reference so that it can be used for built-in
    * diagnostics.
    */
diff --git a/arch/z80/src/common/z80_doirq.c b/arch/z80/src/common/z80_doirq.c
index 81bbc2b51b..8429a41bfc 100644
--- a/arch/z80/src/common/z80_doirq.c
+++ b/arch/z80/src/common/z80_doirq.c
@@ -44,6 +44,13 @@
 
 FAR chipreg_t *z80_doirq(uint8_t irq, FAR chipreg_t *regs)
 {
+  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+
+  if (*running_task != NULL)
+    {
+      z80_copystate((*running_task)->xcp.regs, regs)
+    }
+
   board_autoled_on(LED_INIRQ);
 
   DECL_SAVESTATE();
diff --git a/fs/procfs/fs_procfstcbinfo.c b/fs/procfs/fs_procfstcbinfo.c
index 9aac5246d3..1a89af74db 100644
--- a/fs/procfs/fs_procfstcbinfo.c
+++ b/fs/procfs/fs_procfstcbinfo.c
@@ -181,17 +181,17 @@ static int tcbinfo_close(FAR struct file *filep)
 }
 
 /****************************************************************************
- * Name: tcbinfo_current_regs
+ * Name: tcbinfo_running_regs
  *
  * Description:
- *   A special version of up_current_regs() that is non-optimized.
+ *   A special version of running_regs() that is non-optimized.
  *
  ****************************************************************************/
 
 nooptimiziation_function
-FAR static void *tcbinfo_current_regs(void)
+FAR static void *tcbinfo_running_regs(void)
 {
-  return up_current_regs();
+  return running_regs();
 }
 
 /****************************************************************************
@@ -217,8 +217,8 @@ static ssize_t tcbinfo_read(FAR struct file *filep, FAR 
char *buffer,
     {
       linesize = procfs_snprintf(attr->line, TCBINFO_LINELEN,
                                  "pointer %p size %zu current regs %p\n",
-                                  &g_tcbinfo, sizeof(struct tcbinfo_s),
-                                  tcbinfo_current_regs());
+                                 &g_tcbinfo, sizeof(struct tcbinfo_s),
+                                 tcbinfo_running_regs());
 
       /* Save the linesize in case we are re-entered with f_pos > 0 */
 
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 960847b5b4..21cd765819 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -244,6 +244,8 @@
 #  define this_cpu()                 (0)
 #endif
 
+#define running_regs()               ((void 
*)(g_running_tasks[this_cpu()]->xcp.regs))
+
 /****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
@@ -872,6 +874,12 @@ EXTERN clock_t g_premp_max[CONFIG_SMP_NCPUS];
 EXTERN clock_t g_crit_max[CONFIG_SMP_NCPUS];
 #endif /* CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 */
 
+/* g_running_tasks[] holds a references to the running task for each CPU.
+ * It is valid only when up_interrupt_context() returns true.
+ */
+
+EXTERN FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS];
+
 EXTERN const struct tcbinfo_s g_tcbinfo;
 
 /****************************************************************************
diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c
index cb9a048487..ace1307938 100644
--- a/libs/libc/gdbstub/lib_gdbstub.c
+++ b/libs/libc/gdbstub/lib_gdbstub.c
@@ -1039,7 +1039,7 @@ static void gdb_get_registers(FAR struct gdb_state_s 
*state)
     {
       if (up_interrupt_context())
         {
-          reg = (FAR uint8_t *)up_current_regs();
+          reg = (FAR uint8_t *)running_regs();
         }
       else
         {
diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c
index d45f68bbf1..01ba4df823 100644
--- a/sched/init/nx_start.c
+++ b/sched/init/nx_start.c
@@ -129,7 +129,7 @@ dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
 FAR struct tcb_s *g_delivertasks[CONFIG_SMP_NCPUS];
 #endif
 
-/* g_running_tasks[] holds a references to the running task for each cpu.
+/* g_running_tasks[] holds a references to the running task for each CPU.
  * It is valid only when up_interrupt_context() returns true.
  */
 
diff --git a/sched/misc/assert.c b/sched/misc/assert.c
index 0864e60205..c04f452d07 100644
--- a/sched/misc/assert.c
+++ b/sched/misc/assert.c
@@ -304,7 +304,7 @@ static void dump_stacks(FAR struct tcb_s *rtcb, uintptr_t 
sp)
       /* Try to restore SP from current_regs if assert from interrupt. */
 
       tcbstack_sp = up_interrupt_context() ?
-                    up_getusrsp((FAR void *)up_current_regs()) : 0;
+                    up_getusrsp((FAR void *)running_regs()) : 0;
       if (tcbstack_sp < tcbstack_base || tcbstack_sp >= tcbstack_top)
         {
           tcbstack_sp = 0;
@@ -607,7 +607,7 @@ static void dump_deadlock(void)
 
 static noreturn_function int pause_cpu_handler(FAR void *arg)
 {
-  memcpy(g_last_regs[this_cpu()], up_current_regs(), sizeof(g_last_regs[0]));
+  memcpy(g_last_regs[this_cpu()], running_regs(), sizeof(g_last_regs[0]));
   g_cpu_paused[this_cpu()] = true;
   up_flush_dcache_all();
   while (1);
diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c
index 4f39b51fa4..1de2fb5f2b 100644
--- a/sched/misc/coredump.c
+++ b/sched/misc/coredump.c
@@ -309,7 +309,7 @@ static void elf_emit_tcb_note(FAR struct elf_dumpinfo_s 
*cinfo,
     {
       if (up_interrupt_context())
         {
-          regs = (FAR uintptr_t *)up_current_regs();
+          regs = (FAR uintptr_t *)running_regs();
         }
       else
         {
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index d8ffdf2acc..a978493061 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -197,12 +197,6 @@ extern dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
 
 extern FAR struct tcb_s *g_delivertasks[CONFIG_SMP_NCPUS];
 
-/* g_running_tasks[] holds a references to the running task for each cpu.
- * It is valid only when up_interrupt_context() returns true.
- */
-
-extern FAR struct tcb_s *g_running_tasks[CONFIG_SMP_NCPUS];
-
 /* This is the list of all tasks that are ready-to-run, but cannot be placed
  * in the g_readytorun list because:  (1) They are higher priority than the
  * currently active task at the head of the g_readytorun list, and (2) the
diff --git a/tools/gdb/thread.py b/tools/gdb/thread.py
index b822e3443a..93537ca567 100644
--- a/tools/gdb/thread.py
+++ b/tools/gdb/thread.py
@@ -82,7 +82,7 @@ class Nxsetregs(gdb.Command):
         super(Nxsetregs, self).__init__("nxsetregs", gdb.COMMAND_USER)
 
     def invoke(self, args, from_tty):
-        gdb.execute("set $_current_regs=tcbinfo_current_regs()")
+        gdb.execute("set $_current_regs=tcbinfo_running_regs()")
         current_regs = gdb.parse_and_eval("$_current_regs")
         tcbinfo = gdb.parse_and_eval("g_tcbinfo")
         arg = args.split(" ")

Reply via email to