From 0be78068f17cb2ab152c4ce09704976ac5901870 Mon Sep 17 00:00:00 2001 From: hujun5 Date: Mon, 9 Sep 2024 21:15:00 +0800 Subject: [PATCH] sched: replace sync pause with async pause for nxsig_process Signed-off-by: hujun5 --- 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 ------ .../src/common/arm64_schedulesigaction.c | 21 ----- arch/ceva/src/common/ceva_schedulesigaction.c | 24 ----- .../src/common/riscv_schedulesigaction.c | 20 ----- .../src/sparc_v8/sparc_v8_schedulesigaction.c | 89 +++++-------------- .../src/intel64/intel64_schedulesigaction.c | 77 ++++------------ .../xtensa/src/common/xtensa_schedsigaction.c | 21 ----- sched/signal/sig_dispatch.c | 79 +++++++++++++++- 13 files changed, 115 insertions(+), 398 deletions(-) diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c index 6f0f9316afe33..fa08f75189a64 100644 --- a/arch/arm/src/armv6-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c @@ -101,30 +101,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. @@ -160,14 +136,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 122dee4002af5..d527cce49a45c 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/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 lr and cpsr and one scratch register. These * will be restored by the signal trampoline after the signals * have been delivered. @@ -154,14 +130,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 8f16b70a16630..08010e166d7a6 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -102,30 +102,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. @@ -165,14 +141,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 9cc209e01789a..b6533d73a042a 100644 --- a/arch/arm/src/armv7-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c @@ -97,22 +97,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. @@ -144,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/armv8-m/arm_schedulesigaction.c b/arch/arm/src/armv8-m/arm_schedulesigaction.c index 4162f1f54996f..f8427afb8617a 100644 --- a/arch/arm/src/armv8-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c @@ -102,30 +102,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. @@ -165,14 +141,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 622a1213dafb3..2b2f2a56f7224 100644 --- a/arch/arm/src/armv8-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c @@ -97,22 +97,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. @@ -144,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/arm64/src/common/arm64_schedulesigaction.c b/arch/arm64/src/common/arm64_schedulesigaction.c index 9bed735a6bb51..cb2f9bedf0f9f 100644 --- a/arch/arm64/src/common/arm64_schedulesigaction.c +++ b/arch/arm64/src/common/arm64_schedulesigaction.c @@ -148,18 +148,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. @@ -173,14 +161,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 44a4c80aef20f..88e9d8c34696d 100644 --- a/arch/ceva/src/common/ceva_schedulesigaction.c +++ b/arch/ceva/src/common/ceva_schedulesigaction.c @@ -115,21 +115,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(); @@ -155,15 +140,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 24cd523c48cb1..81468dd60dddb 100644 --- a/arch/risc-v/src/common/riscv_schedulesigaction.c +++ b/arch/risc-v/src/common/riscv_schedulesigaction.c @@ -100,18 +100,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. */ @@ -148,13 +136,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 a49a94c270c3e..3f6b0510a2aa0 100644 --- a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c +++ b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c @@ -206,79 +206,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 fa28e477c7f5a..e6fc4bc09b514 100644 --- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c +++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c @@ -203,74 +203,29 @@ 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_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_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_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 45f015d3ddf86..73e00f1d6e6cc 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -100,18 +100,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. * @@ -154,14 +142,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 8f94d93b78adb..6eecbf8d26070 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 * @@ -118,7 +165,37 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, siginfo_t *info) if (!stcb->sigdeliver) { stcb->sigdeliver = nxsig_deliver; - up_schedule_sigaction(stcb); +#ifdef CONFIG_SMP + int cpu = stcb->cpu; + int me = this_cpu(); + + 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 + { + up_schedule_sigaction(stcb); + } } leave_critical_section(flags);