diff options
Diffstat (limited to 'arch/ia64/kernel/signal.c')
-rw-r--r-- | arch/ia64/kernel/signal.c | 71 |
1 files changed, 23 insertions, 48 deletions
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 0dcd56da6001..aeec8184e862 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -40,47 +40,6 @@ | |||
40 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) | 40 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | long | ||
44 | ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) | ||
45 | { | ||
46 | sigset_t oldset, set; | ||
47 | |||
48 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
49 | if (sigsetsize != sizeof(sigset_t)) | ||
50 | return -EINVAL; | ||
51 | |||
52 | if (!access_ok(VERIFY_READ, uset, sigsetsize)) | ||
53 | return -EFAULT; | ||
54 | |||
55 | if (GET_SIGSET(&set, uset)) | ||
56 | return -EFAULT; | ||
57 | |||
58 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
59 | |||
60 | spin_lock_irq(¤t->sighand->siglock); | ||
61 | { | ||
62 | oldset = current->blocked; | ||
63 | current->blocked = set; | ||
64 | recalc_sigpending(); | ||
65 | } | ||
66 | spin_unlock_irq(¤t->sighand->siglock); | ||
67 | |||
68 | /* | ||
69 | * The return below usually returns to the signal handler. We need to | ||
70 | * pre-set the correct error code here to ensure that the right values | ||
71 | * get saved in sigcontext by ia64_do_signal. | ||
72 | */ | ||
73 | scr->pt.r8 = EINTR; | ||
74 | scr->pt.r10 = -1; | ||
75 | |||
76 | while (1) { | ||
77 | current->state = TASK_INTERRUPTIBLE; | ||
78 | schedule(); | ||
79 | if (ia64_do_signal(&oldset, scr, 1)) | ||
80 | return -EINTR; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | asmlinkage long | 43 | asmlinkage long |
85 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, | 44 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, |
86 | long arg3, long arg4, long arg5, long arg6, long arg7, | 45 | long arg3, long arg4, long arg5, long arg6, long arg7, |
@@ -477,10 +436,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse | |||
477 | * Note that `init' is a special process: it doesn't get signals it doesn't want to | 436 | * Note that `init' is a special process: it doesn't get signals it doesn't want to |
478 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. | 437 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. |
479 | */ | 438 | */ |
480 | long | 439 | void |
481 | ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 440 | ia64_do_signal (struct sigscratch *scr, long in_syscall) |
482 | { | 441 | { |
483 | struct k_sigaction ka; | 442 | struct k_sigaction ka; |
443 | sigset_t *oldset; | ||
484 | siginfo_t info; | 444 | siginfo_t info; |
485 | long restart = in_syscall; | 445 | long restart = in_syscall; |
486 | long errno = scr->pt.r8; | 446 | long errno = scr->pt.r8; |
@@ -492,9 +452,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
492 | * doing anything if so. | 452 | * doing anything if so. |
493 | */ | 453 | */ |
494 | if (!user_mode(&scr->pt)) | 454 | if (!user_mode(&scr->pt)) |
495 | return 0; | 455 | return; |
496 | 456 | ||
497 | if (!oldset) | 457 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
458 | oldset = ¤t->saved_sigmask; | ||
459 | else | ||
498 | oldset = ¤t->blocked; | 460 | oldset = ¤t->blocked; |
499 | 461 | ||
500 | /* | 462 | /* |
@@ -557,8 +519,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
557 | * Whee! Actually deliver the signal. If the delivery failed, we need to | 519 | * Whee! Actually deliver the signal. If the delivery failed, we need to |
558 | * continue to iterate in this loop so we can deliver the SIGSEGV... | 520 | * continue to iterate in this loop so we can deliver the SIGSEGV... |
559 | */ | 521 | */ |
560 | if (handle_signal(signr, &ka, &info, oldset, scr)) | 522 | if (handle_signal(signr, &ka, &info, oldset, scr)) { |
561 | return 1; | 523 | /* a signal was successfully delivered; the saved |
524 | * sigmask will have been stored in the signal frame, | ||
525 | * and will be restored by sigreturn, so we can simply | ||
526 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
527 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
528 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
529 | return; | ||
530 | } | ||
562 | } | 531 | } |
563 | 532 | ||
564 | /* Did we come from a system call? */ | 533 | /* Did we come from a system call? */ |
@@ -584,5 +553,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
584 | } | 553 | } |
585 | } | 554 | } |
586 | } | 555 | } |
587 | return 0; | 556 | |
557 | /* if there's no signal to deliver, we just put the saved sigmask | ||
558 | * back */ | ||
559 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
560 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
561 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
562 | } | ||
588 | } | 563 | } |