diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-04-22 01:30:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-21 23:58:07 -0400 |
commit | 7ae4e32a65148353db3458e3eb87117f25620ac5 (patch) | |
tree | 31a5f95370fb32cb22838332c54e9a364bd9b188 /arch/h8300/kernel | |
parent | 8b6c3309c94b7296614d7783eb259555a6be6f7e (diff) |
h8300: switch to saved_sigmask-based sigsuspend/rt_sigsuspend
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/h8300/kernel')
-rw-r--r-- | arch/h8300/kernel/signal.c | 73 | ||||
-rw-r--r-- | arch/h8300/kernel/syscalls.S | 6 |
2 files changed, 20 insertions, 59 deletions
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 78e9b65df93e..b5e360a95519 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c | |||
@@ -49,56 +49,15 @@ | |||
49 | 49 | ||
50 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 50 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
51 | 51 | ||
52 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
53 | |||
54 | /* | 52 | /* |
55 | * Atomically swap in the new signal mask, and wait for a signal. | 53 | * Atomically swap in the new signal mask, and wait for a signal. |
56 | */ | 54 | */ |
57 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | ||
58 | { | ||
59 | old_sigset_t mask = regs->er3; | ||
60 | sigset_t saveset, blocked; | ||
61 | |||
62 | saveset = current->blocked; | ||
63 | |||
64 | mask &= _BLOCKABLE; | ||
65 | siginitset(&blocked, mask); | ||
66 | set_current_blocked(&blocked); | ||
67 | |||
68 | regs->er0 = -EINTR; | ||
69 | while (1) { | ||
70 | current->state = TASK_INTERRUPTIBLE; | ||
71 | schedule(); | ||
72 | if (do_signal(regs, &saveset)) | ||
73 | return -EINTR; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | asmlinkage int | 55 | asmlinkage int |
78 | do_rt_sigsuspend(struct pt_regs *regs) | 56 | sys_sigsuspend(int unused1, int unused2, old_sigset_t mask) |
79 | { | 57 | { |
80 | sigset_t *unewset = (sigset_t *)regs->er1; | 58 | sigset_t blocked; |
81 | size_t sigsetsize = (size_t)regs->er2; | 59 | siginitset(&blocked, mask); |
82 | sigset_t saveset, newset; | 60 | return sigsuspend(&blocked); |
83 | |||
84 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
85 | if (sigsetsize != sizeof(sigset_t)) | ||
86 | return -EINVAL; | ||
87 | |||
88 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
89 | return -EFAULT; | ||
90 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
91 | |||
92 | saveset = current->blocked; | ||
93 | set_current_blocked(&newset); | ||
94 | |||
95 | regs->er0 = -EINTR; | ||
96 | while (1) { | ||
97 | current->state = TASK_INTERRUPTIBLE; | ||
98 | schedule(); | ||
99 | if (do_signal(regs, &saveset)) | ||
100 | return -EINTR; | ||
101 | } | ||
102 | } | 61 | } |
103 | 62 | ||
104 | asmlinkage int | 63 | asmlinkage int |
@@ -482,8 +441,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
482 | else | 441 | else |
483 | ret = setup_frame(sig, ka, oldset, regs); | 442 | ret = setup_frame(sig, ka, oldset, regs); |
484 | 443 | ||
485 | if (!ret) | 444 | if (!ret) { |
486 | block_sigmask(ka, sig); | 445 | block_sigmask(ka, sig); |
446 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
447 | } | ||
487 | } | 448 | } |
488 | 449 | ||
489 | /* | 450 | /* |
@@ -491,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
491 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 452 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
492 | * mistake. | 453 | * mistake. |
493 | */ | 454 | */ |
494 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | 455 | statis void do_signal(struct pt_regs *regs) |
495 | { | 456 | { |
496 | siginfo_t info; | 457 | siginfo_t info; |
497 | int signr; | 458 | int signr; |
498 | struct k_sigaction ka; | 459 | struct k_sigaction ka; |
460 | sigset_t *oldset; | ||
499 | 461 | ||
500 | /* | 462 | /* |
501 | * We want the common case to go fast, which | 463 | * We want the common case to go fast, which |
@@ -504,21 +466,23 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
504 | * if so. | 466 | * if so. |
505 | */ | 467 | */ |
506 | if ((regs->ccr & 0x10)) | 468 | if ((regs->ccr & 0x10)) |
507 | return 1; | 469 | return; |
508 | 470 | ||
509 | if (try_to_freeze()) | 471 | if (try_to_freeze()) |
510 | goto no_signal; | 472 | goto no_signal; |
511 | 473 | ||
512 | current->thread.esp0 = (unsigned long) regs; | 474 | current->thread.esp0 = (unsigned long) regs; |
513 | 475 | ||
514 | if (!oldset) | 476 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
477 | oldset = ¤t->saved_sigmask; | ||
478 | else | ||
515 | oldset = ¤t->blocked; | 479 | oldset = ¤t->blocked; |
516 | 480 | ||
517 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 481 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
518 | if (signr > 0) { | 482 | if (signr > 0) { |
519 | /* Whee! Actually deliver the signal. */ | 483 | /* Whee! Actually deliver the signal. */ |
520 | handle_signal(signr, &info, &ka, oldset, regs); | 484 | handle_signal(signr, &info, &ka, oldset, regs); |
521 | return 1; | 485 | return; |
522 | } | 486 | } |
523 | no_signal: | 487 | no_signal: |
524 | /* Did we come from a system call? */ | 488 | /* Did we come from a system call? */ |
@@ -535,13 +499,16 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
535 | regs->pc -= 2; | 499 | regs->pc -= 2; |
536 | } | 500 | } |
537 | } | 501 | } |
538 | return 0; | 502 | |
503 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
504 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
505 | set_current_blocked(¤t->saved_sigmask); | ||
539 | } | 506 | } |
540 | 507 | ||
541 | asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) | 508 | asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) |
542 | { | 509 | { |
543 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 510 | if (thread_info_flags & _TIF_SIGPENDING) |
544 | do_signal(regs, NULL); | 511 | do_signal(regs); |
545 | 512 | ||
546 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 513 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
547 | clear_thread_flag(TIF_NOTIFY_RESUME); | 514 | clear_thread_flag(TIF_NOTIFY_RESUME); |
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 4be2ea2fbe26..9d77e715a2ed 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table) | |||
343 | SYMBOL_NAME_LABEL(sys_clone) | 343 | SYMBOL_NAME_LABEL(sys_clone) |
344 | call_sp h8300_clone | 344 | call_sp h8300_clone |
345 | 345 | ||
346 | SYMBOL_NAME_LABEL(sys_sigsuspend) | ||
347 | call_sp do_sigsuspend | ||
348 | |||
349 | SYMBOL_NAME_LABEL(sys_rt_sigsuspend) | ||
350 | call_sp do_rt_sigsuspend | ||
351 | |||
352 | SYMBOL_NAME_LABEL(sys_sigreturn) | 346 | SYMBOL_NAME_LABEL(sys_sigreturn) |
353 | call_sp do_sigreturn | 347 | call_sp do_sigreturn |
354 | 348 | ||