aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/signal32.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 05:42:49 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 05:42:49 -0500
commit2d7d5f05111a9d913131a2764d8b20157f8f758d (patch)
tree792deb7a3b9f72894d16affff1569a15b35e428b /arch/sparc64/kernel/signal32.c
parentf7111ceb5266750db2a1d193b98fb6a3d9b5a56a (diff)
[SPARC]: Add support for *at(), ppoll, and pselect syscalls.
This also includes by necessity _TIF_RESTORE_SIGMASK support, which actually resulted in a lot of cleanups. The sparc signal handling code is quite a mess and I should clean it up some day. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/signal32.c')
-rw-r--r--arch/sparc64/kernel/signal32.c122
1 files changed, 19 insertions, 103 deletions
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 009a86e5ded4..708ba9b42cda 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -32,9 +32,6 @@
32 32
33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
34 34
35int do_signal32(sigset_t *oldset, struct pt_regs *regs,
36 unsigned long orig_o0, int ret_from_syscall);
37
38/* Signal frames: the original one (compatible with SunOS): 35/* Signal frames: the original one (compatible with SunOS):
39 * 36 *
40 * Set up a signal frame... Make the stack look the way SunOS 37 * Set up a signal frame... Make the stack look the way SunOS
@@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
226 return 0; 223 return 0;
227} 224}
228 225
229/*
230 * atomically swap in the new signal mask, and wait for a signal.
231 * This is really tricky on the Sparc, watch out...
232 */
233asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs)
234{
235 sigset_t saveset;
236
237 set &= _BLOCKABLE;
238 spin_lock_irq(&current->sighand->siglock);
239 saveset = current->blocked;
240 siginitset(&current->blocked, set);
241 recalc_sigpending();
242 spin_unlock_irq(&current->sighand->siglock);
243
244 regs->tpc = regs->tnpc;
245 regs->tnpc += 4;
246 if (test_thread_flag(TIF_32BIT)) {
247 regs->tpc &= 0xffffffff;
248 regs->tnpc &= 0xffffffff;
249 }
250
251 /* Condition codes and return value where set here for sigpause,
252 * and so got used by setup_frame, which again causes sigreturn()
253 * to return -EINTR.
254 */
255 while (1) {
256 current->state = TASK_INTERRUPTIBLE;
257 schedule();
258 /*
259 * Return -EINTR and set condition code here,
260 * so the interrupted system call actually returns
261 * these.
262 */
263 regs->tstate |= TSTATE_ICARRY;
264 regs->u_regs[UREG_I0] = EINTR;
265 if (do_signal32(&saveset, regs, 0, 0))
266 return;
267 }
268}
269
270asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs)
271{
272 sigset_t oldset, set;
273 compat_sigset_t set32;
274
275 /* XXX: Don't preclude handling different sized sigset_t's. */
276 if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) {
277 regs->tstate |= TSTATE_ICARRY;
278 regs->u_regs[UREG_I0] = EINVAL;
279 return;
280 }
281 if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) {
282 regs->tstate |= TSTATE_ICARRY;
283 regs->u_regs[UREG_I0] = EFAULT;
284 return;
285 }
286 switch (_NSIG_WORDS) {
287 case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
288 case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
289 case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
290 case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
291 }
292 sigdelsetmask(&set, ~_BLOCKABLE);
293 spin_lock_irq(&current->sighand->siglock);
294 oldset = current->blocked;
295 current->blocked = set;
296 recalc_sigpending();
297 spin_unlock_irq(&current->sighand->siglock);
298
299 regs->tpc = regs->tnpc;
300 regs->tnpc += 4;
301 if (test_thread_flag(TIF_32BIT)) {
302 regs->tpc &= 0xffffffff;
303 regs->tnpc &= 0xffffffff;
304 }
305
306 /* Condition codes and return value where set here for sigpause,
307 * and so got used by setup_frame, which again causes sigreturn()
308 * to return -EINTR.
309 */
310 while (1) {
311 current->state = TASK_INTERRUPTIBLE;
312 schedule();
313 /*
314 * Return -EINTR and set condition code here,
315 * so the interrupted system call actually returns
316 * these.
317 */
318 regs->tstate |= TSTATE_ICARRY;
319 regs->u_regs[UREG_I0] = EINTR;
320 if (do_signal32(&oldset, regs, 0, 0))
321 return;
322 }
323}
324
325static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) 226static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
326{ 227{
327 unsigned long *fpregs = current_thread_info()->fpregs; 228 unsigned long *fpregs = current_thread_info()->fpregs;
@@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
1362 * want to handle. Thus you cannot kill init even with a SIGKILL even by 1263 * want to handle. Thus you cannot kill init even with a SIGKILL even by
1363 * mistake. 1264 * mistake.
1364 */ 1265 */
1365int do_signal32(sigset_t *oldset, struct pt_regs * regs, 1266void do_signal32(sigset_t *oldset, struct pt_regs * regs,
1366 unsigned long orig_i0, int restart_syscall) 1267 unsigned long orig_i0, int restart_syscall)
1367{ 1268{
1368 siginfo_t info; 1269 siginfo_t info;
1369 struct signal_deliver_cookie cookie; 1270 struct signal_deliver_cookie cookie;
@@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
1380 syscall_restart32(orig_i0, regs, &ka.sa); 1281 syscall_restart32(orig_i0, regs, &ka.sa);
1381 handle_signal32(signr, &ka, &info, oldset, 1282 handle_signal32(signr, &ka, &info, oldset,
1382 regs, svr4_signal); 1283 regs, svr4_signal);
1383 return 1; 1284
1285 /* a signal was successfully delivered; the saved
1286 * sigmask will have been stored in the signal frame,
1287 * and will be restored by sigreturn, so we can simply
1288 * clear the TIF_RESTORE_SIGMASK flag.
1289 */
1290 if (test_thread_flag(TIF_RESTORE_SIGMASK))
1291 clear_thread_flag(TIF_RESTORE_SIGMASK);
1292 return;
1384 } 1293 }
1385 if (cookie.restart_syscall && 1294 if (cookie.restart_syscall &&
1386 (regs->u_regs[UREG_I0] == ERESTARTNOHAND || 1295 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
1397 regs->tpc -= 4; 1306 regs->tpc -= 4;
1398 regs->tnpc -= 4; 1307 regs->tnpc -= 4;
1399 } 1308 }
1400 return 0; 1309
1310 /* if there's no signal to deliver, we just put the saved sigmask
1311 * back
1312 */
1313 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
1314 clear_thread_flag(TIF_RESTORE_SIGMASK);
1315 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
1316 }
1401} 1317}
1402 1318
1403struct sigstack32 { 1319struct sigstack32 {