diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-11 17:09:20 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-01-07 08:06:59 -0500 |
commit | 710e91e455caf5cfec02892d667b41f312ec166c (patch) | |
tree | 9e6f3d5c3dcb387809cab3cbc04060768b8a75db /arch/m68knommu/kernel/signal.c | |
parent | bf814b45d560b22e8657ca44d0ae6941ab9d8d36 (diff) |
m68knommu: Switch to saner sigsuspend
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68knommu/kernel/signal.c')
-rw-r--r-- | arch/m68knommu/kernel/signal.c | 63 |
1 files changed, 19 insertions, 44 deletions
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 1934de7aaf6c..c973230dad82 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c | |||
@@ -53,60 +53,25 @@ | |||
53 | 53 | ||
54 | void ret_from_user_signal(void); | 54 | void ret_from_user_signal(void); |
55 | void ret_from_user_rt_signal(void); | 55 | void ret_from_user_rt_signal(void); |
56 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
57 | 56 | ||
58 | /* | 57 | /* |
59 | * Atomically swap in the new signal mask, and wait for a signal. | 58 | * Atomically swap in the new signal mask, and wait for a signal. |
60 | */ | 59 | */ |
61 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | 60 | asmlinkage int |
61 | sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) | ||
62 | { | 62 | { |
63 | old_sigset_t mask = regs->d3; | ||
64 | sigset_t saveset; | ||
65 | |||
66 | mask &= _BLOCKABLE; | 63 | mask &= _BLOCKABLE; |
67 | spin_lock_irq(¤t->sighand->siglock); | 64 | spin_lock_irq(¤t->sighand->siglock); |
68 | saveset = current->blocked; | 65 | current->saved_sigmask = current->blocked; |
69 | siginitset(¤t->blocked, mask); | 66 | siginitset(¤t->blocked, mask); |
70 | recalc_sigpending(); | 67 | recalc_sigpending(); |
71 | spin_unlock_irq(¤t->sighand->siglock); | 68 | spin_unlock_irq(¤t->sighand->siglock); |
72 | 69 | ||
73 | regs->d0 = -EINTR; | 70 | current->state = TASK_INTERRUPTIBLE; |
74 | while (1) { | 71 | schedule(); |
75 | current->state = TASK_INTERRUPTIBLE; | 72 | set_restore_sigmask(); |
76 | schedule(); | ||
77 | if (do_signal(&saveset, regs)) | ||
78 | return -EINTR; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | asmlinkage int | ||
83 | do_rt_sigsuspend(struct pt_regs *regs) | ||
84 | { | ||
85 | sigset_t *unewset = (sigset_t *)regs->d1; | ||
86 | size_t sigsetsize = (size_t)regs->d2; | ||
87 | sigset_t saveset, newset; | ||
88 | |||
89 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
90 | if (sigsetsize != sizeof(sigset_t)) | ||
91 | return -EINVAL; | ||
92 | |||
93 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
94 | return -EFAULT; | ||
95 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
96 | 73 | ||
97 | spin_lock_irq(¤t->sighand->siglock); | 74 | return -ERESTARTNOHAND; |
98 | saveset = current->blocked; | ||
99 | current->blocked = newset; | ||
100 | recalc_sigpending(); | ||
101 | spin_unlock_irq(¤t->sighand->siglock); | ||
102 | |||
103 | regs->d0 = -EINTR; | ||
104 | while (1) { | ||
105 | current->state = TASK_INTERRUPTIBLE; | ||
106 | schedule(); | ||
107 | if (do_signal(&saveset, regs)) | ||
108 | return -EINTR; | ||
109 | } | ||
110 | } | 75 | } |
111 | 76 | ||
112 | asmlinkage int | 77 | asmlinkage int |
@@ -752,11 +717,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
752 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 717 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
753 | * mistake. | 718 | * mistake. |
754 | */ | 719 | */ |
755 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | 720 | asmlinkage int do_signal(struct pt_regs *regs) |
756 | { | 721 | { |
757 | struct k_sigaction ka; | 722 | struct k_sigaction ka; |
758 | siginfo_t info; | 723 | siginfo_t info; |
759 | int signr; | 724 | int signr; |
725 | sigset_t *oldset; | ||
760 | 726 | ||
761 | /* | 727 | /* |
762 | * We want the common case to go fast, which | 728 | * We want the common case to go fast, which |
@@ -767,13 +733,16 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
767 | if (!user_mode(regs)) | 733 | if (!user_mode(regs)) |
768 | return 1; | 734 | return 1; |
769 | 735 | ||
770 | if (!oldset) | 736 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
737 | oldset = ¤t->saved_sigmask; | ||
738 | else | ||
771 | oldset = ¤t->blocked; | 739 | oldset = ¤t->blocked; |
772 | 740 | ||
773 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 741 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
774 | if (signr > 0) { | 742 | if (signr > 0) { |
775 | /* Whee! Actually deliver the signal. */ | 743 | /* Whee! Actually deliver the signal. */ |
776 | handle_signal(signr, &ka, &info, oldset, regs); | 744 | handle_signal(signr, &ka, &info, oldset, regs); |
745 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
777 | return 1; | 746 | return 1; |
778 | } | 747 | } |
779 | 748 | ||
@@ -782,5 +751,11 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
782 | /* Restart the system call - no handlers present */ | 751 | /* Restart the system call - no handlers present */ |
783 | handle_restart(regs, NULL, 0); | 752 | handle_restart(regs, NULL, 0); |
784 | } | 753 | } |
754 | |||
755 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
756 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
757 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
758 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
759 | } | ||
785 | return 0; | 760 | return 0; |
786 | } | 761 | } |