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


The following commit(s) were added to refs/heads/master by this push:
     new c5ecc49c10 riscv: g_current_regs is only used to determine if we are 
in irq,        with other functionalities removed.
c5ecc49c10 is described below

commit c5ecc49c10586125fa97148ee8aac555dc0a5009
Author: hujun5 <[email protected]>
AuthorDate: Fri Sep 20 20:50:51 2024 +0800

    riscv: g_current_regs is only used to determine if we are in irq,
           with other functionalities removed.
    
    reason:
      by doing this we can reduce context switch time,
      When we exit from an interrupt handler, we directly use tcb->xcp.regs
    
    before
       text    data     bss     dec     hex filename
     138805     337   24256  163398   27e46 nuttx
    
    after
       text    data     bss     dec     hex filename
     138499     337   24240  163076   27d04 nuttx
    
     szie change -322
    Signed-off-by: hujun5 <[email protected]>
---
 arch/risc-v/src/common/riscv_doirq.c               |  13 +-
 arch/risc-v/src/common/riscv_internal.h            |  11 -
 arch/risc-v/src/common/riscv_schedulesigaction.c   | 293 ++-------------------
 arch/risc-v/src/common/riscv_swint.c               |  22 +-
 .../src/common/supervisor/riscv_perform_syscall.c  |  10 +-
 5 files changed, 45 insertions(+), 304 deletions(-)

diff --git a/arch/risc-v/src/common/riscv_doirq.c 
b/arch/risc-v/src/common/riscv_doirq.c
index 44da81d418..895bd910de 100644
--- a/arch/risc-v/src/common/riscv_doirq.c
+++ b/arch/risc-v/src/common/riscv_doirq.c
@@ -58,6 +58,8 @@
 
 uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -69,6 +71,10 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
     {
       regs[REG_EPC] += 4;
     }
+  else
+    {
+      tcb->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.
@@ -82,6 +88,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
+  tcb = this_task();
 
   /* 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
@@ -90,7 +97,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
    * returning from the interrupt.
    */
 
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -107,7 +114,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
        * crashes.
        */
 
-      g_running_tasks[this_cpu()] = this_task();
+      g_running_tasks[this_cpu()] = tcb;
 
       /* If a context switch occurred while processing the interrupt then
        * current_regs may have change value.  If we return any value
@@ -115,7 +122,7 @@ uintreg_t *riscv_doirq(int irq, uintreg_t *regs)
        * that a context switch occurred during interrupt processing.
        */
 
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/risc-v/src/common/riscv_internal.h 
b/arch/risc-v/src/common/riscv_internal.h
index 13a887615a..d9165356a9 100644
--- a/arch/risc-v/src/common/riscv_internal.h
+++ b/arch/risc-v/src/common/riscv_internal.h
@@ -85,13 +85,6 @@
 /* Interrupt Stack macros */
 #define INT_STACK_SIZE  (STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK))
 
-/* In the RISC-V model, the state is saved in stack,
- * only a reference stored in TCB.
- */
-
-#define riscv_savestate(regs) (regs = up_current_regs())
-#define riscv_restorestate(regs) up_set_current_regs(regs)
-
 /* Determine which (if any) console driver to use.  If a console is enabled
  * and no other console device is specified, then a serial console is
  * assumed.
@@ -322,8 +315,6 @@ static inline uintptr_t *riscv_vpuregs(struct tcb_s *tcb)
 
 static inline void riscv_savecontext(struct tcb_s *tcb)
 {
-  tcb->xcp.regs = (uintreg_t *)up_current_regs();
-
 #ifdef CONFIG_ARCH_FPU
   /* Save current process FPU state to TCB */
 
@@ -339,8 +330,6 @@ static inline void riscv_savecontext(struct tcb_s *tcb)
 
 static inline void riscv_restorecontext(struct tcb_s *tcb)
 {
-  up_set_current_regs(tcb->xcp.regs);
-
 #ifdef CONFIG_ARCH_FPU
   /* Restore FPU state for next process */
 
diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c 
b/arch/risc-v/src/common/riscv_schedulesigaction.c
index ecc5260cde..d886443d9e 100644
--- a/arch/risc-v/src/common/riscv_schedulesigaction.c
+++ b/arch/risc-v/src/common/riscv_schedulesigaction.c
@@ -76,7 +76,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   uintptr_t int_ctx;
@@ -89,289 +88,33 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
     {
       tcb->xcp.sigdeliver = sigdeliver;
 
-      /* First, handle some special cases when the signal is
-       * being delivered to the currently executing task.
+      /* First, handle some special cases when the signal is being delivered
+       * to task that is currently executing on any CPU.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and
-           * a task is signalling itself for some reason.
-           */
-
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now. */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the
-           * interrupted task is the same as the one that
-           * must receive the signal, then we will have to modify
-           * the return state as well as the state in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following
-           * logic would fail in the strange case where we are in an
-           * interrupt handler, the thread is signalling itself, but
-           * a context switch to another task has occurred so that
-           * current_regs does not refer to the thread of this_task()!
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handler will run in a critical section!
            */
 
-          else
-            {
-              /* Save the context registers.  These will be
-               * restored by the signal trampoline after the signals have
-               * been delivered.
-               */
-
-              riscv_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has
-               * been delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled.  The kernel-space trampoline must run in
-               * privileged thread mode.
-               */
-
-              up_current_regs()[REG_EPC] = (uintptr_t)riscv_sigdeliver;
-
-              int_ctx  = up_current_regs()[REG_INT_CTX];
-              int_ctx &= ~STATUS_PIE;
-#ifndef CONFIG_BUILD_FLAT
-              int_ctx |= STATUS_PPP;
-#endif
-              up_current_regs()[REG_INT_CTX] = int_ctx;
-
-              up_current_regs()[REG_SP] = (uintptr_t)(up_current_regs() +
-                                                       XCPTCONTEXT_REGS);
-
-              sinfo("PC/STATUS Saved: %" PRIxREG "/%" PRIxREG
-                    " New: %" PRIxREG "/%" PRIxREG "\n",
-                    tcb->xcp.saved_regs[REG_EPC],
-                    tcb->xcp.saved_regs[REG_INT_CTX],
-                    up_current_regs()[REG_EPC],
-                    up_current_regs()[REG_INT_CTX]);
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running
-       * from an interrupt handler or (2) we are not in an
-       * interrupt handler and the running task is signalling
-       * some non-running task.
-       */
-
       else
         {
-          /* Save the return EPC and STATUS registers.  These will be
-           * restored by the signal trampoline after the signals have
-           * been delivered.
-           */
-
-          /* Save the current register context location */
-
-          tcb->xcp.saved_regs = tcb->xcp.regs;
-
-          /* Duplicate the register context.  These will be
-           * restored by the signal trampoline after the signal has been
-           * delivered.
-           */
-
-          tcb->xcp.regs = (uintreg_t *)((uintptr_t)tcb->xcp.regs -
-                                                   XCPTCONTEXT_SIZE);
-
-          memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
-
-          tcb->xcp.regs[REG_SP]       = (uintptr_t)tcb->xcp.regs +
-                                                   XCPTCONTEXT_SIZE;
-
-          tcb->xcp.regs[REG_EPC]      = (uintptr_t)riscv_sigdeliver;
-          int_ctx                     = tcb->xcp.regs[REG_INT_CTX];
-          int_ctx                    &= ~STATUS_PIE;
-
-          tcb->xcp.regs[REG_INT_CTX]  = int_ctx;
-
-          sinfo("PC/STATUS Saved: %" PRIxREG "/%" PRIxREG
-                " New: %" PRIxREG "/%" PRIxREG "\n",
-                tcb->xcp.saved_regs[REG_EPC],
-                tcb->xcp.saved_regs[REG_INT_CTX],
-                tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_INT_CTX]);
-        }
-    }
-}
-#endif /* !CONFIG_SMP */
-
 #ifdef CONFIG_SMP
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  uintptr_t int_ctx;
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
+          if (cpu != me)
             {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
+              /* Pause the CPU */
 
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
+              up_cpu_pause(cpu);
             }
-
-          /* CASE 2:  The task that needs to receive the signal is running.
-           * This could happen if the task is running on another CPU OR if
-           * we are in an interrupt handler and the task is running on this
-           * CPU.  In the former case, we will have to PAUSE the other CPU
-           * first.  But in either case, we will have to modify the return
-           * state as well as the state in the TCB.
-           */
-
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  We must already be in privileged thread mode
-                   * to be here.
-                   */
-
-                  /* Save the current register context location */
-
-                  tcb->xcp.saved_regs = tcb->xcp.regs;
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  tcb->xcp.regs = (uintreg_t *)((uintptr_t)tcb->xcp.regs -
-                                                           XCPTCONTEXT_SIZE);
-
-                  memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  tcb->xcp.regs[REG_SP]      = (uintptr_t)tcb->xcp.regs +
-                                                          XCPTCONTEXT_SIZE;
-
-                  tcb->xcp.regs[REG_EPC]     = (uintptr_t)riscv_sigdeliver;
-                  int_ctx                    = tcb->xcp.regs[REG_INT_CTX];
-                  int_ctx                   &= ~STATUS_PIE;
-#ifndef CONFIG_BUILD_FLAT
-                  int_ctx                   |= STATUS_PPP;
 #endif
-                  tcb->xcp.regs[REG_INT_CTX] = int_ctx;
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
 
-                  /* Save the context registers.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  tcb->xcp.saved_regs = up_current_regs();
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uintptr_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_EPC] = (uintptr_t)riscv_sigdeliver;
-
-                  int_ctx  = up_current_regs()[REG_INT_CTX];
-                  int_ctx &= ~STATUS_PIE;
-#ifndef CONFIG_BUILD_FLAT
-                  int_ctx |= STATUS_PPP;
-#endif
-                  up_current_regs()[REG_INT_CTX] = int_ctx;
-                }
-
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
-
-              /* RESUME the other CPU if it was PAUSED */
-
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
-            }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
-
-      else
-        {
           /* Save the return EPC and STATUS registers.  These will be
            * by the signal trampoline after the signal has been delivered.
            */
@@ -403,9 +146,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 
           int_ctx                    = tcb->xcp.regs[REG_INT_CTX];
           int_ctx                   &= ~STATUS_PIE;
+#ifndef CONFIG_BUILD_FLAT
+          int_ctx                   |= STATUS_PPP;
+#endif
 
           tcb->xcp.regs[REG_INT_CTX] = int_ctx;
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
+#endif
         }
     }
 }
-#endif /* CONFIG_SMP */
diff --git a/arch/risc-v/src/common/riscv_swint.c 
b/arch/risc-v/src/common/riscv_swint.c
index f0ed4825d8..510161db6f 100644
--- a/arch/risc-v/src/common/riscv_swint.c
+++ b/arch/risc-v/src/common/riscv_swint.c
@@ -199,8 +199,7 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t 
parm1,
 int riscv_swint(int irq, void *context, void *arg)
 {
   uintreg_t *regs = (uintreg_t *)context;
-
-  DEBUGASSERT(regs && regs == up_current_regs());
+  uintreg_t *new_regs = regs;
 
   /* Software interrupt 0 is invoked with REG_A0 (REG_X10) = system call
    * command and REG_A1-6 = variable number of
@@ -225,11 +224,6 @@ int riscv_swint(int irq, void *context, void *arg)
        *
        *   A0 = SYS_restore_context
        *   A1 = next
-       *
-       * In this case, we simply need to set current_regs to restore register
-       * area referenced in the saved A1. context == current_regs is the
-       * normal exception return.  By setting current_regs = context[A1], we
-       * force the return to the saved context referenced in $a1.
        */
 
       case SYS_restore_context:
@@ -237,6 +231,7 @@ int riscv_swint(int irq, void *context, void *arg)
           struct tcb_s *next = (struct tcb_s *)(uintptr_t)regs[REG_A1];
 
           DEBUGASSERT(regs[REG_A1] != 0);
+          new_regs = next->xcp.regs;
           riscv_restorecontext(next);
         }
         break;
@@ -253,9 +248,7 @@ int riscv_swint(int irq, void *context, void *arg)
        *   A2 = next
        *
        * In this case, we save the context registers to the save register
-       * area referenced by the saved contents of R5 and then set
-       * current_regs to the save register area referenced by the saved
-       * contents of R6.
+       * area referenced by the saved contents of R5.
        */
 
       case SYS_switch_context:
@@ -264,7 +257,9 @@ int riscv_swint(int irq, void *context, void *arg)
           struct tcb_s *next = (struct tcb_s *)(uintptr_t)regs[REG_A2];
 
           DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
+          prev->xcp.regs = regs;
           riscv_savecontext(prev);
+          new_regs = next->xcp.regs;
           riscv_restorecontext(next);
         }
         break;
@@ -478,7 +473,6 @@ int riscv_swint(int irq, void *context, void *arg)
 #endif
 
       default:
-
         DEBUGPANIC();
         break;
     }
@@ -488,10 +482,10 @@ int riscv_swint(int irq, void *context, void *arg)
    */
 
 #ifdef CONFIG_DEBUG_SYSCALL_INFO
-  if (regs != up_current_regs())
+  if (regs != new_regs)
     {
       svcinfo("SWInt Return: Context switch!\n");
-      up_dump_register(up_current_regs());
+      up_dump_register(new_regs);
     }
   else
     {
@@ -499,7 +493,7 @@ int riscv_swint(int irq, void *context, void *arg)
     }
 #endif
 
-  if (regs != up_current_regs())
+  if (regs != new_regs)
     {
       restore_critical_section(this_task(), this_cpu());
     }
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 8b9d287c8d..8e26221e40 100644
--- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
+++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c
@@ -47,10 +47,11 @@ void *riscv_perform_syscall(uintreg_t *regs)
   /* Run the system call handler (swint) */
 
   riscv_swint(0, regs, NULL);
+  tcb = this_task();
 
-#ifdef CONFIG_ARCH_ADDRENV
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.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
@@ -58,11 +59,8 @@ void *riscv_perform_syscall(uintreg_t *regs)
        */
 
       addrenv_switch(NULL);
-    }
 #endif
 
-  if (regs != up_current_regs())
-    {
       /* Record the new "running" task.  g_running_tasks[] is only used by
        * assertion logic for reporting crashes.
        */
@@ -81,7 +79,7 @@ void *riscv_perform_syscall(uintreg_t *regs)
        * that a context switch occurred during interrupt processing.
        */
 
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   up_set_current_regs(NULL);

Reply via email to