diff options
Diffstat (limited to 'arch/alpha/kernel/signal.c')
-rw-r--r-- | arch/alpha/kernel/signal.c | 97 |
1 files changed, 18 insertions, 79 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 0932dbb1ef8e..6f7feb5db271 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
@@ -41,46 +41,20 @@ static void do_signal(struct pt_regs *, struct switch_stack *, | |||
41 | /* | 41 | /* |
42 | * The OSF/1 sigprocmask calling sequence is different from the | 42 | * The OSF/1 sigprocmask calling sequence is different from the |
43 | * C sigprocmask() sequence.. | 43 | * C sigprocmask() sequence.. |
44 | * | ||
45 | * how: | ||
46 | * 1 - SIG_BLOCK | ||
47 | * 2 - SIG_UNBLOCK | ||
48 | * 3 - SIG_SETMASK | ||
49 | * | ||
50 | * We change the range to -1 .. 1 in order to let gcc easily | ||
51 | * use the conditional move instructions. | ||
52 | * | ||
53 | * Note that we don't need to acquire the kernel lock for SMP | ||
54 | * operation, as all of this is local to this thread. | ||
55 | */ | 44 | */ |
56 | SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask, | 45 | SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) |
57 | struct pt_regs *, regs) | ||
58 | { | 46 | { |
59 | unsigned long oldmask = -EINVAL; | 47 | sigset_t oldmask; |
60 | 48 | sigset_t mask; | |
61 | if ((unsigned long)how-1 <= 2) { | 49 | unsigned long res; |
62 | long sign = how-2; /* -1 .. 1 */ | 50 | |
63 | unsigned long block, unblock; | 51 | siginitset(&mask, newmask & _BLOCKABLE); |
64 | 52 | res = sigprocmask(how, &mask, &oldmask); | |
65 | newmask &= _BLOCKABLE; | 53 | if (!res) { |
66 | spin_lock_irq(¤t->sighand->siglock); | 54 | force_successful_syscall_return(); |
67 | oldmask = current->blocked.sig[0]; | 55 | res = oldmask.sig[0]; |
68 | |||
69 | unblock = oldmask & ~newmask; | ||
70 | block = oldmask | newmask; | ||
71 | if (!sign) | ||
72 | block = unblock; | ||
73 | if (sign <= 0) | ||
74 | newmask = block; | ||
75 | if (_NSIG_WORDS > 1 && sign > 0) | ||
76 | sigemptyset(¤t->blocked); | ||
77 | current->blocked.sig[0] = newmask; | ||
78 | recalc_sigpending(); | ||
79 | spin_unlock_irq(¤t->sighand->siglock); | ||
80 | |||
81 | regs->r0 = 0; /* special no error return */ | ||
82 | } | 56 | } |
83 | return oldmask; | 57 | return res; |
84 | } | 58 | } |
85 | 59 | ||
86 | SYSCALL_DEFINE3(osf_sigaction, int, sig, | 60 | SYSCALL_DEFINE3(osf_sigaction, int, sig, |
@@ -94,9 +68,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, | |||
94 | old_sigset_t mask; | 68 | old_sigset_t mask; |
95 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 69 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
96 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 70 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
97 | __get_user(new_ka.sa.sa_flags, &act->sa_flags)) | 71 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || |
72 | __get_user(mask, &act->sa_mask)) | ||
98 | return -EFAULT; | 73 | return -EFAULT; |
99 | __get_user(mask, &act->sa_mask); | ||
100 | siginitset(&new_ka.sa.sa_mask, mask); | 74 | siginitset(&new_ka.sa.sa_mask, mask); |
101 | new_ka.ka_restorer = NULL; | 75 | new_ka.ka_restorer = NULL; |
102 | } | 76 | } |
@@ -106,9 +80,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, | |||
106 | if (!ret && oact) { | 80 | if (!ret && oact) { |
107 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 81 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
108 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 82 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
109 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) | 83 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || |
84 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
110 | return -EFAULT; | 85 | return -EFAULT; |
111 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
112 | } | 86 | } |
113 | 87 | ||
114 | return ret; | 88 | return ret; |
@@ -144,8 +118,7 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, | |||
144 | /* | 118 | /* |
145 | * Atomically swap in the new signal mask, and wait for a signal. | 119 | * Atomically swap in the new signal mask, and wait for a signal. |
146 | */ | 120 | */ |
147 | asmlinkage int | 121 | SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) |
148 | do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) | ||
149 | { | 122 | { |
150 | mask &= _BLOCKABLE; | 123 | mask &= _BLOCKABLE; |
151 | spin_lock_irq(¤t->sighand->siglock); | 124 | spin_lock_irq(¤t->sighand->siglock); |
@@ -154,41 +127,6 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) | |||
154 | recalc_sigpending(); | 127 | recalc_sigpending(); |
155 | spin_unlock_irq(¤t->sighand->siglock); | 128 | spin_unlock_irq(¤t->sighand->siglock); |
156 | 129 | ||
157 | /* Indicate EINTR on return from any possible signal handler, | ||
158 | which will not come back through here, but via sigreturn. */ | ||
159 | regs->r0 = EINTR; | ||
160 | regs->r19 = 1; | ||
161 | |||
162 | current->state = TASK_INTERRUPTIBLE; | ||
163 | schedule(); | ||
164 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
165 | return -ERESTARTNOHAND; | ||
166 | } | ||
167 | |||
168 | asmlinkage int | ||
169 | do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, | ||
170 | struct pt_regs *regs, struct switch_stack *sw) | ||
171 | { | ||
172 | sigset_t set; | ||
173 | |||
174 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
175 | if (sigsetsize != sizeof(sigset_t)) | ||
176 | return -EINVAL; | ||
177 | if (copy_from_user(&set, uset, sizeof(set))) | ||
178 | return -EFAULT; | ||
179 | |||
180 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
181 | spin_lock_irq(¤t->sighand->siglock); | ||
182 | current->saved_sigmask = current->blocked; | ||
183 | current->blocked = set; | ||
184 | recalc_sigpending(); | ||
185 | spin_unlock_irq(¤t->sighand->siglock); | ||
186 | |||
187 | /* Indicate EINTR on return from any possible signal handler, | ||
188 | which will not come back through here, but via sigreturn. */ | ||
189 | regs->r0 = EINTR; | ||
190 | regs->r19 = 1; | ||
191 | |||
192 | current->state = TASK_INTERRUPTIBLE; | 130 | current->state = TASK_INTERRUPTIBLE; |
193 | schedule(); | 131 | schedule(); |
194 | set_thread_flag(TIF_RESTORE_SIGMASK); | 132 | set_thread_flag(TIF_RESTORE_SIGMASK); |
@@ -239,6 +177,8 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
239 | unsigned long usp; | 177 | unsigned long usp; |
240 | long i, err = __get_user(regs->pc, &sc->sc_pc); | 178 | long i, err = __get_user(regs->pc, &sc->sc_pc); |
241 | 179 | ||
180 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
181 | |||
242 | sw->r26 = (unsigned long) ret_from_sys_call; | 182 | sw->r26 = (unsigned long) ret_from_sys_call; |
243 | 183 | ||
244 | err |= __get_user(regs->r0, sc->sc_regs+0); | 184 | err |= __get_user(regs->r0, sc->sc_regs+0); |
@@ -591,7 +531,6 @@ syscall_restart(unsigned long r0, unsigned long r19, | |||
591 | regs->pc -= 4; | 531 | regs->pc -= 4; |
592 | break; | 532 | break; |
593 | case ERESTART_RESTARTBLOCK: | 533 | case ERESTART_RESTARTBLOCK: |
594 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
595 | regs->r0 = EINTR; | 534 | regs->r0 = EINTR; |
596 | break; | 535 | break; |
597 | } | 536 | } |