Skip to content

Commit 0f243bd

Browse files
hujun260jerpelea
authored andcommitted
arch: fix the issue of asynchronous signal processing
in SMP, signal processing cannot be nested, we use xcp.sigdeliver to identify whether there is currently a signal being processed, but this state does not match the actual situation One possible scenario is that signal processing has already been completed, but an interrupt occurs, resulting in xcp.sigdeliver not being correctly set to NULL, At this point, a new signal arrives, which can only be placed in the queue and cannot be processed immediately Our solution is that signal processing and signal complete status are set in the same critical section, which can ensure status synchronization Signed-off-by: hujun5 <[email protected]>
1 parent 35dee8f commit 0f243bd

File tree

10 files changed

+125
-29
lines changed

10 files changed

+125
-29
lines changed

arch/arm/src/armv6-m/arm_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ void arm_sigdeliver(void)
7171
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7272
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7373

74+
retry:
7475
#ifdef CONFIG_SMP
7576
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7677
* 'irqcount' in order to force us into a critical section. Save the
7778
* pre-incremented irqcount.
7879
*/
7980

80-
saved_irqcount = rtcb->irqcount - 1;
81-
DEBUGASSERT(saved_irqcount >= 0);
81+
saved_irqcount = rtcb->irqcount;
82+
DEBUGASSERT(saved_irqcount >= 1);
8283

8384
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8485
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -129,6 +130,12 @@ void arm_sigdeliver(void)
129130
up_irq_save();
130131
#endif
131132

133+
if (!sq_empty(&rtcb->sigpendactionq) &&
134+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
135+
{
136+
goto retry;
137+
}
138+
132139
/* Modify the saved return state with the actual saved values in the
133140
* TCB. This depends on the fact that nested signal handling is
134141
* not supported. Therefore, these values will persist throughout the
@@ -146,5 +153,8 @@ void arm_sigdeliver(void)
146153
*/
147154

148155
board_autoled_off(LED_SIGNAL);
156+
#ifdef CONFIG_SMP
157+
rtcb->irqcount--;
158+
#endif
149159
arm_fullcontextrestore(regs);
150160
}

arch/arm/src/armv7-a/arm_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ void arm_sigdeliver(void)
7171
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7272
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7373

74+
retry:
7475
#ifdef CONFIG_SMP
7576
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7677
* 'irqcount' in order to force us into a critical section. Save the
7778
* pre-incremented irqcount.
7879
*/
7980

80-
saved_irqcount = rtcb->irqcount - 1;
81-
DEBUGASSERT(saved_irqcount >= 0);
81+
saved_irqcount = rtcb->irqcount;
82+
DEBUGASSERT(saved_irqcount >= 1);
8283

8384
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8485
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -129,6 +130,12 @@ void arm_sigdeliver(void)
129130
up_irq_save();
130131
#endif
131132

133+
if (!sq_empty(&rtcb->sigpendactionq) &&
134+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
135+
{
136+
goto retry;
137+
}
138+
132139
/* Modify the saved return state with the actual saved values in the
133140
* TCB. This depends on the fact that nested signal handling is
134141
* not supported. Therefore, these values will persist throughout the
@@ -144,5 +151,8 @@ void arm_sigdeliver(void)
144151
/* Then restore the correct state for this thread of execution. */
145152

146153
board_autoled_off(LED_SIGNAL);
154+
#ifdef CONFIG_SMP
155+
rtcb->irqcount--;
156+
#endif
147157
arm_fullcontextrestore(regs);
148158
}

arch/arm/src/armv7-m/arm_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ void arm_sigdeliver(void)
7171
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7272
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7373

74+
retry:
7475
#ifdef CONFIG_SMP
7576
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7677
* 'irqcount' in order to force us into a critical section. Save the
7778
* pre-incremented irqcount.
7879
*/
7980

80-
saved_irqcount = rtcb->irqcount - 1;
81-
DEBUGASSERT(saved_irqcount >= 0);
81+
saved_irqcount = rtcb->irqcount;
82+
DEBUGASSERT(saved_irqcount >= 1);
8283

8384
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8485
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -133,6 +134,12 @@ void arm_sigdeliver(void)
133134
up_irq_save();
134135
#endif
135136

137+
if (!sq_empty(&rtcb->sigpendactionq) &&
138+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
139+
{
140+
goto retry;
141+
}
142+
136143
/* Modify the saved return state with the actual saved values in the
137144
* TCB. This depends on the fact that nested signal handling is
138145
* not supported. Therefore, these values will persist throughout the
@@ -150,5 +157,8 @@ void arm_sigdeliver(void)
150157
*/
151158

152159
board_autoled_off(LED_SIGNAL);
160+
#ifdef CONFIG_SMP
161+
rtcb->irqcount--;
162+
#endif
153163
arm_fullcontextrestore(regs);
154164
}

arch/arm/src/armv7-r/arm_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ void arm_sigdeliver(void)
7171
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7272
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7373

74+
retry:
7475
#ifdef CONFIG_SMP
7576
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7677
* 'irqcount' in order to force us into a critical section. Save the
7778
* pre-incremented irqcount.
7879
*/
7980

80-
saved_irqcount = rtcb->irqcount - 1;
81-
DEBUGASSERT(saved_irqcount >= 0);
81+
saved_irqcount = rtcb->irqcount;
82+
DEBUGASSERT(saved_irqcount >= 1);
8283

8384
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8485
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -126,6 +127,12 @@ void arm_sigdeliver(void)
126127
up_irq_save();
127128
#endif
128129

130+
if (!sq_empty(&rtcb->sigpendactionq) &&
131+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
132+
{
133+
goto retry;
134+
}
135+
129136
/* Modify the saved return state with the actual saved values in the
130137
* TCB. This depends on the fact that nested signal handling is
131138
* not supported. Therefore, these values will persist throughout the
@@ -141,5 +148,8 @@ void arm_sigdeliver(void)
141148
/* Then restore the correct state for this thread of execution. */
142149

143150
board_autoled_off(LED_SIGNAL);
151+
#ifdef CONFIG_SMP
152+
rtcb->irqcount--;
153+
#endif
144154
arm_fullcontextrestore(regs);
145155
}

arch/arm/src/armv8-m/arm_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ void arm_sigdeliver(void)
7171
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7272
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7373

74+
retry:
7475
#ifdef CONFIG_SMP
7576
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7677
* 'irqcount' in order to force us into a critical section. Save the
7778
* pre-incremented irqcount.
7879
*/
7980

80-
saved_irqcount = rtcb->irqcount - 1;
81-
DEBUGASSERT(saved_irqcount >= 0);
81+
saved_irqcount = rtcb->irqcount;
82+
DEBUGASSERT(saved_irqcount >= 1);
8283

8384
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8485
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -133,6 +134,12 @@ void arm_sigdeliver(void)
133134
up_irq_save();
134135
#endif
135136

137+
if (!sq_empty(&rtcb->sigpendactionq) &&
138+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
139+
{
140+
goto retry;
141+
}
142+
136143
/* Modify the saved return state with the actual saved values in the
137144
* TCB. This depends on the fact that nested signal handling is
138145
* not supported. Therefore, these values will persist throughout the
@@ -150,5 +157,8 @@ void arm_sigdeliver(void)
150157
*/
151158

152159
board_autoled_off(LED_SIGNAL);
160+
#ifdef CONFIG_SMP
161+
rtcb->irqcount--;
162+
#endif
153163
arm_fullcontextrestore(regs);
154164
}

arch/arm64/src/common/arm64_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ void arm64_sigdeliver(void)
7777
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7878
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7979

80+
retry:
8081
#ifdef CONFIG_SMP
8182
/* In the SMP case, up_schedule_sigaction(0) will have incremented
8283
* 'irqcount' in order to force us into a critical section. Save the
8384
* pre-incremented irqcount.
8485
*/
8586

86-
saved_irqcount = rtcb->irqcount - 1;
87-
DEBUGASSERT(saved_irqcount >= 0);
87+
saved_irqcount = rtcb->irqcount;
88+
DEBUGASSERT(saved_irqcount >= 1);
8889

8990
/* Now we need call leave_critical_section() repeatedly to get the irqcount
9091
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -135,6 +136,12 @@ void arm64_sigdeliver(void)
135136
up_irq_save();
136137
#endif
137138

139+
if (!sq_empty(&rtcb->sigpendactionq) &&
140+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
141+
{
142+
goto retry;
143+
}
144+
138145
/* Modify the saved return state with the actual saved values in the
139146
* TCB. This depends on the fact that nested signal handling is
140147
* not supported. Therefore, these values will persist throughout the
@@ -155,5 +162,8 @@ void arm64_sigdeliver(void)
155162

156163
/* Then restore the correct state for this thread of execution. */
157164

165+
#ifdef CONFIG_SMP
166+
rtcb->irqcount--;
167+
#endif
158168
arm64_fullcontextrestore(rtcb->xcp.regs);
159169
}

arch/risc-v/src/common/riscv_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,15 @@ void riscv_sigdeliver(void)
7272
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
7373
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
7474

75+
retry:
7576
#ifdef CONFIG_SMP
7677
/* In the SMP case, up_schedule_sigaction(0) will have incremented
7778
* 'irqcount' in order to force us into a critical section. Save the
7879
* pre-incremented irqcount.
7980
*/
8081

81-
saved_irqcount = rtcb->irqcount - 1;
82-
DEBUGASSERT(saved_irqcount >= 0);
82+
saved_irqcount = rtcb->irqcount;
83+
DEBUGASSERT(saved_irqcount >= 1);
8384

8485
/* Now we need call leave_critical_section() repeatedly to get the irqcount
8586
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -128,6 +129,12 @@ void riscv_sigdeliver(void)
128129
up_irq_save();
129130
#endif
130131

132+
if (!sq_empty(&rtcb->sigpendactionq) &&
133+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
134+
{
135+
goto retry;
136+
}
137+
131138
/* Modify the saved return state with the actual saved values in the
132139
* TCB. This depends on the fact that nested signal handling is
133140
* not supported. Therefore, these values will persist throughout the
@@ -145,5 +152,8 @@ void riscv_sigdeliver(void)
145152
*/
146153

147154
board_autoled_off(LED_SIGNAL);
155+
#ifdef CONFIG_SMP
156+
rtcb->irqcount--;
157+
#endif
148158
riscv_fullcontextrestore(regs);
149159
}

arch/sim/src/sim/sim_sigdeliver.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@
5252
void sim_sigdeliver(void)
5353
{
5454
struct tcb_s *rtcb = current_task(this_cpu());
55+
#ifdef CONFIG_SMP
56+
/* In the SMP case, we must terminate the critical section while the signal
57+
* handler executes, but we also need to restore the irqcount when the
58+
* we resume the main thread of the task.
59+
*/
5560

61+
int16_t saved_irqcount;
62+
irqstate_t flags;
63+
#endif
5664
if (NULL == (rtcb->xcp.sigdeliver))
5765
{
5866
return;
@@ -63,16 +71,7 @@ void sim_sigdeliver(void)
6371
*/
6472

6573
#ifdef CONFIG_SMP
66-
irqstate_t flags = enter_critical_section();
67-
#endif
68-
69-
#ifdef CONFIG_SMP
70-
/* In the SMP case, we must terminate the critical section while the signal
71-
* handler executes, but we also need to restore the irqcount when the
72-
* we resume the main thread of the task.
73-
*/
74-
75-
int16_t saved_irqcount;
74+
flags = enter_critical_section();
7675
#endif
7776

7877
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
@@ -81,14 +80,15 @@ void sim_sigdeliver(void)
8180

8281
/* NOTE: we do not save the return state for sim */
8382

83+
retry:
8484
#ifdef CONFIG_SMP
8585
/* In the SMP case, up_schedule_sigaction(0) will have incremented
8686
* 'irqcount' in order to force us into a critical section. Save the
8787
* pre-incremented irqcount.
8888
*/
8989

9090
saved_irqcount = rtcb->irqcount;
91-
DEBUGASSERT(saved_irqcount >= 0);
91+
DEBUGASSERT(saved_irqcount >= 1);
9292

9393
/* Now we need call leave_critical_section() repeatedly to get the irqcount
9494
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -127,6 +127,12 @@ void sim_sigdeliver(void)
127127
}
128128
#endif
129129

130+
if (!sq_empty(&rtcb->sigpendactionq) &&
131+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
132+
{
133+
goto retry;
134+
}
135+
130136
/* Allows next handler to be scheduled */
131137

132138
rtcb->xcp.sigdeliver = NULL;

arch/sparc/src/sparc_v8/sparc_v8_sigdeliver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,15 @@ void sparc_sigdeliver(void)
8484

8585
sparc_copystate(regs, rtcb->xcp.regs);
8686

87+
retry:
8788
#ifdef CONFIG_SMP
8889
/* In the SMP case, up_schedule_sigaction(0) will have incremented
8990
* 'irqcount' in order to force us into a critical section. Save the
9091
* pre-incremented irqcount.
9192
*/
9293

93-
saved_irqcount = rtcb->irqcount - 1;
94-
DEBUGASSERT(saved_irqcount >= 0);
94+
saved_irqcount = rtcb->irqcount;
95+
DEBUGASSERT(saved_irqcount >= 1);
9596

9697
/* Now we need call leave_critical_section() repeatedly to get the irqcount
9798
* to zero, freeing all global spinlocks that enforce the critical section.
@@ -144,6 +145,12 @@ void sparc_sigdeliver(void)
144145

145146
set_errno(saved_errno);
146147

148+
if (!sq_empty(&rtcb->sigpendactionq) &&
149+
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
150+
{
151+
goto retry;
152+
}
153+
147154
/* Modify the saved return state with the actual saved values in the
148155
* TCB. This depends on the fact that nested signal handling is
149156
* not supported. Therefore, these values will persist throughout the
@@ -195,5 +202,8 @@ void sparc_sigdeliver(void)
195202
*/
196203

197204
board_autoled_off(LED_SIGNAL);
205+
#ifdef CONFIG_SMP
206+
rtcb->irqcount--;
207+
#endif
198208
sparc_fullcontextrestore(regs);
199209
}

0 commit comments

Comments
 (0)