diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-01-26 22:33:43 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-01-26 22:33:43 -0500 |
commit | 71e834f563799e09c6bd7d6638993b464fac26f5 (patch) | |
tree | 3a35643ddc54e7217ec000eb415cc79a65cdcac1 /arch/powerpc/kernel/signal_32.c | |
parent | ff0fc1467f8189c8e2340b91161c97138a75e484 (diff) | |
parent | 3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff) |
Merge branch 'master'
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 76 |
1 files changed, 20 insertions, 56 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 177bba78fb0b..3747ab0dac3f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs); | |||
252 | /* | 252 | /* |
253 | * Atomically swap in the new signal mask, and wait for a signal. | 253 | * Atomically swap in the new signal mask, and wait for a signal. |
254 | */ | 254 | */ |
255 | long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, | 255 | long sys_sigsuspend(old_sigset_t mask) |
256 | struct pt_regs *regs) | ||
257 | { | 256 | { |
258 | sigset_t saveset; | 257 | sigset_t saveset; |
259 | 258 | ||
@@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, | |||
264 | recalc_sigpending(); | 263 | recalc_sigpending(); |
265 | spin_unlock_irq(¤t->sighand->siglock); | 264 | spin_unlock_irq(¤t->sighand->siglock); |
266 | 265 | ||
267 | regs->result = -EINTR; | 266 | current->state = TASK_INTERRUPTIBLE; |
268 | regs->gpr[3] = EINTR; | 267 | schedule(); |
269 | regs->ccr |= 0x10000000; | 268 | set_thread_flag(TIF_RESTORE_SIGMASK); |
270 | while (1) { | 269 | return -ERESTARTNOHAND; |
271 | current->state = TASK_INTERRUPTIBLE; | ||
272 | schedule(); | ||
273 | if (do_signal(&saveset, regs)) { | ||
274 | set_thread_flag(TIF_RESTOREALL); | ||
275 | return 0; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | long sys_rt_sigsuspend( | ||
281 | #ifdef CONFIG_PPC64 | ||
282 | compat_sigset_t __user *unewset, | ||
283 | #else | ||
284 | sigset_t __user *unewset, | ||
285 | #endif | ||
286 | size_t sigsetsize, int p3, int p4, | ||
287 | int p6, int p7, struct pt_regs *regs) | ||
288 | { | ||
289 | sigset_t saveset, newset; | ||
290 | |||
291 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
292 | if (sigsetsize != sizeof(sigset_t)) | ||
293 | return -EINVAL; | ||
294 | |||
295 | if (get_sigset_t(&newset, unewset)) | ||
296 | return -EFAULT; | ||
297 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
298 | |||
299 | spin_lock_irq(¤t->sighand->siglock); | ||
300 | saveset = current->blocked; | ||
301 | current->blocked = newset; | ||
302 | recalc_sigpending(); | ||
303 | spin_unlock_irq(¤t->sighand->siglock); | ||
304 | |||
305 | regs->result = -EINTR; | ||
306 | regs->gpr[3] = EINTR; | ||
307 | regs->ccr |= 0x10000000; | ||
308 | while (1) { | ||
309 | current->state = TASK_INTERRUPTIBLE; | ||
310 | schedule(); | ||
311 | if (do_signal(&saveset, regs)) { | ||
312 | set_thread_flag(TIF_RESTOREALL); | ||
313 | return 0; | ||
314 | } | ||
315 | } | ||
316 | } | 270 | } |
317 | 271 | ||
318 | #ifdef CONFIG_PPC32 | 272 | #ifdef CONFIG_PPC32 |
@@ -1174,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1174 | { | 1128 | { |
1175 | siginfo_t info; | 1129 | siginfo_t info; |
1176 | struct k_sigaction ka; | 1130 | struct k_sigaction ka; |
1177 | unsigned int frame, newsp; | 1131 | unsigned int newsp; |
1178 | int signr, ret; | 1132 | int signr, ret; |
1179 | 1133 | ||
1180 | #ifdef CONFIG_PPC32 | 1134 | #ifdef CONFIG_PPC32 |
@@ -1185,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
1185 | } | 1139 | } |
1186 | #endif | 1140 | #endif |
1187 | 1141 | ||
1188 | if (!oldset) | 1142 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
1143 | oldset = ¤t->saved_sigmask; | ||
1144 | else if (!oldset) | ||
1189 | oldset = ¤t->blocked; | 1145 | oldset = ¤t->blocked; |
1190 | 1146 | ||
1191 | newsp = frame = 0; | ||
1192 | |||
1193 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 1147 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
1194 | #ifdef CONFIG_PPC32 | 1148 | #ifdef CONFIG_PPC32 |
1195 | no_signal: | 1149 | no_signal: |
@@ -1219,8 +1173,14 @@ no_signal: | |||
1219 | } | 1173 | } |
1220 | } | 1174 | } |
1221 | 1175 | ||
1222 | if (signr == 0) | 1176 | if (signr == 0) { |
1177 | /* No signal to deliver -- put the saved sigmask back */ | ||
1178 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
1179 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1180 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
1181 | } | ||
1223 | return 0; /* no signals delivered */ | 1182 | return 0; /* no signals delivered */ |
1183 | } | ||
1224 | 1184 | ||
1225 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | 1185 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size |
1226 | && !on_sig_stack(regs->gpr[1])) | 1186 | && !on_sig_stack(regs->gpr[1])) |
@@ -1253,6 +1213,10 @@ no_signal: | |||
1253 | sigaddset(¤t->blocked, signr); | 1213 | sigaddset(¤t->blocked, signr); |
1254 | recalc_sigpending(); | 1214 | recalc_sigpending(); |
1255 | spin_unlock_irq(¤t->sighand->siglock); | 1215 | spin_unlock_irq(¤t->sighand->siglock); |
1216 | /* A signal was successfully delivered; the saved sigmask is in | ||
1217 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
1218 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
1219 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1256 | } | 1220 | } |
1257 | 1221 | ||
1258 | return ret; | 1222 | return ret; |