|
72 | 72 | * |
73 | 73 | ****************************************************************************/ |
74 | 74 |
|
75 | | -#ifndef CONFIG_SMP |
76 | 75 | void up_schedule_sigaction(struct tcb_s *tcb) |
77 | 76 | { |
78 | 77 | sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, |
79 | | - this_task(), up_current_regs()); |
80 | | - |
81 | | - /* First, handle some special cases when the signal is being delivered |
82 | | - * to the currently executing task. |
83 | | - */ |
84 | | - |
85 | | - if (tcb == this_task()) |
86 | | - { |
87 | | - /* CASE 1: We are not in an interrupt handler and a task is |
88 | | - * signalling itself for some reason. |
89 | | - */ |
90 | | - |
91 | | - if (!up_current_regs()) |
92 | | - { |
93 | | - /* In this case just deliver the signal with a function call |
94 | | - * now. |
95 | | - */ |
96 | | - |
97 | | - (tcb->sigdeliver)(tcb); |
98 | | - tcb->sigdeliver = NULL; |
99 | | - } |
100 | | - |
101 | | - /* CASE 2: We are in an interrupt handler AND the interrupted task |
102 | | - * is the same as the one that must receive the signal, then we |
103 | | - * will have to modify the return state as well as the state in the |
104 | | - * TCB. |
105 | | - * |
106 | | - * Hmmm... there looks like a latent bug here: The following logic |
107 | | - * would fail in the strange case where we are in an interrupt |
108 | | - * handler, the thread is signalling itself, but a context switch |
109 | | - * to another task has occurred so that current_regs does not |
110 | | - * refer to the thread of this_task()! |
111 | | - */ |
112 | | - |
113 | | - else |
114 | | - { |
115 | | - /* Save the return lr and cpsr and one scratch register. These |
116 | | - * will be restored by the signal trampoline after the signals |
117 | | - * have been delivered. |
118 | | - */ |
119 | | - |
120 | | - tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; |
121 | | - tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; |
122 | | - tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; |
123 | | - |
124 | | - /* Then set up to vector to the trampoline with interrupts |
125 | | - * disabled |
126 | | - */ |
127 | | - |
128 | | - up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; |
129 | | - up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; |
130 | | - up_current_regs()[REG_RFLAGS] = 0; |
131 | | - |
132 | | -#ifdef CONFIG_ARCH_KERNEL_STACK |
133 | | - /* Update segments to kernel segments */ |
134 | | - |
135 | | - up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS]; |
136 | | - up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS]; |
137 | | - up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS]; |
138 | | - |
139 | | - /* Update RSP to kernel stack */ |
140 | | - |
141 | | - up_current_regs()[REG_RSP] = (uint64_t)x86_64_get_ktopstk(); |
142 | | -#endif |
143 | | - } |
144 | | - } |
145 | | - |
146 | | - /* Otherwise, we are (1) signaling a task is not running |
147 | | - * from an interrupt handler or (2) we are not in an |
148 | | - * interrupt handler and the running task is signalling |
149 | | - * some non-running task. |
150 | | - */ |
151 | | - |
152 | | - else |
153 | | - { |
154 | | - /* Save the return lr and cpsr and one scratch register |
155 | | - * These will be restored by the signal trampoline after |
156 | | - * the signals have been delivered. |
157 | | - */ |
158 | | - |
159 | | - tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; |
160 | | - tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; |
161 | | - tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; |
162 | | - |
163 | | - /* Then set up to vector to the trampoline with interrupts |
164 | | - * disabled |
165 | | - */ |
166 | | - |
167 | | - tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; |
168 | | - tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8; |
169 | | - tcb->xcp.regs[REG_RFLAGS] = 0; |
170 | | - } |
171 | | -} |
172 | | -#else /* !CONFIG_SMP */ |
173 | | -void up_schedule_sigaction(struct tcb_s *tcb) |
174 | | -{ |
175 | | - int cpu; |
176 | | - int me; |
177 | | - |
178 | | - sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb, |
179 | | - this_task(), up_current_regs()); |
| 78 | + this_task(), this_task()->xcp.regs); |
180 | 79 |
|
181 | 80 | /* First, handle some special cases when the signal is being delivered |
182 | 81 | * to task that is currently executing on any CPU. |
183 | 82 | */ |
184 | 83 |
|
185 | | - if (tcb->task_state == TSTATE_TASK_RUNNING) |
| 84 | + if (tcb == this_task() && !up_interrupt_context()) |
186 | 85 | { |
187 | | - me = this_cpu(); |
188 | | - cpu = tcb->cpu; |
189 | | - |
190 | | - /* CASE 1: We are not in an interrupt handler and a task is |
191 | | - * signaling itself for some reason. |
192 | | - */ |
193 | | - |
194 | | - if (cpu == me && !up_current_regs()) |
195 | | - { |
196 | | - /* In this case just deliver the signal now. |
197 | | - * REVISIT: Signal handler will run in a critical section! |
198 | | - */ |
199 | | - |
200 | | - (tcb->sigdeliver)(tcb); |
201 | | - tcb->sigdeliver = NULL; |
202 | | - } |
203 | | - |
204 | | - /* CASE 2: The task that needs to receive the signal is running. |
205 | | - * This could happen if the task is running on another CPU OR if |
206 | | - * we are in an interrupt handler and the task is running on this |
207 | | - * CPU. In the former case, we will have to PAUSE the other CPU |
208 | | - * first. But in either case, we will have to modify the return |
209 | | - * state as well as the state in the TCB. |
210 | | - */ |
211 | | - |
212 | | - else |
213 | | - { |
214 | | - /* tcb is running on the same CPU */ |
215 | | - |
216 | | - /* Save the return lr and cpsr and one scratch register. |
217 | | - * These will be restored by the signal trampoline after |
218 | | - * the signals have been delivered. |
219 | | - */ |
220 | | - |
221 | | - tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; |
222 | | - tcb->xcp.saved_rsp = up_current_regs()[REG_RSP]; |
223 | | - tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; |
224 | | - |
225 | | - /* Then set up to vector to the trampoline with interrupts |
226 | | - * disabled |
227 | | - */ |
228 | | - |
229 | | - up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; |
230 | | - up_current_regs()[REG_RSP] = up_current_regs()[REG_RSP] - 8; |
231 | | - up_current_regs()[REG_RFLAGS] = 0; |
232 | | - |
233 | | -#ifdef CONFIG_ARCH_KERNEL_STACK |
234 | | - /* Update segments to kernel segments */ |
235 | | - |
236 | | - up_current_regs()[REG_SS] = tcb->xcp.regs[REG_SS]; |
237 | | - up_current_regs()[REG_CS] = tcb->xcp.regs[REG_CS]; |
238 | | - up_current_regs()[REG_DS] = tcb->xcp.regs[REG_DS]; |
239 | | - |
240 | | - /* Update RSP to kernel stack */ |
241 | | - |
242 | | - up_current_regs()[REG_RSP] = |
243 | | - (uint64_t)x86_64_get_ktopstk(); |
244 | | -#endif |
245 | | - /* Mark that full context switch is necessary when we |
246 | | - * return from interrupt handler. |
247 | | - * In that case RIP, RSP and RFLAGS are changed, but |
248 | | - * register area pointer remains the same, so we need an |
249 | | - * additional variable to signal the need for full context switch |
250 | | - */ |
251 | | - |
252 | | - tcb->xcp.regs[REG_AUX] = REG_AUX_FULLCONTEXT; |
253 | | - } |
| 86 | + (tcb->sigdeliver)(tcb); |
| 87 | + tcb->sigdeliver = NULL; |
254 | 88 | } |
255 | 89 |
|
256 | 90 | /* Otherwise, we are (1) signaling a task is not running from an |
@@ -278,4 +112,3 @@ void up_schedule_sigaction(struct tcb_s *tcb) |
278 | 112 | tcb->xcp.regs[REG_RFLAGS] = 0; |
279 | 113 | } |
280 | 114 | } |
281 | | -#endif /* CONFIG_SMP */ |
0 commit comments