diff options
author | Alexey Dobriyan <adobriyan@openvz.org> | 2007-01-23 11:03:17 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-05-08 17:51:59 -0400 |
commit | 4a177cbf84f827cf9f1d6cfa5264fafd3cc33ce0 (patch) | |
tree | ef04ada4e2b708ee965081cd905026c9156863d3 /arch/ia64/kernel/signal.c | |
parent | 690def21414fa43fac1b8053fd952c0366c476de (diff) |
[IA64] Add TIF_RESTORE_SIGMASK
Preparation for pselect and ppoll.
ia32 compat code not tested. :-(
Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
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 77f8b49c7882..034b81d62bb1 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -41,47 +41,6 @@ | |||
41 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) | 41 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | long | ||
45 | ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) | ||
46 | { | ||
47 | sigset_t oldset, set; | ||
48 | |||
49 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
50 | if (sigsetsize != sizeof(sigset_t)) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (!access_ok(VERIFY_READ, uset, sigsetsize)) | ||
54 | return -EFAULT; | ||
55 | |||
56 | if (GET_SIGSET(&set, uset)) | ||
57 | return -EFAULT; | ||
58 | |||
59 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
60 | |||
61 | spin_lock_irq(¤t->sighand->siglock); | ||
62 | { | ||
63 | oldset = current->blocked; | ||
64 | current->blocked = set; | ||
65 | recalc_sigpending(); | ||
66 | } | ||
67 | spin_unlock_irq(¤t->sighand->siglock); | ||
68 | |||
69 | /* | ||
70 | * The return below usually returns to the signal handler. We need to | ||
71 | * pre-set the correct error code here to ensure that the right values | ||
72 | * get saved in sigcontext by ia64_do_signal. | ||
73 | */ | ||
74 | scr->pt.r8 = EINTR; | ||
75 | scr->pt.r10 = -1; | ||
76 | |||
77 | while (1) { | ||
78 | current->state = TASK_INTERRUPTIBLE; | ||
79 | schedule(); | ||
80 | if (ia64_do_signal(&oldset, scr, 1)) | ||
81 | return -EINTR; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | asmlinkage long | 44 | asmlinkage long |
86 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, | 45 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, |
87 | long arg3, long arg4, long arg5, long arg6, long arg7, | 46 | long arg3, long arg4, long arg5, long arg6, long arg7, |
@@ -478,10 +437,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse | |||
478 | * Note that `init' is a special process: it doesn't get signals it doesn't want to | 437 | * Note that `init' is a special process: it doesn't get signals it doesn't want to |
479 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. | 438 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. |
480 | */ | 439 | */ |
481 | long | 440 | void |
482 | ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 441 | ia64_do_signal (struct sigscratch *scr, long in_syscall) |
483 | { | 442 | { |
484 | struct k_sigaction ka; | 443 | struct k_sigaction ka; |
444 | sigset_t *oldset; | ||
485 | siginfo_t info; | 445 | siginfo_t info; |
486 | long restart = in_syscall; | 446 | long restart = in_syscall; |
487 | long errno = scr->pt.r8; | 447 | long errno = scr->pt.r8; |
@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
493 | * doing anything if so. | 453 | * doing anything if so. |
494 | */ | 454 | */ |
495 | if (!user_mode(&scr->pt)) | 455 | if (!user_mode(&scr->pt)) |
496 | return 0; | 456 | return; |
497 | 457 | ||
498 | if (!oldset) | 458 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
459 | oldset = ¤t->saved_sigmask; | ||
460 | else | ||
499 | oldset = ¤t->blocked; | 461 | oldset = ¤t->blocked; |
500 | 462 | ||
501 | /* | 463 | /* |
@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
558 | * Whee! Actually deliver the signal. If the delivery failed, we need to | 520 | * Whee! Actually deliver the signal. If the delivery failed, we need to |
559 | * continue to iterate in this loop so we can deliver the SIGSEGV... | 521 | * continue to iterate in this loop so we can deliver the SIGSEGV... |
560 | */ | 522 | */ |
561 | if (handle_signal(signr, &ka, &info, oldset, scr)) | 523 | if (handle_signal(signr, &ka, &info, oldset, scr)) { |
562 | return 1; | 524 | /* a signal was successfully delivered; the saved |
525 | * sigmask will have been stored in the signal frame, | ||
526 | * and will be restored by sigreturn, so we can simply | ||
527 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
528 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
529 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
530 | return; | ||
531 | } | ||
563 | } | 532 | } |
564 | 533 | ||
565 | /* Did we come from a system call? */ | 534 | /* Did we come from a system call? */ |
@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
585 | } | 554 | } |
586 | } | 555 | } |
587 | } | 556 | } |
588 | return 0; | 557 | |
558 | /* if there's no signal to deliver, we just put the saved sigmask | ||
559 | * back */ | ||
560 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
561 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
562 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
563 | } | ||
589 | } | 564 | } |