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 2b22ee03d6a44f82c94a557e5c0c41932718c5d1
Author: hujun5 <[email protected]>
AuthorDate: Thu Nov 21 16:48:42 2024 +0800

    arm: remove g_running_tasks[this_cpu()] = NULL
    
    reason:
    We hope to keep g_running_tasks valid forever.
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm/include/tlsr82/irq.h         |  2 --
 arch/arm/src/arm/arm_sigdeliver.c     |  1 -
 arch/arm/src/arm/arm_syscall.c        | 60 +++++++++++++++----------------
 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    | 68 ++++++++++++++++-------------------
 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    | 57 +++++++++++++++--------------
 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    | 57 +++++++++++++++--------------
 arch/arm/src/common/arm_exit.c        |  2 +-
 arch/arm/src/common/arm_internal.h    |  2 ++
 arch/arm/src/tlsr82/chip.h            |  2 ++
 18 files changed, 142 insertions(+), 135 deletions(-)

diff --git a/arch/arm/include/tlsr82/irq.h b/arch/arm/include/tlsr82/irq.h
index 529c5692aa..115f9f14b6 100644
--- a/arch/arm/include/tlsr82/irq.h
+++ b/arch/arm/include/tlsr82/irq.h
@@ -283,8 +283,6 @@ static inline_function void up_set_interrupt_context(bool 
flag)
 #endif
 }
 
-#define arm_fullcontextrestore() tc32_fullcontextrestore(this_task()->xcp.regs)
-
 #define up_switch_context(tcb, rtcb)                        \
   do {                                                      \
     if (!up_interrupt_context())                            \
diff --git a/arch/arm/src/arm/arm_sigdeliver.c 
b/arch/arm/src/arm/arm_sigdeliver.c
index a76152b535..a0ab5f36fb 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 7443e27c1d..3903159bfd 100644
--- a/arch/arm/src/arm/arm_syscall.c
+++ b/arch/arm/src/arm/arm_syscall.c
@@ -54,7 +54,8 @@
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  int cpu = this_cpu();
+  struct tcb_s **running_task = &g_running_tasks[cpu];
   FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
 
@@ -62,12 +63,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);
 
@@ -75,12 +73,35 @@ 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:
       case SYS_switch_context:
+
+        /* Update scheduler parameters */
+
+        nxsched_resume_scheduler(tcb);
+
+      case SYS_restore_context:
+        nxsched_suspend_scheduler(*running_task);
+        *running_task = tcb;
+
+        /* Restore the cpu lock */
+
+        restore_critical_section(tcb, cpu);
+#ifdef CONFIG_ARCH_ADDRENV
+        addrenv_switch(tcb);
+#endif
         break;
 
       default:
@@ -92,29 +113,6 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (*running_task != tcb)
-    {
-#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 the ready-to-run list.
-       */
-
-      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());
-    }
-
   /* Set irq flag */
 
   up_set_interrupt_context(false);
diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c
index 9c9e78d3cf..e3e6383e48 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 5fd3f44463..73ad65e14a 100644
--- a/arch/arm/src/armv6-m/arm_sigdeliver.c
+++ b/arch/arm/src/armv6-m/arm_sigdeliver.c
@@ -162,7 +162,7 @@ retry:
   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 5c0e058a4e..5de0caa880 100644
--- a/arch/arm/src/armv7-a/arm_sigdeliver.c
+++ b/arch/arm/src/armv7-a/arm_sigdeliver.c
@@ -161,7 +161,6 @@ retry:
   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 f31e403155..df7f68d1ff 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -159,7 +159,8 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  int cpu = this_cpu();
+  struct tcb_s **running_task = &g_running_tasks[cpu];
   struct tcb_s *tcb = this_task();
   uint32_t cmd;
 #ifdef CONFIG_BUILD_KERNEL
@@ -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,24 @@ uint32_t *arm_syscall(uint32_t *regs)
         }
         break;
 #endif
-      case SYS_restore_context:
+
       case SYS_switch_context:
+
+        /* Update scheduler parameters */
+
+        nxsched_resume_scheduler(tcb);
+
+      case SYS_restore_context:
+        nxsched_suspend_scheduler(*running_task);
+        *running_task = tcb;
+
+        /* Restore the cpu lock */
+
+        restore_critical_section(tcb, cpu);
+        regs = tcb->xcp.regs;
+#ifdef CONFIG_ARCH_ADDRENV
+        addrenv_switch(tcb);
+#endif
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -522,35 +545,6 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (*running_task != tcb)
-    {
-#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 the ready-to-run list.
-       */
-
-      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());
-      regs = tcb->xcp.regs;
-    }
-
   /* Report what happened */
 
   dump_syscall("Exit", cmd, regs);
diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c
index 9989437e47..dcbdd9dc12 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 5642e82623..3d617ea46a 100644
--- a/arch/arm/src/armv7-m/arm_sigdeliver.c
+++ b/arch/arm/src/armv7-m/arm_sigdeliver.c
@@ -175,7 +175,6 @@ retry:
   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 009ad90657..bd715470cd 100644
--- a/arch/arm/src/armv7-r/arm_sigdeliver.c
+++ b/arch/arm/src/armv7-r/arm_sigdeliver.c
@@ -158,7 +158,6 @@ retry:
   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 315a6f42d4..179b27baae 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -156,7 +156,8 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  int cpu = this_cpu();
+  struct tcb_s **running_task = &g_running_tasks[cpu];
   FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
 #ifdef CONFIG_BUILD_PROTECTED
@@ -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.
    */
@@ -253,8 +260,23 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
 #endif
 
-      case SYS_restore_context:
       case SYS_switch_context:
+
+        /* Update scheduler parameters */
+
+        nxsched_resume_scheduler(tcb);
+
+      case SYS_restore_context:
+        nxsched_suspend_scheduler(*running_task);
+        *running_task = tcb;
+
+        /* Restore the cpu lock */
+
+        restore_critical_section(tcb, cpu);
+        regs = tcb->xcp.regs;
+#ifdef CONFIG_ARCH_ADDRENV
+        addrenv_switch(tcb);
+#endif
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -520,25 +542,6 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (*running_task != tcb)
-    {
-      /* 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());
-      regs = tcb->xcp.regs;
-    }
-
   /* Report what happened */
 
   dump_syscall("Exit", cmd, regs);
diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c
index 3cd28ae298..55183573a5 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 aff8738235..43d72e35a8 100644
--- a/arch/arm/src/armv8-m/arm_sigdeliver.c
+++ b/arch/arm/src/armv8-m/arm_sigdeliver.c
@@ -174,7 +174,7 @@ retry:
 #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 5e4015e986..17fbc7b198 100644
--- a/arch/arm/src/armv8-r/arm_sigdeliver.c
+++ b/arch/arm/src/armv8-r/arm_sigdeliver.c
@@ -156,7 +156,6 @@ retry:
   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 e478aafecf..d003166840 100644
--- a/arch/arm/src/armv8-r/arm_syscall.c
+++ b/arch/arm/src/armv8-r/arm_syscall.c
@@ -156,7 +156,8 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s **running_task = &g_running_tasks[this_cpu()];
+  int cpu = this_cpu();
+  struct tcb_s **running_task = &g_running_tasks[cpu];
   FAR struct tcb_s *tcb = this_task();
   uint32_t cmd;
 #ifdef CONFIG_BUILD_PROTECTED
@@ -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.
    */
@@ -253,8 +260,23 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
 #endif
 
-      case SYS_restore_context:
       case SYS_switch_context:
+
+        /* Update scheduler parameters */
+
+        nxsched_resume_scheduler(tcb);
+
+      case SYS_restore_context:
+        nxsched_suspend_scheduler(*running_task);
+        *running_task = tcb;
+
+        /* Restore the cpu lock */
+
+        restore_critical_section(tcb, cpu);
+        regs = tcb->xcp.regs;
+#ifdef CONFIG_ARCH_ADDRENV
+        addrenv_switch(tcb);
+#endif
         break;
 
       /* R0=SYS_task_start:  This a user task start
@@ -520,25 +542,6 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  if (*running_task != tcb)
-    {
-      /* 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());
-      regs = tcb->xcp.regs;
-    }
-
   /* Report what happened */
 
   dump_syscall("Exit", cmd, regs);
diff --git a/arch/arm/src/common/arm_exit.c b/arch/arm/src/common/arm_exit.c
index fa49dc5fed..1b6cafbf80 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 */
 
diff --git a/arch/arm/src/common/arm_internal.h 
b/arch/arm/src/common/arm_internal.h
index b72c256a83..c7e4243cae 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -33,6 +33,8 @@
 #  include <sys/types.h>
 #  include <stdint.h>
 #  include <syscall.h>
+
+#  include "chip.h"
 #endif
 
 /****************************************************************************
diff --git a/arch/arm/src/tlsr82/chip.h b/arch/arm/src/tlsr82/chip.h
index dfc81861bd..18be19cf38 100644
--- a/arch/arm/src/tlsr82/chip.h
+++ b/arch/arm/src/tlsr82/chip.h
@@ -33,6 +33,8 @@
 
 #define ARMV6M_PERIPHERAL_INTERRUPTS NR_IRQS
 
+#define arm_fullcontextrestore() tc32_fullcontextrestore(this_task()->xcp.regs)
+
 /* Include the memory map file.
  * Other chip hardware files should then include this file for the proper
  * setup.

Reply via email to