diff --git a/arch/arm/src/armv6-m/arm_sigdeliver.c b/arch/arm/src/armv6-m/arm_sigdeliver.c index 164318865b2..5150c86f2bf 100644 --- a/arch/arm/src/armv6-m/arm_sigdeliver.c +++ b/arch/arm/src/armv6-m/arm_sigdeliver.c @@ -71,14 +71,15 @@ void arm_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -129,6 +130,12 @@ void arm_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -146,5 +153,8 @@ void arm_sigdeliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm_fullcontextrestore(regs); } diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c index 856f216c0ce..6dfd9044d16 100644 --- a/arch/arm/src/armv7-a/arm_sigdeliver.c +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -71,14 +71,15 @@ void arm_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -129,6 +130,12 @@ void arm_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -144,5 +151,8 @@ void arm_sigdeliver(void) /* Then restore the correct state for this thread of execution. */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm_fullcontextrestore(regs); } diff --git a/arch/arm/src/armv7-m/arm_sigdeliver.c b/arch/arm/src/armv7-m/arm_sigdeliver.c index 94098e03674..b7e80fda55c 100644 --- a/arch/arm/src/armv7-m/arm_sigdeliver.c +++ b/arch/arm/src/armv7-m/arm_sigdeliver.c @@ -71,14 +71,15 @@ void arm_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -133,6 +134,12 @@ void arm_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -150,5 +157,8 @@ void arm_sigdeliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm_fullcontextrestore(regs); } diff --git a/arch/arm/src/armv7-r/arm_sigdeliver.c b/arch/arm/src/armv7-r/arm_sigdeliver.c index be1553b0f61..a1e409faf11 100644 --- a/arch/arm/src/armv7-r/arm_sigdeliver.c +++ b/arch/arm/src/armv7-r/arm_sigdeliver.c @@ -71,14 +71,15 @@ void arm_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -126,6 +127,12 @@ void arm_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -141,5 +148,8 @@ void arm_sigdeliver(void) /* Then restore the correct state for this thread of execution. */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm_fullcontextrestore(regs); } diff --git a/arch/arm/src/armv8-m/arm_sigdeliver.c b/arch/arm/src/armv8-m/arm_sigdeliver.c index 717a7009f6d..1ef5c33d1be 100644 --- a/arch/arm/src/armv8-m/arm_sigdeliver.c +++ b/arch/arm/src/armv8-m/arm_sigdeliver.c @@ -71,14 +71,15 @@ void arm_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -133,6 +134,12 @@ void arm_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -150,5 +157,8 @@ void arm_sigdeliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm_fullcontextrestore(regs); } diff --git a/arch/arm64/src/common/arm64_sigdeliver.c b/arch/arm64/src/common/arm64_sigdeliver.c index 1937ecb0571..36de66243b7 100644 --- a/arch/arm64/src/common/arm64_sigdeliver.c +++ b/arch/arm64/src/common/arm64_sigdeliver.c @@ -77,14 +77,15 @@ void arm64_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -135,6 +136,12 @@ void arm64_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -155,5 +162,8 @@ void arm64_sigdeliver(void) /* Then restore the correct state for this thread of execution. */ +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif arm64_fullcontextrestore(rtcb->xcp.regs); } diff --git a/arch/risc-v/src/common/riscv_sigdeliver.c b/arch/risc-v/src/common/riscv_sigdeliver.c index ded797a405c..c5c61cd9cab 100644 --- a/arch/risc-v/src/common/riscv_sigdeliver.c +++ b/arch/risc-v/src/common/riscv_sigdeliver.c @@ -72,14 +72,15 @@ void riscv_sigdeliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -128,6 +129,12 @@ void riscv_sigdeliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -145,5 +152,8 @@ void riscv_sigdeliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif riscv_fullcontextrestore(regs); } diff --git a/arch/sim/src/sim/sim_sigdeliver.c b/arch/sim/src/sim/sim_sigdeliver.c index fb3f0d9404f..eca8c3bf910 100644 --- a/arch/sim/src/sim/sim_sigdeliver.c +++ b/arch/sim/src/sim/sim_sigdeliver.c @@ -52,7 +52,15 @@ void sim_sigdeliver(void) { struct tcb_s *rtcb = current_task(this_cpu()); +#ifdef CONFIG_SMP + /* In the SMP case, we must terminate the critical section while the signal + * handler executes, but we also need to restore the irqcount when the + * we resume the main thread of the task. + */ + int16_t saved_irqcount; + irqstate_t flags; +#endif if (NULL == (rtcb->xcp.sigdeliver)) { return; @@ -63,16 +71,7 @@ void sim_sigdeliver(void) */ #ifdef CONFIG_SMP - irqstate_t flags = enter_critical_section(); -#endif - -#ifdef CONFIG_SMP - /* In the SMP case, we must terminate the critical section while the signal - * handler executes, but we also need to restore the irqcount when the - * we resume the main thread of the task. - */ - - int16_t saved_irqcount; + flags = enter_critical_section(); #endif sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", @@ -81,6 +80,7 @@ void sim_sigdeliver(void) /* NOTE: we do not save the return state for sim */ +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the @@ -88,7 +88,7 @@ void sim_sigdeliver(void) */ saved_irqcount = rtcb->irqcount; - DEBUGASSERT(saved_irqcount >= 0); + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -127,6 +127,12 @@ void sim_sigdeliver(void) } #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Allows next handler to be scheduled */ rtcb->xcp.sigdeliver = NULL; diff --git a/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c b/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c index aadebc2f103..411a7b05f54 100644 --- a/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c +++ b/arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c @@ -84,14 +84,15 @@ void sparc_sigdeliver(void) sparc_copystate(regs, rtcb->xcp.regs); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need call leave_critical_section() repeatedly to get the irqcount * to zero, freeing all global spinlocks that enforce the critical section. @@ -144,6 +145,12 @@ void sparc_sigdeliver(void) set_errno(saved_errno); + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -195,5 +202,8 @@ void sparc_sigdeliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif sparc_fullcontextrestore(regs); } diff --git a/arch/xtensa/src/common/xtensa_sigdeliver.c b/arch/xtensa/src/common/xtensa_sigdeliver.c index a18e3a281f9..9443ad4afa1 100644 --- a/arch/xtensa/src/common/xtensa_sigdeliver.c +++ b/arch/xtensa/src/common/xtensa_sigdeliver.c @@ -71,14 +71,15 @@ void xtensa_sig_deliver(void) rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); +retry: #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the * pre-incremented irqcount. */ - saved_irqcount = rtcb->irqcount - 1; - DEBUGASSERT(saved_irqcount >= 0); + saved_irqcount = rtcb->irqcount; + DEBUGASSERT(saved_irqcount >= 1); /* Now we need to call leave_critical_section() repeatedly to get the * irqcount to zero, freeing all global spinlocks that enforce the critical @@ -127,6 +128,12 @@ void xtensa_sig_deliver(void) up_irq_save(); #endif + if (!sq_empty(&rtcb->sigpendactionq) && + (rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0) + { + goto retry; + } + /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is * not supported. Therefore, these values will persist throughout the @@ -143,5 +150,8 @@ void xtensa_sig_deliver(void) */ board_autoled_off(LED_SIGNAL); +#ifdef CONFIG_SMP + rtcb->irqcount--; +#endif xtensa_context_restore(regs); }