diff --git a/arch/arm/src/arm/arm_schedulesigaction.c b/arch/arm/src/arm/arm_schedulesigaction.c index 2643eb3f0d..1eca541afa 100644 --- a/arch/arm/src/arm/arm_schedulesigaction.c +++ b/arch/arm/src/arm/arm_schedulesigaction.c @@ -75,70 +75,61 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; + /* In this case just deliver the signal now. */ - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + (tcb->sigdeliver)(tcb); + tcb->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 lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + /* Save the current register context location */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. */ + tcb->xcp.saved_regs = tcb->xcp.regs; - sigdeliver(tcb); - tcb->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. + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. */ - else - { - /* 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.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - /* Save the current register context location */ + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - tcb->xcp.saved_regs = tcb->xcp.regs; + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT; #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif - } } } diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c index dfd5031bfd..1bc4929820 100644 --- a/arch/arm/src/armv6-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c @@ -78,103 +78,93 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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 (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - 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. - */ + /* 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* 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. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to 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)arm_sigdeliver; - tcb->xcp.regs[REG_PRIMASK] = 1; - tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + 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 */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + 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 2727d545db..75b0bb5598 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -77,98 +77,89 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on this CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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 (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - 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. - */ + /* 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + 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 05da1b9d4e..8786085526 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -79,107 +79,97 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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 (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - 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. - */ + /* 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* 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. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to 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)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV7M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + 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 */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + 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 f23262badf..7d8d935c59 100644 --- a/arch/arm/src/armv7-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c @@ -75,90 +75,81 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + 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 6c2c936275..d11025a544 100644 --- a/arch/arm/src/armv8-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c @@ -79,107 +79,97 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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 (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - 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. - */ + /* 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* 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. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to 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)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV8M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + 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 */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + 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 77ee55430e..b61a0bd39c 100644 --- a/arch/arm/src/armv8-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c @@ -75,90 +75,81 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); - - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + 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(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); #ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; + tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + up_cpu_resume(cpu); } +#endif } } diff --git a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c index fcc2bdcc25..cf2176e3ad 100644 --- a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c +++ b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c @@ -75,67 +75,58 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; + /* In this case just deliver the signal now. */ - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + (tcb->sigdeliver)(tcb); + tcb->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 lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), - this_task()->xcp.regs); + /* Save the current register context location */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. */ + tcb->xcp.saved_regs = tcb->xcp.regs; - sigdeliver(tcb); - tcb->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. + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. */ - else - { - /* 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.regs = (void *)((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - /* Save the current register context location */ + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - tcb->xcp.saved_regs = tcb->xcp.regs; + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; - tcb->xcp.regs[REG_IRQ_EN] = 0; - } + tcb->xcp.regs[REG_LR] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; + tcb->xcp.regs[REG_IRQ_EN] = 0; } } diff --git a/arch/arm64/src/common/arm64_schedulesigaction.c b/arch/arm64/src/common/arm64_schedulesigaction.c index 05c5725bb4..78529d48db 100644 --- a/arch/arm64/src/common/arm64_schedulesigaction.c +++ b/arch/arm64/src/common/arm64_schedulesigaction.c @@ -112,62 +112,56 @@ void arm64_init_signal_process(struct tcb_s *tcb, struct regs_context *regs) * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - else - { + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { #ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* 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_reg = tcb->xcp.regs; + tcb->xcp.saved_reg = tcb->xcp.regs; - /* create signal process context */ + /* create signal process context */ - arm64_init_signal_process(tcb, NULL); + arm64_init_signal_process(tcb, NULL); #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + up_cpu_resume(cpu); } +#endif } } diff --git a/arch/avr/src/avr/avr_schedulesigaction.c b/arch/avr/src/avr/avr_schedulesigaction.c index bf00b6c943..02f7d16132 100644 --- a/arch/avr/src/avr/avr_schedulesigaction.c +++ b/arch/avr/src/avr/avr_schedulesigaction.c @@ -75,120 +75,112 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uintptr_t reg_ptr = (uintptr_t)avr_sigdeliver; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* 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_pc0 = up_current_regs()[REG_PC0]; - tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1]; -#if defined(REG_PC2) - tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2]; -#endif - tcb->xcp.saved_sreg = up_current_regs()[REG_SREG]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - -#if !defined(REG_PC2) - up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8; - up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff; -#else - up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16; - up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8; - up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff; -#endif - up_current_regs()[REG_SREG] &= ~(1 << SREG_I); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - avr_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 + * g_current_regs does not refer to the thread of this_task()! */ else { - /* Save registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have been delivered. + /* 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_pc0 = tcb->xcp.regs[REG_PC0]; - tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1]; + tcb->xcp.saved_pc0 = up_current_regs()[REG_PC0]; + tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1]; #if defined(REG_PC2) - tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2]; + tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2]; #endif - tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; + tcb->xcp.saved_sreg = up_current_regs()[REG_SREG]; /* Then set up to vector to the trampoline with interrupts * disabled */ #if !defined(REG_PC2) - tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8; - tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff; + up_current_regs()[REG_PC0] = (uint16_t)reg_ptr >> 8; + up_current_regs()[REG_PC1] = (uint16_t)reg_ptr & 0xff; #else - tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16; - tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8; - tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff; - + up_current_regs()[REG_PC0] = (uint32_t)reg_ptr >> 16; + up_current_regs()[REG_PC1] = (uint32_t)reg_ptr >> 8; + up_current_regs()[REG_PC2] = (uint32_t)reg_ptr & 0xff; #endif - tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I); + up_current_regs()[REG_SREG] &= ~(1 << SREG_I); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + avr_savestate(tcb->xcp.regs); } } + + /* 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 registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc0 = tcb->xcp.regs[REG_PC0]; + tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1]; +#if defined(REG_PC2) + tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2]; +#endif + tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + +#if !defined(REG_PC2) + tcb->xcp.regs[REG_PC0] = (uint16_t)reg_ptr >> 8; + tcb->xcp.regs[REG_PC1] = (uint16_t)reg_ptr & 0xff; +#else + tcb->xcp.regs[REG_PC0] = (uint32_t)reg_ptr >> 16; + tcb->xcp.regs[REG_PC1] = (uint32_t)reg_ptr >> 8; + tcb->xcp.regs[REG_PC2] = (uint32_t)reg_ptr & 0xff; + +#endif + tcb->xcp.regs[REG_SREG] &= ~(1 << SREG_I); + } } diff --git a/arch/avr/src/avr32/avr_schedulesigaction.c b/arch/avr/src/avr32/avr_schedulesigaction.c index 294bd31bcc..66ead0617a 100644 --- a/arch/avr/src/avr32/avr_schedulesigaction.c +++ b/arch/avr/src/avr32/avr_schedulesigaction.c @@ -75,95 +75,87 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* 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_sr = up_current_regs()[REG_SR]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver; - up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - avr_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 + * g_current_regs does not refer to the thread of this_task()! */ else { - /* Save registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have been delivered. + /* 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 = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_SR]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver; - tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK; + up_current_regs()[REG_PC] = (uint32_t)avr_sigdeliver; + up_current_regs()[REG_SR] |= AVR32_SR_GM_MASK; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + avr_savestate(tcb->xcp.regs); } } + + /* 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 registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)avr_sigdeliver; + tcb->xcp.regs[REG_SR] |= AVR32_SR_GM_MASK; + } } diff --git a/arch/ceva/src/common/ceva_schedulesigaction.c b/arch/ceva/src/common/ceva_schedulesigaction.c index 7f79d23341..2de479d814 100644 --- a/arch/ceva/src/common/ceva_schedulesigaction.c +++ b/arch/ceva/src/common/ceva_schedulesigaction.c @@ -72,139 +72,130 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - DEBUGASSERT(tcb != NULL && sigdeliver != NULL); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (tcb->sigdeliver == NULL) + if (tcb->task_state == TSTATE_TASK_RUNNING) { - tcb->sigdeliver = sigdeliver; + uint8_t me = this_cpu(); +#ifdef CONFIG_SMP + uint8_t cpu = tcb->cpu; +#else + uint8_t cpu = 0; +#endif - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* CASE 1: We are not in an interrupt handler and a task is + * signaling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) + if (cpu == me && !up_current_regs()) { - uint8_t me = this_cpu(); -#ifdef CONFIG_SMP - uint8_t cpu = tcb->cpu; -#else - uint8_t cpu = 0; -#endif + /* In this case just deliver the signal now. */ - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - - /* 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 - { -#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(); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_current_regs() -= XCPTCONTEXT_REGS; - memcpy(up_current_regs(), up_current_regs() + - XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)up_current_regs(); - - /* Then set up to vector to the trampoline with interrupts - * unchanged. We must already be in privileged thread mode - * to be here. - */ - - up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver; -#ifdef REG_OM - 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 - } + (tcb->sigdeliver)(tcb); + tcb->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 signaling some other non-running task. + /* 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 { +#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 = tcb->xcp.regs; + 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. + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. */ - tcb->xcp.regs -= XCPTCONTEXT_REGS; - memcpy(tcb->xcp.regs, tcb->xcp.regs + - XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); + up_current_regs() -= XCPTCONTEXT_REGS; + memcpy(up_current_regs(), up_current_regs() + + XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs; + up_current_regs()[REG_SP] = (uint32_t)up_current_regs(); /* Then set up to vector to the trampoline with interrupts - * unchanged. We must already be in privileged thread mode to be - * here. + * unchanged. We must already be in privileged thread mode + * to be here. */ - tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver; + up_current_regs()[REG_PC] = (uint32_t)ceva_sigdeliver; #ifdef REG_OM - tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK; - tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL; + 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 } } + + /* 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 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 -= XCPTCONTEXT_REGS; + memcpy(tcb->xcp.regs, tcb->xcp.regs + + XCPTCONTEXT_REGS, XCPTCONTEXT_SIZE); + + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs; + + /* Then set up to vector to the trampoline with interrupts + * unchanged. We must already be in privileged thread mode to be + * here. + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)ceva_sigdeliver; +#ifdef REG_OM + tcb->xcp.regs[REG_OM] &= ~REG_OM_MASK; + tcb->xcp.regs[REG_OM] |= REG_OM_KERNEL; +#endif + } } #endif /* !CONFIG_DISABLE_SIGNALS */ diff --git a/arch/mips/src/mips32/mips_schedulesigaction.c b/arch/mips/src/mips32/mips_schedulesigaction.c index 7d1cd3a9ee..32501b02eb 100644 --- a/arch/mips/src/mips32/mips_schedulesigaction.c +++ b/arch/mips/src/mips32/mips_schedulesigaction.c @@ -76,88 +76,41 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uint32_t status; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; - tcb->xcp.saved_status = up_current_regs()[REG_STATUS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver; - status = up_current_regs()[REG_STATUS]; - status &= ~CP0_STATUS_INT_MASK; - status |= CP0_STATUS_INT_SW0; - up_current_regs()[REG_STATUS] = status; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - mips_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 - " New: %08" PRIx32 "/%08" PRIx32 "\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_EPC], - up_current_regs()[REG_STATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 + * g_current_regs does not refer to the thread of this_task()! */ else @@ -167,23 +120,62 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; - tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS]; + tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; + tcb->xcp.saved_status = up_current_regs()[REG_STATUS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver; - status = tcb->xcp.regs[REG_STATUS]; - status &= ~CP0_STATUS_INT_MASK; - status |= CP0_STATUS_INT_SW0; - tcb->xcp.regs[REG_STATUS] = status; + up_current_regs()[REG_EPC] = (uint32_t)mips_sigdeliver; + status = up_current_regs()[REG_STATUS]; + status &= ~CP0_STATUS_INT_MASK; + status |= CP0_STATUS_INT_SW0; + up_current_regs()[REG_STATUS] = status; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + mips_savestate(tcb->xcp.regs); sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 " New: %08" PRIx32 "/%08" PRIx32 "\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + up_current_regs()[REG_EPC], + up_current_regs()[REG_STATUS]); } } + + /* 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. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; + tcb->xcp.saved_status = tcb->xcp.regs[REG_STATUS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EPC] = (uint32_t)mips_sigdeliver; + status = tcb->xcp.regs[REG_STATUS]; + status &= ~CP0_STATUS_INT_MASK; + status |= CP0_STATUS_INT_SW0; + tcb->xcp.regs[REG_STATUS] = status; + + sinfo("PC/STATUS Saved: %08" PRIx32 "/%08" PRIx32 + " New: %08" PRIx32 "/%08" PRIx32 "\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + } } diff --git a/arch/misoc/src/lm32/lm32_schedulesigaction.c b/arch/misoc/src/lm32/lm32_schedulesigaction.c index f694a22e45..437f180d75 100644 --- a/arch/misoc/src/lm32/lm32_schedulesigaction.c +++ b/arch/misoc/src/lm32/lm32_schedulesigaction.c @@ -75,81 +75,39 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver; - up_current_regs()[REG_INT_CTX] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - misoc_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_EPC], - up_current_regs()[REG_STATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 + * g_current_regs does not refer to the thread of this_task()! */ else @@ -159,19 +117,53 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; - tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX]; + tcb->xcp.saved_epc = up_current_regs()[REG_EPC]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver; - tcb->xcp.regs[REG_INT_CTX] = 0; + up_current_regs()[REG_EPC] = (uint32_t)lm32_sigdeliver; + up_current_regs()[REG_INT_CTX] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + misoc_savestate(tcb->xcp.regs); sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + up_current_regs()[REG_EPC], + up_current_regs()[REG_STATUS]); } } + + /* 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. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC]; + tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EPC] = (uint32_t)lm32_sigdeliver; + tcb->xcp.regs[REG_INT_CTX] = 0; + + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]); + } } diff --git a/arch/misoc/src/minerva/minerva_schedulesigaction.c b/arch/misoc/src/minerva/minerva_schedulesigaction.c index 02a02952e5..9d8487dc68 100644 --- a/arch/misoc/src/minerva/minerva_schedulesigaction.c +++ b/arch/misoc/src/minerva/minerva_schedulesigaction.c @@ -76,103 +76,95 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 g_current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_CSR_MEPC] = - (uint32_t)minerva_sigdeliver; - up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - misoc_savestate(tcb->xcp.regs); - - sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", - tcb->xcp.saved_epc, tcb->xcp.saved_status, - up_current_regs()[REG_CSR_MEPC], - up_current_regs()[REG_CSR_MSTATUS]); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 g_current_regs does not + * refer to the thread of this_task()! */ else { /* Save the return EPC and STATUS registers. These will be - * restored by the signal trampoline after the signals have been - * delivered. + * restored by the signal trampoline after the signals have + * been delivered. */ - tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC]; - tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS]; + tcb->xcp.saved_epc = up_current_regs()[REG_CSR_MEPC]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver; + up_current_regs()[REG_CSR_MEPC] = + (uint32_t)minerva_sigdeliver; up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; + /* And make sure that the saved context in the TCB is the same + * as the interrupt return context. + */ + + misoc_savestate(tcb->xcp.regs); + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", tcb->xcp.saved_epc, tcb->xcp.saved_status, - tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]); + up_current_regs()[REG_CSR_MEPC], + up_current_regs()[REG_CSR_MSTATUS]); } } + + /* 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. + */ + + tcb->xcp.saved_epc = tcb->xcp.regs[REG_CSR_MEPC]; + tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_CSR_MSTATUS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_CSR_MEPC] = (uint32_t) minerva_sigdeliver; + up_current_regs()[REG_CSR_MSTATUS] &= ~CSR_MSTATUS_MIE; + + sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n", + tcb->xcp.saved_epc, tcb->xcp.saved_status, + tcb->xcp.regs[REG_CSR_MEPC], tcb->xcp.regs[REG_CSR_MSTATUS]); + } } diff --git a/arch/or1k/src/common/or1k_schedulesigaction.c b/arch/or1k/src/common/or1k_schedulesigaction.c index 00e8944f6f..c7f56ede5b 100644 --- a/arch/or1k/src/common/or1k_schedulesigaction.c +++ b/arch/or1k/src/common/or1k_schedulesigaction.c @@ -74,80 +74,39 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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()! - */ - - else - { - /* 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_pc = up_current_regs()[REG_PC]; - * tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR]; - */ - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver; - * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT | - * PSR_F_BIT; - */ - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - or1k_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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()! */ else @@ -157,17 +116,50 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - - /* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */ + /* tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + * tcb->xcp.saved_cpsr = up_current_regs()[REG_CPSR]; + */ /* Then set up to vector to the trampoline with interrupts * disabled */ - /* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver; - * tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + /* up_current_regs()[REG_PC] = (uint32_t)or1k_sigdeliver; + * up_current_regs()[REG_CPSR] = SVC_MODE | PSR_I_BIT | + * PSR_F_BIT; */ + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + or1k_savestate(tcb->xcp.regs); } } + + /* 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 lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + + /* tcb->xcp.saved_cpsr = tcb->xcp.regs[REG_CPSR]; */ + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + /* tcb->xcp.regs[REG_PC] = (uint32_t)or1k_sigdeliver; + * tcb->xcp.regs[REG_CPSR] = SVC_MODE | PSR_I_BIT | PSR_F_BIT; + */ + } } diff --git a/arch/renesas/src/m16c/m16c_schedulesigaction.c b/arch/renesas/src/m16c/m16c_schedulesigaction.c index 6f6d879c2c..58a5fe23e7 100644 --- a/arch/renesas/src/m16c/m16c_schedulesigaction.c +++ b/arch/renesas/src/m16c/m16c_schedulesigaction.c @@ -74,73 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC]; - tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1]; - tcb->xcp.saved_flg = up_current_regs()[REG_FLG]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; - up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_FLG] &= ~M16C_FLG_I; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else @@ -150,17 +110,49 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1]; - tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG]; + tcb->xcp.saved_pc[0] = up_current_regs()[REG_PC]; + tcb->xcp.saved_pc[1] = up_current_regs()[REG_PC + 1]; + tcb->xcp.saved_flg = up_current_regs()[REG_FLG]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; - tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; + up_current_regs()[REG_PC + 1] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_FLG] &= ~M16C_FLG_I; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* 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 PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc[0] = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_pc[1] = tcb->xcp.regs[REG_PC + 1]; + tcb->xcp.saved_flg = tcb->xcp.regs[REG_FLG]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver >> 8; + tcb->xcp.regs[REG_PC + 1] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_FLG] &= ~M16C_FLG_I; + } } diff --git a/arch/renesas/src/rx65n/rx65n_schedulesigaction.c b/arch/renesas/src/rx65n/rx65n_schedulesigaction.c index 3956a41844..bdbe03cb96 100644 --- a/arch/renesas/src/rx65n/rx65n_schedulesigaction.c +++ b/arch/renesas/src/rx65n/rx65n_schedulesigaction.c @@ -74,71 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_sr = up_current_regs()[REG_PSW]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_PSW] |= 0x00030000; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else @@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_PSW]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_PSW] |= 0x00030000; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_PSW] |= 0x00030000; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* 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 PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_PSW]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_PSW] |= 0x00030000; + } } diff --git a/arch/renesas/src/sh1/sh1_schedulesigaction.c b/arch/renesas/src/sh1/sh1_schedulesigaction.c index 94b9c39dfb..c5271a566e 100644 --- a/arch/renesas/src/sh1/sh1_schedulesigaction.c +++ b/arch/renesas/src/sh1/sh1_schedulesigaction.c @@ -74,71 +74,33 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Save the return PC and SR and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - tcb->xcp.saved_pc = up_current_regs()[REG_PC]; - tcb->xcp.saved_sr = up_current_regs()[REG_SR]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; - up_current_regs()[REG_SR] |= 0x000000f0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - renesas_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else @@ -148,15 +110,45 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * the signals have been delivered. */ - tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; - tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + tcb->xcp.saved_pc = up_current_regs()[REG_PC]; + tcb->xcp.saved_sr = up_current_regs()[REG_SR]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; - tcb->xcp.regs[REG_SR] |= 0x000000f0 ; + up_current_regs()[REG_PC] = (uint32_t)renesas_sigdeliver; + up_current_regs()[REG_SR] |= 0x000000f0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + renesas_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* 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 PC and SR and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_sr = tcb->xcp.regs[REG_SR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)renesas_sigdeliver; + tcb->xcp.regs[REG_SR] |= 0x000000f0 ; + } } diff --git a/arch/risc-v/src/common/riscv_schedulesigaction.c b/arch/risc-v/src/common/riscv_schedulesigaction.c index 2b5fe178fb..7ff6e3e94e 100644 --- a/arch/risc-v/src/common/riscv_schedulesigaction.c +++ b/arch/risc-v/src/common/riscv_schedulesigaction.c @@ -76,89 +76,83 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { uintptr_t int_ctx; - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - else - { + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { #ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(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. - */ + /* Save the return EPC and STATUS registers. These will be + * by the signal trampoline after the signal has been delivered. + */ - /* Save the current register context location */ + /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + 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. - */ + /* 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); + tcb->xcp.regs = (uintreg_t *) + ((uintptr_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_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_SP] = (uintptr_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ + /* Then set up to vector to the trampoline with interrupts + * disabled. We must already be in privileged thread mode to be + * here. + */ - tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; + tcb->xcp.regs[REG_EPC] = (uintptr_t)riscv_sigdeliver; - int_ctx = tcb->xcp.regs[REG_INT_CTX]; - int_ctx &= ~STATUS_PIE; + int_ctx = tcb->xcp.regs[REG_INT_CTX]; + int_ctx &= ~STATUS_PIE; #ifndef CONFIG_BUILD_FLAT - int_ctx |= STATUS_PPP; + int_ctx |= STATUS_PPP; #endif - tcb->xcp.regs[REG_INT_CTX] = int_ctx; + tcb->xcp.regs[REG_INT_CTX] = int_ctx; #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + up_cpu_resume(cpu); } +#endif } } diff --git a/arch/sim/src/sim/sim_schedulesigaction.c b/arch/sim/src/sim/sim_schedulesigaction.c index c485dc538d..6bc8aa535b 100644 --- a/arch/sim/src/sim/sim_schedulesigaction.c +++ b/arch/sim/src/sim/sim_schedulesigaction.c @@ -71,27 +71,15 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - irqstate_t flags; - /* We don't have to anything complex for the simulated target */ - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p\n", tcb); - /* Make sure that interrupts are disabled */ - - flags = enter_critical_section(); - - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - if (tcb == this_task()) - { - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; } - - leave_critical_section(flags); } diff --git a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c index aa78155e81..b6635297d5 100644 --- a/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c +++ b/arch/sparc/src/sparc_v8/sparc_v8_schedulesigaction.c @@ -72,245 +72,39 @@ ****************************************************************************/ #ifndef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - irqstate_t flags; + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - /* Make sure that interrupts are disabled */ - - flags = enter_critical_section(); - - /* Refuse to handle nested signal actions */ - - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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()! - */ - - else - { - /* 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 to vector to the trampoline with interrupts - * disabled - */ - - 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); - } + (tcb->sigdeliver)(tcb); + tcb->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 registers that must be protected while the signal handler - * runs. These will be restored by the signal trampoline after - * the signals have 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 to vector to the trampoline with interrupts - * disabled - */ - - 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; - } - } - - leave_critical_section(flags); -} -#endif /* !CONFIG_SMP */ - -#ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - irqstate_t flags; - int cpu; - int me; - - sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); - - /* Make sure that interrupts are disabled */ - - flags = enter_critical_section(); - - /* Refuse to handle nested signal actions */ - - if (!tcb->sigdeliver) - { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=0x%p current_regs=0x%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()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - - /* 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. - */ - - 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 - */ - - /* 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. + /* 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()! */ else @@ -325,16 +119,191 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.saved_status = up_current_regs()[REG_PSR]; /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. + * disabled */ - 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; + 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); } } - leave_critical_section(flags); + /* 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 registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have 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 to vector to the trampoline with interrupts + * disabled + */ + + 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; + } +} +#endif /* !CONFIG_SMP */ + +#ifdef CONFIG_SMP +void up_schedule_sigaction(struct tcb_s *tcb) +{ + int cpu; + int me; + + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); + + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ + + 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()) + { + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! + */ + + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + + /* 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. + */ + + 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 + */ + + /* 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 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 to 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; + } } #endif /* CONFIG_SMP */ diff --git a/arch/tricore/src/common/tricore_schedulesigaction.c b/arch/tricore/src/common/tricore_schedulesigaction.c index ef9eae0135..bc62436d4b 100644 --- a/arch/tricore/src/common/tricore_schedulesigaction.c +++ b/arch/tricore/src/common/tricore_schedulesigaction.c @@ -76,88 +76,81 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - if (tcb == this_task()) + if (up_current_regs() == NULL) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (up_current_regs() == NULL) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 - * g_current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the context registers. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tricore_savestate(tcb->xcp.saved_regs); - - /* Create a new CSA for signal delivery. The new context - * will borrow the process stack of the current tcb. - */ - - up_set_current_regs(tricore_alloc_csa((uintptr_t) - tricore_sigdeliver, - STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), - PSW_IO_SUPERVISOR | PSW_CDE, true)); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 + * g_current_regs does not refer to the thread of this_task()! */ else { - /* Save the return EPC and STATUS registers. These will be + /* Save the context 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; + tricore_savestate(tcb->xcp.saved_regs); /* Create a new CSA for signal delivery. The new context * will borrow the process stack of the current tcb. */ - tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver, - STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), - PSW_IO_SUPERVISOR | PSW_CDE, true); + up_set_current_regs(tricore_alloc_csa((uintptr_t) + tricore_sigdeliver, + STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), + PSW_IO_SUPERVISOR | PSW_CDE, true)); } } + + /* 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; + + /* Create a new CSA for signal delivery. The new context + * will borrow the process stack of the current tcb. + */ + + tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver, + STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)), + PSW_IO_SUPERVISOR | PSW_CDE, true); + } } diff --git a/arch/x86/src/i486/i486_schedulesigaction.c b/arch/x86/src/i486/i486_schedulesigaction.c index 1638583d53..219d3aa9bb 100644 --- a/arch/x86/src/i486/i486_schedulesigaction.c +++ b/arch/x86/src/i486/i486_schedulesigaction.c @@ -70,95 +70,87 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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 g_current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* 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_eip = up_current_regs()[REG_EIP]; - tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver; - up_current_regs()[REG_EFLAGS] = 0; - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - x86_savestate(tcb->xcp.regs); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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 g_current_regs does not + * refer to the thread of this_task()! */ else { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* 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_eip = tcb->xcp.regs[REG_EIP]; - tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS]; + tcb->xcp.saved_eip = up_current_regs()[REG_EIP]; + tcb->xcp.saved_eflags = up_current_regs()[REG_EFLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver; - tcb->xcp.regs[REG_EFLAGS] = 0; + up_current_regs()[REG_EIP] = (uint32_t)x86_sigdeliver; + up_current_regs()[REG_EFLAGS] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + x86_savestate(tcb->xcp.regs); } } + + /* 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 lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.saved_eip = tcb->xcp.regs[REG_EIP]; + tcb->xcp.saved_eflags = tcb->xcp.regs[REG_EFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_EIP] = (uint32_t)x86_sigdeliver; + tcb->xcp.regs[REG_EFLAGS] = 0; + } } diff --git a/arch/x86_64/src/intel64/intel64_schedulesigaction.c b/arch/x86_64/src/intel64/intel64_schedulesigaction.c index 2923c75d1e..de7b30cd8f 100644 --- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c +++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c @@ -71,54 +71,173 @@ ****************************************************************************/ #ifndef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - sinfo("rtcb=%p g_current_regs=%p\n", this_task(), up_current_regs()); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. + /* In this case just deliver the signal with a function call + * now. */ - if (!up_current_regs()) + (tcb->sigdeliver)(tcb); + tcb->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()! + */ + + else + { + /* 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); + } + } + + /* 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 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 = 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_RFLAGS] = 0; + } +} +#else /* !CONFIG_SMP */ +void up_schedule_sigaction(struct tcb_s *tcb) +{ + int cpu; + int me; + + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); + + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ + + 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()) + { + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! + */ + + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + + /* 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 && tcb->task_state == TSTATE_TASK_RUNNING) { - /* In this case just deliver the signal with a function call - * now. + /* 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. */ - sigdeliver(tcb); - tcb->sigdeliver = NULL; + 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; } - - /* 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()! - */ - else { - /* 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 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]; @@ -139,184 +258,46 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) x86_64_savestate(tcb->xcp.regs); } - } - /* 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 lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* 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_rip = tcb->xcp.regs[REG_RIP]; - tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; - tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + /* RESUME the other CPU if it was PAUSED */ - /* 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; + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + up_cpu_resume(cpu); + } } } -} -#else /* !CONFIG_SMP */ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + /* 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. + */ - /* Refuse to handle nested signal actions */ - - if (tcb->sigdeliver == NULL) + else { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any 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. */ - sinfo("rtcb=0x%p current_regs=0x%p\n", this_task(), - up_current_regs()); + 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]; - 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()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - - /* 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 && 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]; - - /* 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 - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - 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. + /* Then set up to vector to the trampoline with interrupts + * disabled */ - else - { - /* 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 = 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; - } + 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; } } #endif /* CONFIG_SMP */ diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c index e021f14ca1..71c51fe32e 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -78,94 +78,88 @@ * ****************************************************************************/ -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, this_task(), + this_task()->xcp.regs); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to task that is currently executing on any CPU. + */ - if (!tcb->sigdeliver) + if (tcb == this_task() && !up_interrupt_context()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (tcb == this_task() && !up_interrupt_context()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->sigdeliver = NULL; - } - else - { + (tcb->sigdeliver)(tcb); + tcb->sigdeliver = NULL; + } + else + { #ifdef CONFIG_SMP - int cpu = tcb->cpu; - int me = this_cpu(); + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - /* Pause the CPU */ + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + /* Pause the CPU */ - up_cpu_pause(cpu); - } + up_cpu_pause(cpu); + } #endif - /* Save the context registers. These will be restored by the - * signal trampoline after the signals have been delivered. - * - * NOTE: that hi-priority interrupts are not disabled. - */ + /* Save the context registers. These will be restored by the + * signal trampoline after the signals have been delivered. + * + * NOTE: that hi-priority interrupts are not disabled. + */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; - if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) - { - tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; - } + if ((tcb->xcp.saved_regs[REG_PS] & PS_EXCM_MASK) != 0) + { + tcb->xcp.saved_regs[REG_PS] &= ~PS_EXCM_MASK; + } - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ + /* Duplicate the register context. These will be + * restored by the signal trampoline after the signal has been + * delivered. + */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); + memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_A1] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; - /* Then set up to vector to the trampoline with interrupts - * disabled - */ + /* Then set up to vector to the trampoline with interrupts + * disabled + */ - tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver; + tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sig_deliver; #ifdef __XTENSA_CALL0_ABI__ - tcb->xcp.regs[REG_PS] = (uint32_t) - (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); + tcb->xcp.regs[REG_PS] = (uint32_t) + (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); #else - tcb->xcp.regs[REG_PS] = (uint32_t) - (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | - PS_WOE | PS_CALLINC(1)); + tcb->xcp.regs[REG_PS] = (uint32_t) + (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | + PS_WOE | PS_CALLINC(1)); #endif #ifndef CONFIG_BUILD_FLAT - xtensa_raiseprivilege(tcb->xcp.regs); + xtensa_raiseprivilege(tcb->xcp.regs); #endif #ifdef CONFIG_SMP - /* RESUME the other CPU if it was PAUSED */ + /* RESUME the other CPU if it was PAUSED */ - if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) - { - up_cpu_resume(cpu); - } -#endif + if (cpu != me && tcb->task_state == TSTATE_TASK_RUNNING) + { + up_cpu_resume(cpu); } +#endif } } diff --git a/arch/z16/src/common/z16_schedulesigaction.c b/arch/z16/src/common/z16_schedulesigaction.c index 3c063c4b83..51cceea436 100644 --- a/arch/z16/src/common/z16_schedulesigaction.c +++ b/arch/z16/src/common/z16_schedulesigaction.c @@ -74,93 +74,85 @@ * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%06x\n", tcb, (uint32_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ - if (!tcb->sigdeliver) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is - * being delivered to the currently executing task. + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) + if (!up_current_regs()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - FAR uint32_t *current_pc = - (FAR uint32_t *)&up_current_regs()[REG_PC]; - - /* Save the return address and interrupt state. These will be - * restored by the signal trampoline after the signals have - * been delivered. - */ - - tcb->xcp.saved_pc = *current_pc; - tcb->xcp.saved_i = up_current_regs()[REG_FLAGS]; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - *current_pc = (uint32_t)z16_sigdeliver; - up_current_regs()[REG_FLAGS] = 0; - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - z16_copystate(tcb->xcp.regs, up_current_regs()); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else { - FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC]; + FAR uint32_t *current_pc = + (FAR uint32_t *)&up_current_regs()[REG_PC]; - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. + /* Save the return address and interrupt state. These will be + * restored by the signal trampoline after the signals have + * been delivered. */ - tcb->xcp.saved_pc = *saved_pc; - tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS]; + tcb->xcp.saved_pc = *current_pc; + tcb->xcp.saved_i = up_current_regs()[REG_FLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - *saved_pc = (uint32_t)z16_sigdeliver; - tcb->xcp.regs[REG_FLAGS] = 0; + *current_pc = (uint32_t)z16_sigdeliver; + up_current_regs()[REG_FLAGS] = 0; + + /* And make sure that the saved context in the TCB is the + * same as the interrupt return context. + */ + + z16_copystate(tcb->xcp.regs, up_current_regs()); } } + + /* 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 + { + FAR uint32_t *saved_pc = (FAR uint32_t *)&tcb->xcp.regs[REG_PC]; + + /* 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_pc = *saved_pc; + tcb->xcp.saved_i = tcb->xcp.regs[REG_FLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + *saved_pc = (uint32_t)z16_sigdeliver; + tcb->xcp.regs[REG_FLAGS] = 0; + } } diff --git a/arch/z80/src/ez80/ez80_schedulesigaction.c b/arch/z80/src/ez80/ez80_schedulesigaction.c index 214a3e49f6..e96611102e 100644 --- a/arch/z80/src/ez80/ez80_schedulesigaction.c +++ b/arch/z80/src/ez80/ez80_schedulesigaction.c @@ -43,8 +43,7 @@ * Name: ez80_sigsetup ****************************************************************************/ -static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void ez80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -99,66 +98,60 @@ static void ez80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%06" PRIx32 "\n", tcb, (uint32_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - ez80_sigsetup(tcb, sigdeliver, (chipreg_t *)IRQ_STATE()); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - SAVE_IRQCONTEXT(tcb); - } + (tcb->sigdeliver)(tcb); + tcb->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 signaling some non-running task. + /* 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. */ else { - /* Set up to vector to the trampoline with interrupts disabled. */ + /* Set up to vector to the trampoline with interrupts + * disabled. + */ - ez80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + ez80_sigsetup(tcb, (chipreg_t *)IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); } } + + /* 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 non-running task. + */ + + else + { + /* Set up to vector to the trampoline with interrupts disabled. */ + + ez80_sigsetup(tcb, tcb->xcp.regs); + } } diff --git a/arch/z80/src/z180/z180_schedulesigaction.c b/arch/z80/src/z180/z180_schedulesigaction.c index a72aa770f2..c577745c3f 100644 --- a/arch/z80/src/z180/z180_schedulesigaction.c +++ b/arch/z80/src/z180/z180_schedulesigaction.c @@ -46,8 +46,7 @@ * Name: z180_sigsetup ****************************************************************************/ -static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z180_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -102,67 +101,61 @@ static void z180_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - _info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z180_sigsetup(tcb, sigdeliver, IRQ_STATE()); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - SAVE_IRQCONTEXT(tcb); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else { - /* Set up to vector to the trampoline with interrupts disabled. */ + /* Set up to vector to the trampoline with interrupts + * disabled. + */ - z180_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + z180_sigsetup(tcb, IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); } } + + /* 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 + { + /* Set up to vector to the trampoline with interrupts disabled. */ + + z180_sigsetup(tcb, tcb->xcp.regs); + } } diff --git a/arch/z80/src/z8/z8_schedulesigaction.c b/arch/z80/src/z8/z8_schedulesigaction.c index 8731db67d2..cddf5c6af3 100644 --- a/arch/z80/src/z8/z8_schedulesigaction.c +++ b/arch/z80/src/z8/z8_schedulesigaction.c @@ -43,8 +43,7 @@ * Name: z8_sigsetup ****************************************************************************/ -static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z8_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -99,60 +98,33 @@ static void z8_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - sinfo("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z8_sigsetup(tcb, sigdeliver, IRQ_STATE()); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - SAVE_IRQCONTEXT(tcb); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else @@ -161,7 +133,28 @@ void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) * disabled. */ - z8_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + z8_sigsetup(tcb, IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); } } + + /* 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 + { + /* Set up to vector to the trampoline with interrupts + * disabled. + */ + + z8_sigsetup(tcb, tcb->xcp.regs); + } } diff --git a/arch/z80/src/z80/z80_schedulesigaction.c b/arch/z80/src/z80/z80_schedulesigaction.c index 2a3a016859..f03690e784 100644 --- a/arch/z80/src/z80/z80_schedulesigaction.c +++ b/arch/z80/src/z80/z80_schedulesigaction.c @@ -44,8 +44,7 @@ * Name: z80_sigsetup ****************************************************************************/ -static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, - FAR chipreg_t *regs) +static void z80_sigsetup(FAR struct tcb_s *tcb, FAR chipreg_t *regs) { /* Save the return address and interrupt state. These will be restored by * the signal trampoline after the signals have been delivered. @@ -100,67 +99,61 @@ static void z80_sigsetup(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) +void up_schedule_sigaction(FAR struct tcb_s *tcb) { - _info("tcb=%p sigdeliver=0x%04x\n", tcb, (uint16_t)sigdeliver); + sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, + this_task(), up_current_regs()); - /* Refuse to handle nested signal actions */ + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ - if (tcb->sigdeliver == NULL) + if (tcb == this_task()) { - tcb->sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. */ - if (tcb == this_task()) + if (!IN_INTERRUPT()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!IN_INTERRUPT()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->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. - */ - - else - { - /* Set up to vector to the trampoline with interrupts - * disabled. - */ - - z80_sigsetup(tcb, sigdeliver, IRQ_STATE()); - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - SAVE_IRQCONTEXT(tcb); - } + (tcb->sigdeliver)(tcb); + tcb->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. + /* 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. */ else { - /* Set up to vector to the trampoline with interrupts disabled. */ + /* Set up to vector to the trampoline with interrupts + * disabled. + */ - z80_sigsetup(tcb, sigdeliver, tcb->xcp.regs); + z80_sigsetup(tcb, IRQ_STATE()); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + SAVE_IRQCONTEXT(tcb); } } + + /* 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 + { + /* Set up to vector to the trampoline with interrupts disabled. */ + + z80_sigsetup(tcb, tcb->xcp.regs); + } } diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 559e85264d..f149d8a36d 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -541,7 +541,7 @@ int up_backtrace(FAR struct tcb_s *tcb, * ****************************************************************************/ -void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver); +void up_schedule_sigaction(FAR struct tcb_s *tcb); /**************************************************************************** * Name: up_task_start diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index 7e238b8e95..8f94d93b78 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -115,7 +115,12 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, siginfo_t *info) * up_schedule_sigaction() */ - up_schedule_sigaction(stcb, nxsig_deliver); + if (!stcb->sigdeliver) + { + stcb->sigdeliver = nxsig_deliver; + up_schedule_sigaction(stcb); + } + leave_critical_section(flags); } }