From 4fd92edee7ff36b50af7a8e4c6669ea0e882cf3f 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 | 87 +++++-------------- .../src/intel64/intel64_schedulesigaction.c | 83 ++++-------------- .../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 */ + 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]; - 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 + /* 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; - if (cpu != me) - { - up_cpu_resume(cpu); - } + /* And make sure that the saved context in the TCB is the + * same as the interrupt return context. + */ + + 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. + /* 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. */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + 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]; - 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]; - - /* 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 - */ - - 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; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - x86_64_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 + /* Then set up to vector to the trampoline with interrupts + * disabled */ - /* RESUME the other CPU if it was PAUSED */ + 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; - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + 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);