aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/signal.c')
-rw-r--r--arch/s390/kernel/signal.c146
1 files changed, 71 insertions, 75 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 6ae4a77270b5..ae1927e48cfb 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -1,8 +1,7 @@
1/* 1/*
2 * arch/s390/kernel/signal.c 2 * arch/s390/kernel/signal.c
3 * 3 *
4 * S390 version 4 * Copyright (C) IBM Corp. 1999,2006
5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 5 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
7 * 6 *
8 * Based on Intel version 7 * Based on Intel version
@@ -51,60 +50,24 @@ typedef struct
51 struct ucontext uc; 50 struct ucontext uc;
52} rt_sigframe; 51} rt_sigframe;
53 52
54int do_signal(struct pt_regs *regs, sigset_t *oldset);
55
56/* 53/*
57 * Atomically swap in the new signal mask, and wait for a signal. 54 * Atomically swap in the new signal mask, and wait for a signal.
58 */ 55 */
59asmlinkage int 56asmlinkage int
60sys_sigsuspend(struct pt_regs * regs, int history0, int history1, 57sys_sigsuspend(int history0, int history1, old_sigset_t mask)
61 old_sigset_t mask)
62{ 58{
63 sigset_t saveset;
64
65 mask &= _BLOCKABLE; 59 mask &= _BLOCKABLE;
66 spin_lock_irq(&current->sighand->siglock); 60 spin_lock_irq(&current->sighand->siglock);
67 saveset = current->blocked; 61 current->saved_sigmask = current->blocked;
68 siginitset(&current->blocked, mask); 62 siginitset(&current->blocked, mask);
69 recalc_sigpending(); 63 recalc_sigpending();
70 spin_unlock_irq(&current->sighand->siglock); 64 spin_unlock_irq(&current->sighand->siglock);
71 regs->gprs[2] = -EINTR;
72
73 while (1) {
74 set_current_state(TASK_INTERRUPTIBLE);
75 schedule();
76 if (do_signal(regs, &saveset))
77 return -EINTR;
78 }
79}
80
81asmlinkage long
82sys_rt_sigsuspend(struct pt_regs *regs, sigset_t __user *unewset,
83 size_t sigsetsize)
84{
85 sigset_t saveset, newset;
86 65
87 /* XXX: Don't preclude handling different sized sigset_t's. */ 66 current->state = TASK_INTERRUPTIBLE;
88 if (sigsetsize != sizeof(sigset_t)) 67 schedule();
89 return -EINVAL; 68 set_thread_flag(TIF_RESTORE_SIGMASK);
90 69
91 if (copy_from_user(&newset, unewset, sizeof(newset))) 70 return -ERESTARTNOHAND;
92 return -EFAULT;
93 sigdelsetmask(&newset, ~_BLOCKABLE);
94
95 spin_lock_irq(&current->sighand->siglock);
96 saveset = current->blocked;
97 current->blocked = newset;
98 recalc_sigpending();
99 spin_unlock_irq(&current->sighand->siglock);
100 regs->gprs[2] = -EINTR;
101
102 while (1) {
103 set_current_state(TASK_INTERRUPTIBLE);
104 schedule();
105 if (do_signal(regs, &saveset))
106 return -EINTR;
107 }
108} 71}
109 72
110asmlinkage long 73asmlinkage long
@@ -306,8 +269,8 @@ static inline int map_signal(int sig)
306 return sig; 269 return sig;
307} 270}
308 271
309static void setup_frame(int sig, struct k_sigaction *ka, 272static int setup_frame(int sig, struct k_sigaction *ka,
310 sigset_t *set, struct pt_regs * regs) 273 sigset_t *set, struct pt_regs * regs)
311{ 274{
312 sigframe __user *frame; 275 sigframe __user *frame;
313 276
@@ -355,13 +318,14 @@ static void setup_frame(int sig, struct k_sigaction *ka,
355 /* Place signal number on stack to allow backtrace from handler. */ 318 /* Place signal number on stack to allow backtrace from handler. */
356 if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) 319 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
357 goto give_sigsegv; 320 goto give_sigsegv;
358 return; 321 return 0;
359 322
360give_sigsegv: 323give_sigsegv:
361 force_sigsegv(sig, current); 324 force_sigsegv(sig, current);
325 return -EFAULT;
362} 326}
363 327
364static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 328static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
365 sigset_t *set, struct pt_regs * regs) 329 sigset_t *set, struct pt_regs * regs)
366{ 330{
367 int err = 0; 331 int err = 0;
@@ -409,32 +373,39 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
409 regs->gprs[2] = map_signal(sig); 373 regs->gprs[2] = map_signal(sig);
410 regs->gprs[3] = (unsigned long) &frame->info; 374 regs->gprs[3] = (unsigned long) &frame->info;
411 regs->gprs[4] = (unsigned long) &frame->uc; 375 regs->gprs[4] = (unsigned long) &frame->uc;
412 return; 376 return 0;
413 377
414give_sigsegv: 378give_sigsegv:
415 force_sigsegv(sig, current); 379 force_sigsegv(sig, current);
380 return -EFAULT;
416} 381}
417 382
418/* 383/*
419 * OK, we're invoking a handler 384 * OK, we're invoking a handler
420 */ 385 */
421 386
422static void 387static int
423handle_signal(unsigned long sig, struct k_sigaction *ka, 388handle_signal(unsigned long sig, struct k_sigaction *ka,
424 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) 389 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
425{ 390{
391 int ret;
392
426 /* Set up the stack frame */ 393 /* Set up the stack frame */
427 if (ka->sa.sa_flags & SA_SIGINFO) 394 if (ka->sa.sa_flags & SA_SIGINFO)
428 setup_rt_frame(sig, ka, info, oldset, regs); 395 ret = setup_rt_frame(sig, ka, info, oldset, regs);
429 else 396 else
430 setup_frame(sig, ka, oldset, regs); 397 ret = setup_frame(sig, ka, oldset, regs);
398
399 if (ret == 0) {
400 spin_lock_irq(&current->sighand->siglock);
401 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
402 if (!(ka->sa.sa_flags & SA_NODEFER))
403 sigaddset(&current->blocked,sig);
404 recalc_sigpending();
405 spin_unlock_irq(&current->sighand->siglock);
406 }
431 407
432 spin_lock_irq(&current->sighand->siglock); 408 return ret;
433 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
434 if (!(ka->sa.sa_flags & SA_NODEFER))
435 sigaddset(&current->blocked,sig);
436 recalc_sigpending();
437 spin_unlock_irq(&current->sighand->siglock);
438} 409}
439 410
440/* 411/*
@@ -446,12 +417,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
446 * the kernel can handle, and then we build all the user-level signal handling 417 * the kernel can handle, and then we build all the user-level signal handling
447 * stack-frames in one go after that. 418 * stack-frames in one go after that.
448 */ 419 */
449int do_signal(struct pt_regs *regs, sigset_t *oldset) 420void do_signal(struct pt_regs *regs)
450{ 421{
451 unsigned long retval = 0, continue_addr = 0, restart_addr = 0; 422 unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
452 siginfo_t info; 423 siginfo_t info;
453 int signr; 424 int signr;
454 struct k_sigaction ka; 425 struct k_sigaction ka;
426 sigset_t *oldset;
455 427
456 /* 428 /*
457 * We want the common case to go fast, which 429 * We want the common case to go fast, which
@@ -460,9 +432,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
460 * if so. 432 * if so.
461 */ 433 */
462 if (!user_mode(regs)) 434 if (!user_mode(regs))
463 return 1; 435 return;
464 436
465 if (!oldset) 437 if (test_thread_flag(TIF_RESTORE_SIGMASK))
438 oldset = &current->saved_sigmask;
439 else
466 oldset = &current->blocked; 440 oldset = &current->blocked;
467 441
468 /* Are we from a system call? */ 442 /* Are we from a system call? */
@@ -473,12 +447,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
473 447
474 /* Prepare for system call restart. We do this here so that a 448 /* Prepare for system call restart. We do this here so that a
475 debugger will see the already changed PSW. */ 449 debugger will see the already changed PSW. */
476 if (retval == -ERESTARTNOHAND || 450 switch (retval) {
477 retval == -ERESTARTSYS || 451 case -ERESTARTNOHAND:
478 retval == -ERESTARTNOINTR) { 452 case -ERESTARTSYS:
453 case -ERESTARTNOINTR:
479 regs->gprs[2] = regs->orig_gpr2; 454 regs->gprs[2] = regs->orig_gpr2;
480 regs->psw.addr = restart_addr; 455 regs->psw.addr = restart_addr;
481 } else if (retval == -ERESTART_RESTARTBLOCK) { 456 break;
457 case -ERESTART_RESTARTBLOCK:
482 regs->gprs[2] = -EINTR; 458 regs->gprs[2] = -EINTR;
483 } 459 }
484 } 460 }
@@ -503,17 +479,38 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
503 /* Whee! Actually deliver the signal. */ 479 /* Whee! Actually deliver the signal. */
504#ifdef CONFIG_COMPAT 480#ifdef CONFIG_COMPAT
505 if (test_thread_flag(TIF_31BIT)) { 481 if (test_thread_flag(TIF_31BIT)) {
506 extern void handle_signal32(unsigned long sig, 482 extern int handle_signal32(unsigned long sig,
507 struct k_sigaction *ka, 483 struct k_sigaction *ka,
508 siginfo_t *info, 484 siginfo_t *info,
509 sigset_t *oldset, 485 sigset_t *oldset,
510 struct pt_regs *regs); 486 struct pt_regs *regs);
511 handle_signal32(signr, &ka, &info, oldset, regs); 487 if (handle_signal32(
512 return 1; 488 signr, &ka, &info, oldset, regs) == 0) {
489 if (test_thread_flag(TIF_RESTORE_SIGMASK))
490 clear_thread_flag(TIF_RESTORE_SIGMASK);
491 }
492 return;
513 } 493 }
514#endif 494#endif
515 handle_signal(signr, &ka, &info, oldset, regs); 495 if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
516 return 1; 496 /*
497 * A signal was successfully delivered; the saved
498 * sigmask will have been stored in the signal frame,
499 * and will be restored by sigreturn, so we can simply
500 * clear the TIF_RESTORE_SIGMASK flag.
501 */
502 if (test_thread_flag(TIF_RESTORE_SIGMASK))
503 clear_thread_flag(TIF_RESTORE_SIGMASK);
504 }
505 return;
506 }
507
508 /*
509 * If there's no signal to deliver, we just put the saved sigmask back.
510 */
511 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
512 clear_thread_flag(TIF_RESTORE_SIGMASK);
513 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
517 } 514 }
518 515
519 /* Restart a different system call. */ 516 /* Restart a different system call. */
@@ -522,5 +519,4 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
522 regs->gprs[2] = __NR_restart_syscall; 519 regs->gprs[2] = __NR_restart_syscall;
523 set_thread_flag(TIF_RESTART_SVC); 520 set_thread_flag(TIF_RESTART_SVC);
524 } 521 }
525 return 0;
526} 522}