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

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

commit 4fd92edee7ff36b50af7a8e4c6669ea0e882cf3f
Author: hujun5 <[email protected]>
AuthorDate: Mon Sep 9 21:15:00 2024 +0800

    sched: replace sync pause with async pause for nxsig_process
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm/src/armv6-m/arm_schedulesigaction.c       | 33 --------
 arch/arm/src/armv7-a/arm_schedulesigaction.c       | 33 --------
 arch/arm/src/armv7-m/arm_schedulesigaction.c       | 33 --------
 arch/arm/src/armv7-r/arm_schedulesigaction.c       | 25 ------
 arch/arm/src/armv8-m/arm_schedulesigaction.c       | 33 --------
 arch/arm/src/armv8-r/arm_schedulesigaction.c       | 25 ------
 arch/arm64/src/common/arm64_schedulesigaction.c    | 21 -----
 arch/ceva/src/common/ceva_schedulesigaction.c      | 24 ------
 arch/risc-v/src/common/riscv_schedulesigaction.c   | 20 -----
 .../src/sparc_v8/sparc_v8_schedulesigaction.c      | 89 +++++-----------------
 .../x86_64/src/intel64/intel64_schedulesigaction.c | 81 +++++---------------
 arch/xtensa/src/common/xtensa_schedsigaction.c     | 21 -----
 sched/signal/sig_dispatch.c                        | 80 ++++++++++++++++++-
 13 files changed, 118 insertions(+), 400 deletions(-)

diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c 
b/arch/arm/src/armv6-m/arm_schedulesigaction.c
index 1bc4929820..9eeda2acb3 100644
--- a/arch/arm/src/armv6-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c
@@ -98,30 +98,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* 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.
-       */
-
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
        * registers (and perhaps also the LR).  These will be restored
        * by the signal trampoline after the signal has been delivered.
@@ -157,14 +133,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
       tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
       tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c 
b/arch/arm/src/armv7-a/arm_schedulesigaction.c
index 75b0bb5598..9ac4edec49 100644
--- a/arch/arm/src/armv7-a/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c
@@ -97,30 +97,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* 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.
-       */
-
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return lr and cpsr and one scratch register.  These
        * will be restored by the signal trampoline after the signals
        * have been delivered.
@@ -152,14 +128,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 #ifdef CONFIG_ARM_THUMB
       tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c 
b/arch/arm/src/armv7-m/arm_schedulesigaction.c
index 8786085526..8d4749ca2a 100644
--- a/arch/arm/src/armv7-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c
@@ -99,30 +99,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* 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.
-       */
-
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
        * registers (and perhaps also the LR).  These will be restored
        * by the signal trampoline after the signal has been delivered.
@@ -162,14 +138,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
       tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
       tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm/src/armv7-r/arm_schedulesigaction.c 
b/arch/arm/src/armv7-r/arm_schedulesigaction.c
index 7d8d935c59..4946d0e0ac 100644
--- a/arch/arm/src/armv7-r/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c
@@ -95,22 +95,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return lr and cpsr and one scratch register.  These
        * will be restored by the signal trampoline after the signals
        * have been delivered.
@@ -142,14 +126,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 #ifdef CONFIG_ARM_THUMB
       tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm/src/armv8-m/arm_schedulesigaction.c 
b/arch/arm/src/armv8-m/arm_schedulesigaction.c
index d11025a544..ea12ca1e48 100644
--- a/arch/arm/src/armv8-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c
@@ -99,30 +99,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* 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.
-       */
-
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
        * registers (and perhaps also the LR).  These will be restored
        * by the signal trampoline after the signal has been delivered.
@@ -162,14 +138,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
       tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
       tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm/src/armv8-r/arm_schedulesigaction.c 
b/arch/arm/src/armv8-r/arm_schedulesigaction.c
index b61a0bd39c..94f1111c37 100644
--- a/arch/arm/src/armv8-r/arm_schedulesigaction.c
+++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c
@@ -95,22 +95,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-      /* If we signaling a task running on the other CPU, we have
-       * to PAUSE the other CPU.
-       */
-
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return lr and cpsr and one scratch register.  These
        * will be restored by the signal trampoline after the signals
        * have been delivered.
@@ -142,14 +126,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 #ifdef CONFIG_ARM_THUMB
       tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/arm64/src/common/arm64_schedulesigaction.c 
b/arch/arm64/src/common/arm64_schedulesigaction.c
index 78529d48db..cbfc897ded 100644
--- a/arch/arm64/src/common/arm64_schedulesigaction.c
+++ b/arch/arm64/src/common/arm64_schedulesigaction.c
@@ -132,18 +132,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return lr and cpsr and one scratch register.  These
        * will be restored by the signal trampoline after the signals
        * have been delivered.
@@ -154,14 +142,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
       /* create signal process context */
 
       arm64_init_signal_process(tcb, NULL);
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/ceva/src/common/ceva_schedulesigaction.c 
b/arch/ceva/src/common/ceva_schedulesigaction.c
index 2de479d814..c96a741141 100644
--- a/arch/ceva/src/common/ceva_schedulesigaction.c
+++ b/arch/ceva/src/common/ceva_schedulesigaction.c
@@ -112,21 +112,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 
       else
         {
-#ifdef CONFIG_SMP
-          /* 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 */
-#endif
-
           /* Save the current register context location */
 
           tcb->xcp.saved_regs = up_current_regs();
@@ -152,15 +137,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
           up_current_regs()[REG_OM] &= ~REG_OM_MASK;
           up_current_regs()[REG_OM] |=  REG_OM_KERNEL;
 #endif
-
-#ifdef CONFIG_SMP
-          /* RESUME the other CPU if it was PAUSED */
-
-          if (cpu != me)
-            {
-              up_cpu_resume(cpu);
-            }
-#endif
         }
     }
 
diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c 
b/arch/risc-v/src/common/riscv_schedulesigaction.c
index 7ff6e3e94e..076d11f1fb 100644
--- a/arch/risc-v/src/common/riscv_schedulesigaction.c
+++ b/arch/risc-v/src/common/riscv_schedulesigaction.c
@@ -98,18 +98,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the return EPC and STATUS registers.  These will be
        * by the signal trampoline after the signal has been delivered.
        */
@@ -146,13 +134,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 #endif
 
       tcb->xcp.regs[REG_INT_CTX] = int_ctx;
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c 
b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c
index b6635297d5..e54871576a 100644
--- a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c
+++ b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c
@@ -204,79 +204,32 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 
       else
         {
-          /* If we signaling a task running on the other CPU, we have
-           * to PAUSE the other CPU.
+          /* tcb is running on the same CPU */
+
+          /* Save registers that must be protected while the signal
+           * handler runs. These will be restored by the signal
+           * trampoline after the signal(s) have been delivered.
            */
 
-          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.
-               */
-
-              tcb->xcp.saved_pc     = tcb->xcp.regs[REG_PC];
-              tcb->xcp.saved_npc    = tcb->xcp.regs[REG_NPC];
-              tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR];
-
-              /* Then set up vector to the trampoline with interrupts
-               * disabled.  We must already be in privileged thread mode
-               * to be here.
-               */
-
-              tcb->xcp.regs[REG_PC]  = (uint32_t)sparc_sigdeliver;
-              tcb->xcp.regs[REG_NPC] = (uint32_t)sparc_sigdeliver + 4;
-              tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK;
-            }
-          else
-            {
-              /* tcb is running on the same CPU */
-
-              /* Save registers that must be protected while the signal
-               * handler runs. These will be restored by the signal
-               * trampoline after the signal(s) have been delivered.
-               */
-
-              tcb->xcp.saved_pc     = up_current_regs()[REG_PC];
-              tcb->xcp.saved_npc    = up_current_regs()[REG_NPC];
-              tcb->xcp.saved_status = up_current_regs()[REG_PSR];
-
-              /* Then set up vector to the trampoline with interrupts
-               * disabled.  The kernel-space trampoline must run in
-               * privileged thread mode.
-               */
-
-              up_current_regs()[REG_PC]  = (uint32_t)sparc_sigdeliver;
-              up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver
-                                            + 4;
-              up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
-
-              /* And make sure that the saved context in the TCB is the
-               * same as the interrupt return context.
-               */
-
-              sparc_savestate(tcb->xcp.regs);
-            }
-
-          /* 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
+          tcb->xcp.saved_pc     = up_current_regs()[REG_PC];
+          tcb->xcp.saved_npc    = up_current_regs()[REG_NPC];
+          tcb->xcp.saved_status = up_current_regs()[REG_PSR];
+
+          /* Then set up vector to the trampoline with interrupts
+           * disabled.  The kernel-space trampoline must run in
+           * privileged thread mode.
            */
 
-          /* RESUME the other CPU if it was PAUSED */
+          up_current_regs()[REG_PC]  = (uint32_t)sparc_sigdeliver;
+          up_current_regs()[REG_NPC] = (uint32_t)sparc_sigdeliver
+                                        + 4;
+          up_current_regs()[REG_PSR] |= SPARC_PSR_ET_MASK;
+
+          /* And make sure that the saved context in the TCB is the
+           * same as the interrupt return context.
+           */
 
-          if (cpu != me)
-            {
-              up_cpu_resume(cpu);
-            }
+          sparc_savestate(tcb->xcp.regs);
         }
     }
 
diff --git a/arch/x86_64/src/intel64/intel64_schedulesigaction.c 
b/arch/x86_64/src/intel64/intel64_schedulesigaction.c
index de7b30cd8f..d9d01d23ef 100644
--- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c
+++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c
@@ -157,6 +157,7 @@ void up_schedule_sigaction(struct tcb_s *tcb)
        */
 
       tcb->xcp.regs[REG_RIP]    = (uint64_t)x86_64_sigdeliver;
+      tcb->xcp.regs[REG_RIP]    = tcb->xcp.regs[REG_RIP] - 8;
       tcb->xcp.regs[REG_RFLAGS] = 0;
     }
 }
@@ -202,76 +203,30 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 
       else
         {
-          /* If we signaling a task running on the other CPU, we have
-           * to PAUSE the other CPU.
-           */
-
-          if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-            {
-              /* 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.
-               */
-
-              tcb->xcp.saved_rip        = tcb->xcp.regs[REG_RIP];
-              tcb->xcp.saved_rsp        = tcb->xcp.regs[REG_RSP];
-              tcb->xcp.saved_rflags     = tcb->xcp.regs[REG_RFLAGS];
+          /* tcb is running on the same CPU */
 
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
-
-              tcb->xcp.regs[REG_RIP]    = (uint64_t)x86_64_sigdeliver;
-              tcb->xcp.regs[REG_RSP]    = tcb->xcp.regs[REG_RSP] - 8;
-              tcb->xcp.regs[REG_RFLAGS] = 0;
-            }
-          else
-            {
-              /* tcb is running on the same CPU */
-
-              /* Save the return lr and cpsr and one scratch register.
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              tcb->xcp.saved_rip         = up_current_regs()[REG_RIP];
-              tcb->xcp.saved_rsp         = up_current_regs()[REG_RSP];
-              tcb->xcp.saved_rflags      = up_current_regs()[REG_RFLAGS];
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
+          /* Save the return lr and cpsr and one scratch register.
+           * These will be restored by the signal trampoline after
+           * the signals have been delivered.
+           */
 
-              up_current_regs()[REG_RIP]    = (uint64_t)x86_64_sigdeliver;
-              up_current_regs()[REG_RSP]    = up_current_regs()[REG_RSP] - 8;
-              up_current_regs()[REG_RFLAGS] = 0;
+          tcb->xcp.saved_rip         = up_current_regs()[REG_RIP];
+          tcb->xcp.saved_rsp         = up_current_regs()[REG_RSP];
+          tcb->xcp.saved_rflags      = up_current_regs()[REG_RFLAGS];
 
-              /* And make sure that the saved context in the TCB
-               * is the same as the interrupt return context.
-               */
+          /* Then set up to vector to the trampoline with interrupts
+           * disabled
+           */
 
-              x86_64_savestate(tcb->xcp.regs);
-            }
+          up_current_regs()[REG_RIP]    = (uint64_t)x86_64_sigdeliver;
+          up_current_regs()[REG_RIP]    = up_current_regs()[REG_RIP] - 8;
+          up_current_regs()[REG_RFLAGS] = 0;
 
-          /* 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
+          /* And make sure that the saved context in the TCB
+           * is the same as the interrupt return context.
            */
 
-          /* RESUME the other CPU if it was PAUSED */
-
-          if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-            {
-              up_cpu_resume(cpu);
-            }
+          x86_64_savestate(tcb->xcp.regs);
         }
     }
 
diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c 
b/arch/xtensa/src/common/xtensa_schedsigaction.c
index 71c51fe32e..0a37b5bcca 100644
--- a/arch/xtensa/src/common/xtensa_schedsigaction.c
+++ b/arch/xtensa/src/common/xtensa_schedsigaction.c
@@ -98,18 +98,6 @@ void up_schedule_sigaction(struct tcb_s *tcb)
     }
   else
     {
-#ifdef CONFIG_SMP
-      int cpu = tcb->cpu;
-      int me  = this_cpu();
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          /* Pause the CPU */
-
-          up_cpu_pause(cpu);
-        }
-#endif
-
       /* Save the context registers.  These will be restored by the
        * signal trampoline after the signals have been delivered.
        *
@@ -152,14 +140,5 @@ void up_schedule_sigaction(struct tcb_s *tcb)
 #ifndef CONFIG_BUILD_FLAT
       xtensa_raiseprivilege(tcb->xcp.regs);
 #endif
-
-#ifdef CONFIG_SMP
-      /* RESUME the other CPU if it was PAUSED */
-
-      if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          up_cpu_resume(cpu);
-        }
-#endif
     }
 }
diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c
index 8f94d93b78..d726d5c3ae 100644
--- a/sched/signal/sig_dispatch.c
+++ b/sched/signal/sig_dispatch.c
@@ -46,10 +46,57 @@
 #include "signal/signal.h"
 #include "mqueue/mqueue.h"
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct sig_arg_s
+{
+  pid_t pid;
+  cpu_set_t saved_affinity;
+  uint16_t saved_flags;
+  bool need_restore;
+};
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
+#ifdef CONFIG_SMP
+static int sig_handler(FAR void *cookie)
+{
+  FAR struct sig_arg_s *arg = cookie;
+  FAR struct tcb_s *tcb;
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+  tcb = nxsched_get_tcb(arg->pid);
+
+  if (!tcb || tcb->task_state == TSTATE_TASK_INVALID ||
+      (tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
+    {
+      /* There is no TCB with this pid or, if there is, it is not a task. */
+
+      leave_critical_section(flags);
+      return -ESRCH;
+    }
+
+  if (arg->need_restore)
+    {
+      tcb->affinity = arg->saved_affinity;
+      tcb->flags = arg->saved_flags;
+    }
+
+  if (tcb->sigdeliver)
+    {
+      up_schedule_sigaction(tcb);
+    }
+
+  leave_critical_section(flags);
+  return OK;
+}
+#endif
+
 /****************************************************************************
  * Name: nxsig_queue_action
  *
@@ -117,8 +164,39 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, 
siginfo_t *info)
 
           if (!stcb->sigdeliver)
             {
+#ifdef CONFIG_SMP
+              int cpu = stcb->cpu;
+              int me  = this_cpu();
+
               stcb->sigdeliver = nxsig_deliver;
-              up_schedule_sigaction(stcb);
+              if (cpu != me && stcb->task_state == TSTATE_TASK_RUNNING)
+                {
+                  struct sig_arg_s arg;
+
+                  if ((stcb->flags & TCB_FLAG_CPU_LOCKED) != 0)
+                    {
+                      arg.need_restore   = false;
+                    }
+                  else
+                    {
+                      arg.saved_flags    = stcb->flags;
+                      arg.saved_affinity = stcb->affinity;
+                      arg.need_restore   = true;
+
+                      stcb->flags        |= TCB_FLAG_CPU_LOCKED;
+                      CPU_SET(stcb->cpu, &stcb->affinity);
+                    }
+
+                  arg.pid = stcb->pid;
+                  nxsched_smp_call_single(stcb->cpu, sig_handler, &arg,
+                                          true);
+                }
+              else
+#endif
+                {
+                  stcb->sigdeliver = nxsig_deliver;
+                  up_schedule_sigaction(stcb);
+                }
             }
 
           leave_critical_section(flags);

Reply via email to