diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-09-24 01:20:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-24 16:54:19 -0400 |
commit | a7f8388e2c167c73b6abb3b749157aafd08f90ee (patch) | |
tree | 361a61b35ee04b0684eb984d415ef121f1e751f8 /arch | |
parent | a850ea30374ebed32a0724742601861853fde869 (diff) |
m32r: fix rt_sigsuspend()
do_signal() should know about saved_mask for it to work...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/m32r/include/asm/signal.h | 1 | ||||
-rw-r--r-- | arch/m32r/include/asm/unistd.h | 1 | ||||
-rw-r--r-- | arch/m32r/kernel/entry.S | 3 | ||||
-rw-r--r-- | arch/m32r/kernel/signal.c | 48 |
4 files changed, 14 insertions, 39 deletions
diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index 9c1acb2b1a92..b2eeb0de1c8d 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h | |||
@@ -157,7 +157,6 @@ typedef struct sigaltstack { | |||
157 | #undef __HAVE_ARCH_SIG_BITOPS | 157 | #undef __HAVE_ARCH_SIG_BITOPS |
158 | 158 | ||
159 | struct pt_regs; | 159 | struct pt_regs; |
160 | extern int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
161 | 160 | ||
162 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | 161 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) |
163 | 162 | ||
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index 76125777483c..c70545689da8 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h | |||
@@ -351,6 +351,7 @@ | |||
351 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/ | 351 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/ |
352 | #define __ARCH_WANT_SYS_OLDUMOUNT | 352 | #define __ARCH_WANT_SYS_OLDUMOUNT |
353 | #define __ARCH_WANT_SYS_RT_SIGACTION | 353 | #define __ARCH_WANT_SYS_RT_SIGACTION |
354 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
354 | 355 | ||
355 | #define __IGNORE_lchown | 356 | #define __IGNORE_lchown |
356 | #define __IGNORE_setuid | 357 | #define __IGNORE_setuid |
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 403869833b98..90149daa560f 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S | |||
@@ -235,8 +235,7 @@ work_resched: | |||
235 | work_notifysig: ; deal with pending signals and | 235 | work_notifysig: ; deal with pending signals and |
236 | ; notify-resume requests | 236 | ; notify-resume requests |
237 | mv r0, sp ; arg1 : struct pt_regs *regs | 237 | mv r0, sp ; arg1 : struct pt_regs *regs |
238 | ldi r1, #0 ; arg2 : sigset_t *oldset | 238 | ldi r1, r9 ; arg2 : __u32 thread_info_flags |
239 | mv r2, r9 ; arg3 : __u32 thread_info_flags | ||
240 | bl do_notify_resume | 239 | bl do_notify_resume |
241 | bra restore_all | 240 | bra restore_all |
242 | 241 | ||
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index 144b0f124fc7..acd69f7f3357 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c | |||
@@ -28,37 +28,6 @@ | |||
28 | 28 | ||
29 | #define DEBUG_SIG 0 | 29 | #define DEBUG_SIG 0 |
30 | 30 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
32 | |||
33 | int do_signal(struct pt_regs *, sigset_t *); | ||
34 | |||
35 | asmlinkage int | ||
36 | sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, | ||
37 | unsigned long r2, unsigned long r3, unsigned long r4, | ||
38 | unsigned long r5, unsigned long r6, struct pt_regs *regs) | ||
39 | { | ||
40 | sigset_t newset; | ||
41 | |||
42 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
43 | if (sigsetsize != sizeof(sigset_t)) | ||
44 | return -EINVAL; | ||
45 | |||
46 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
47 | return -EFAULT; | ||
48 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
49 | |||
50 | spin_lock_irq(¤t->sighand->siglock); | ||
51 | current->saved_sigmask = current->blocked; | ||
52 | current->blocked = newset; | ||
53 | recalc_sigpending(); | ||
54 | spin_unlock_irq(¤t->sighand->siglock); | ||
55 | |||
56 | current->state = TASK_INTERRUPTIBLE; | ||
57 | schedule(); | ||
58 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
59 | return -ERESTARTNOHAND; | ||
60 | } | ||
61 | |||
62 | asmlinkage int | 31 | asmlinkage int |
63 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 32 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
64 | unsigned long r2, unsigned long r3, unsigned long r4, | 33 | unsigned long r2, unsigned long r3, unsigned long r4, |
@@ -332,12 +301,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
332 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 301 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
333 | * mistake. | 302 | * mistake. |
334 | */ | 303 | */ |
335 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | 304 | static int do_signal(struct pt_regs *regs) |
336 | { | 305 | { |
337 | siginfo_t info; | 306 | siginfo_t info; |
338 | int signr; | 307 | int signr; |
339 | struct k_sigaction ka; | 308 | struct k_sigaction ka; |
340 | unsigned short inst; | 309 | unsigned short inst; |
310 | sigset_t *oldset; | ||
341 | 311 | ||
342 | /* | 312 | /* |
343 | * We want the common case to go fast, which | 313 | * We want the common case to go fast, which |
@@ -351,7 +321,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
351 | if (try_to_freeze()) | 321 | if (try_to_freeze()) |
352 | goto no_signal; | 322 | goto no_signal; |
353 | 323 | ||
354 | if (!oldset) | 324 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
325 | oldset = ¤t->saved_sigmask; | ||
326 | else | ||
355 | oldset = ¤t->blocked; | 327 | oldset = ¤t->blocked; |
356 | 328 | ||
357 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 329 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
@@ -364,6 +336,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
364 | 336 | ||
365 | /* Whee! Actually deliver the signal. */ | 337 | /* Whee! Actually deliver the signal. */ |
366 | handle_signal(signr, &ka, &info, oldset, regs); | 338 | handle_signal(signr, &ka, &info, oldset, regs); |
339 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
367 | return 1; | 340 | return 1; |
368 | } | 341 | } |
369 | 342 | ||
@@ -391,6 +364,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
391 | regs->bpc -= 4; | 364 | regs->bpc -= 4; |
392 | } | 365 | } |
393 | } | 366 | } |
367 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
368 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
369 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
370 | } | ||
394 | return 0; | 371 | return 0; |
395 | } | 372 | } |
396 | 373 | ||
@@ -398,8 +375,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
398 | * notification of userspace execution resumption | 375 | * notification of userspace execution resumption |
399 | * - triggered by current->work.notify_resume | 376 | * - triggered by current->work.notify_resume |
400 | */ | 377 | */ |
401 | void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, | 378 | void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) |
402 | __u32 thread_info_flags) | ||
403 | { | 379 | { |
404 | /* Pending single-step? */ | 380 | /* Pending single-step? */ |
405 | if (thread_info_flags & _TIF_SINGLESTEP) | 381 | if (thread_info_flags & _TIF_SINGLESTEP) |
@@ -407,7 +383,7 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, | |||
407 | 383 | ||
408 | /* deal with pending signal delivery */ | 384 | /* deal with pending signal delivery */ |
409 | if (thread_info_flags & _TIF_SIGPENDING) | 385 | if (thread_info_flags & _TIF_SIGPENDING) |
410 | do_signal(regs,oldset); | 386 | do_signal(regs); |
411 | 387 | ||
412 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 388 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
413 | clear_thread_flag(TIF_NOTIFY_RESUME); | 389 | clear_thread_flag(TIF_NOTIFY_RESUME); |