aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/signal.c')
-rw-r--r--arch/alpha/kernel/signal.c69
1 files changed, 26 insertions, 43 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 74b05e6ed44..10ab2d74ecb 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -34,9 +34,6 @@
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35 35
36asmlinkage void ret_from_sys_call(void); 36asmlinkage void ret_from_sys_call(void);
37static void do_signal(struct pt_regs *, struct switch_stack *,
38 unsigned long, unsigned long);
39
40 37
41/* 38/*
42 * The OSF/1 sigprocmask calling sequence is different from the 39 * The OSF/1 sigprocmask calling sequence is different from the
@@ -367,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
367 oldsp = rdusp(); 364 oldsp = rdusp();
368 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 365 frame = get_sigframe(ka, oldsp, sizeof(*frame));
369 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 366 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
370 goto give_sigsegv; 367 return -EFAULT;
371 368
372 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); 369 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
373 if (err) 370 if (err)
374 goto give_sigsegv; 371 return -EFAULT;
375 372
376 /* Set up to return from userspace. If provided, use a stub 373 /* Set up to return from userspace. If provided, use a stub
377 already in userspace. */ 374 already in userspace. */
@@ -387,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
387 384
388 /* Check that everything was written properly. */ 385 /* Check that everything was written properly. */
389 if (err) 386 if (err)
390 goto give_sigsegv; 387 return err;
391 388
392 /* "Return" to the handler */ 389 /* "Return" to the handler */
393 regs->r26 = r26; 390 regs->r26 = r26;
@@ -401,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
401 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", 398 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
402 current->comm, current->pid, frame, regs->pc, regs->r26); 399 current->comm, current->pid, frame, regs->pc, regs->r26);
403#endif 400#endif
404
405 return 0; 401 return 0;
406
407give_sigsegv:
408 force_sigsegv(sig, current);
409 return -EFAULT;
410} 402}
411 403
412static int 404static int
@@ -419,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
419 oldsp = rdusp(); 411 oldsp = rdusp();
420 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 412 frame = get_sigframe(ka, oldsp, sizeof(*frame));
421 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 413 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
422 goto give_sigsegv; 414 return -EFAULT;
423 415
424 err |= copy_siginfo_to_user(&frame->info, info); 416 err |= copy_siginfo_to_user(&frame->info, info);
425 417
@@ -434,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
434 set->sig[0], oldsp); 426 set->sig[0], oldsp);
435 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 427 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
436 if (err) 428 if (err)
437 goto give_sigsegv; 429 return -EFAULT;
438 430
439 /* Set up to return from userspace. If provided, use a stub 431 /* Set up to return from userspace. If provided, use a stub
440 already in userspace. */ 432 already in userspace. */
@@ -450,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
450 } 442 }
451 443
452 if (err) 444 if (err)
453 goto give_sigsegv; 445 return -EFAULT;
454 446
455 /* "Return" to the handler */ 447 /* "Return" to the handler */
456 regs->r26 = r26; 448 regs->r26 = r26;
@@ -466,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
466#endif 458#endif
467 459
468 return 0; 460 return 0;
469
470give_sigsegv:
471 force_sigsegv(sig, current);
472 return -EFAULT;
473} 461}
474 462
475 463
476/* 464/*
477 * OK, we're invoking a handler. 465 * OK, we're invoking a handler.
478 */ 466 */
479static inline int 467static inline void
480handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 468handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
481 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) 469 struct pt_regs * regs, struct switch_stack *sw)
482{ 470{
471 sigset_t *oldset = &current->blocked;
483 int ret; 472 int ret;
484 473
474 if (test_thread_flag(TIF_RESTORE_SIGMASK))
475 oldset = &current->saved_sigmask;
476
485 if (ka->sa.sa_flags & SA_SIGINFO) 477 if (ka->sa.sa_flags & SA_SIGINFO)
486 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); 478 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
487 else 479 else
488 ret = setup_frame(sig, ka, oldset, regs, sw); 480 ret = setup_frame(sig, ka, oldset, regs, sw);
489 481
490 if (ret == 0) 482 if (ret) {
491 block_sigmask(ka, sig); 483 force_sigsegv(sig, current);
492 484 return;
493 return ret; 485 }
486 block_sigmask(ka, sig);
487 /* A signal was successfully delivered, and the
488 saved sigmask was stored on the signal frame,
489 and will be restored by sigreturn. So we can
490 simply clear the restore sigmask flag. */
491 clear_thread_flag(TIF_RESTORE_SIGMASK);
494} 492}
495 493
496static inline void 494static inline void
@@ -538,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
538 int signr; 536 int signr;
539 unsigned long single_stepping = ptrace_cancel_bpt(current); 537 unsigned long single_stepping = ptrace_cancel_bpt(current);
540 struct k_sigaction ka; 538 struct k_sigaction ka;
541 sigset_t *oldset;
542
543 if (test_thread_flag(TIF_RESTORE_SIGMASK))
544 oldset = &current->saved_sigmask;
545 else
546 oldset = &current->blocked;
547 539
548 /* This lets the debugger run, ... */ 540 /* This lets the debugger run, ... */
549 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 541 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -555,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
555 /* Whee! Actually deliver the signal. */ 547 /* Whee! Actually deliver the signal. */
556 if (r0) 548 if (r0)
557 syscall_restart(r0, r19, regs, &ka); 549 syscall_restart(r0, r19, regs, &ka);
558 if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { 550 handle_signal(signr, &ka, &info, regs, sw);
559 /* A signal was successfully delivered, and the
560 saved sigmask was stored on the signal frame,
561 and will be restored by sigreturn. So we can
562 simply clear the restore sigmask flag. */
563 if (test_thread_flag(TIF_RESTORE_SIGMASK))
564 clear_thread_flag(TIF_RESTORE_SIGMASK);
565 }
566 if (single_stepping) 551 if (single_stepping)
567 ptrace_set_bpt(current); /* re-set bpt */ 552 ptrace_set_bpt(current); /* re-set bpt */
568 return; 553 return;
@@ -587,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
587 } 572 }
588 573
589 /* If there's no signal to deliver, we just restore the saved mask. */ 574 /* If there's no signal to deliver, we just restore the saved mask. */
590 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 575 if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
591 clear_thread_flag(TIF_RESTORE_SIGMASK); 576 set_current_blocked(&current->saved_sigmask);
592 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
593 }
594 577
595 if (single_stepping) 578 if (single_stepping)
596 ptrace_set_bpt(current); /* re-set breakpoint */ 579 ptrace_set_bpt(current); /* re-set breakpoint */
@@ -601,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
601 unsigned long thread_info_flags, 584 unsigned long thread_info_flags,
602 unsigned long r0, unsigned long r19) 585 unsigned long r0, unsigned long r19)
603{ 586{
604 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 587 if (thread_info_flags & _TIF_SIGPENDING)
605 do_signal(regs, sw, r0, r19); 588 do_signal(regs, sw, r0, r19);
606 589
607 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 590 if (thread_info_flags & _TIF_NOTIFY_RESUME) {