diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 20:04:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 20:04:32 -0400 |
commit | 805120795947008612ef64618bba8a6aa30cf88b (patch) | |
tree | 229acb76bfddb595f4d8b215637e12d911c1727d | |
parent | 9e39264ed4f687251632c0a6f4a70c2e51719662 (diff) | |
parent | 73d382deccac186d103496bf10388bc2432a8384 (diff) |
Merge branch 'x86-signal-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-signal-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: Kill handle_signal()->set_fs()
x86, do_signal: Simplify the TS_RESTORE_SIGMASK logic
x86, signals: Convert the X86_32 code to use set_current_blocked()
x86, signals: Convert the IA32_EMULATION code to use set_current_blocked()
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 22 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 56 |
2 files changed, 27 insertions, 51 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 588a7aa937e1..65577698cab2 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -127,15 +127,17 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |||
127 | 127 | ||
128 | asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) | 128 | asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) |
129 | { | 129 | { |
130 | mask &= _BLOCKABLE; | 130 | sigset_t blocked; |
131 | spin_lock_irq(¤t->sighand->siglock); | 131 | |
132 | current->saved_sigmask = current->blocked; | 132 | current->saved_sigmask = current->blocked; |
133 | siginitset(¤t->blocked, mask); | 133 | |
134 | recalc_sigpending(); | 134 | mask &= _BLOCKABLE; |
135 | spin_unlock_irq(¤t->sighand->siglock); | 135 | siginitset(&blocked, mask); |
136 | set_current_blocked(&blocked); | ||
136 | 137 | ||
137 | current->state = TASK_INTERRUPTIBLE; | 138 | current->state = TASK_INTERRUPTIBLE; |
138 | schedule(); | 139 | schedule(); |
140 | |||
139 | set_restore_sigmask(); | 141 | set_restore_sigmask(); |
140 | return -ERESTARTNOHAND; | 142 | return -ERESTARTNOHAND; |
141 | } | 143 | } |
@@ -279,10 +281,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs) | |||
279 | goto badframe; | 281 | goto badframe; |
280 | 282 | ||
281 | sigdelsetmask(&set, ~_BLOCKABLE); | 283 | sigdelsetmask(&set, ~_BLOCKABLE); |
282 | spin_lock_irq(¤t->sighand->siglock); | 284 | set_current_blocked(&set); |
283 | current->blocked = set; | ||
284 | recalc_sigpending(); | ||
285 | spin_unlock_irq(¤t->sighand->siglock); | ||
286 | 285 | ||
287 | if (ia32_restore_sigcontext(regs, &frame->sc, &ax)) | 286 | if (ia32_restore_sigcontext(regs, &frame->sc, &ax)) |
288 | goto badframe; | 287 | goto badframe; |
@@ -308,10 +307,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) | |||
308 | goto badframe; | 307 | goto badframe; |
309 | 308 | ||
310 | sigdelsetmask(&set, ~_BLOCKABLE); | 309 | sigdelsetmask(&set, ~_BLOCKABLE); |
311 | spin_lock_irq(¤t->sighand->siglock); | 310 | set_current_blocked(&set); |
312 | current->blocked = set; | ||
313 | recalc_sigpending(); | ||
314 | spin_unlock_irq(¤t->sighand->siglock); | ||
315 | 311 | ||
316 | if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | 312 | if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
317 | goto badframe; | 313 | goto badframe; |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 40a24932a8a1..54ddaeb221c1 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -485,17 +485,18 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
485 | asmlinkage int | 485 | asmlinkage int |
486 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 486 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
487 | { | 487 | { |
488 | mask &= _BLOCKABLE; | 488 | sigset_t blocked; |
489 | spin_lock_irq(¤t->sighand->siglock); | 489 | |
490 | current->saved_sigmask = current->blocked; | 490 | current->saved_sigmask = current->blocked; |
491 | siginitset(¤t->blocked, mask); | 491 | |
492 | recalc_sigpending(); | 492 | mask &= _BLOCKABLE; |
493 | spin_unlock_irq(¤t->sighand->siglock); | 493 | siginitset(&blocked, mask); |
494 | set_current_blocked(&blocked); | ||
494 | 495 | ||
495 | current->state = TASK_INTERRUPTIBLE; | 496 | current->state = TASK_INTERRUPTIBLE; |
496 | schedule(); | 497 | schedule(); |
497 | set_restore_sigmask(); | ||
498 | 498 | ||
499 | set_restore_sigmask(); | ||
499 | return -ERESTARTNOHAND; | 500 | return -ERESTARTNOHAND; |
500 | } | 501 | } |
501 | 502 | ||
@@ -572,10 +573,7 @@ unsigned long sys_sigreturn(struct pt_regs *regs) | |||
572 | goto badframe; | 573 | goto badframe; |
573 | 574 | ||
574 | sigdelsetmask(&set, ~_BLOCKABLE); | 575 | sigdelsetmask(&set, ~_BLOCKABLE); |
575 | spin_lock_irq(¤t->sighand->siglock); | 576 | set_current_blocked(&set); |
576 | current->blocked = set; | ||
577 | recalc_sigpending(); | ||
578 | spin_unlock_irq(¤t->sighand->siglock); | ||
579 | 577 | ||
580 | if (restore_sigcontext(regs, &frame->sc, &ax)) | 578 | if (restore_sigcontext(regs, &frame->sc, &ax)) |
581 | goto badframe; | 579 | goto badframe; |
@@ -653,11 +651,15 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
653 | 651 | ||
654 | static int | 652 | static int |
655 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 653 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
656 | sigset_t *set, struct pt_regs *regs) | 654 | struct pt_regs *regs) |
657 | { | 655 | { |
658 | int usig = signr_convert(sig); | 656 | int usig = signr_convert(sig); |
657 | sigset_t *set = ¤t->blocked; | ||
659 | int ret; | 658 | int ret; |
660 | 659 | ||
660 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | ||
661 | set = ¤t->saved_sigmask; | ||
662 | |||
661 | /* Set up the stack frame */ | 663 | /* Set up the stack frame */ |
662 | if (is_ia32) { | 664 | if (is_ia32) { |
663 | if (ka->sa.sa_flags & SA_SIGINFO) | 665 | if (ka->sa.sa_flags & SA_SIGINFO) |
@@ -672,12 +674,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
672 | return -EFAULT; | 674 | return -EFAULT; |
673 | } | 675 | } |
674 | 676 | ||
677 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | ||
675 | return ret; | 678 | return ret; |
676 | } | 679 | } |
677 | 680 | ||
678 | static int | 681 | static int |
679 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 682 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
680 | sigset_t *oldset, struct pt_regs *regs) | 683 | struct pt_regs *regs) |
681 | { | 684 | { |
682 | sigset_t blocked; | 685 | sigset_t blocked; |
683 | int ret; | 686 | int ret; |
@@ -712,20 +715,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
712 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 715 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
713 | regs->flags &= ~X86_EFLAGS_TF; | 716 | regs->flags &= ~X86_EFLAGS_TF; |
714 | 717 | ||
715 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 718 | ret = setup_rt_frame(sig, ka, info, regs); |
716 | 719 | ||
717 | if (ret) | 720 | if (ret) |
718 | return ret; | 721 | return ret; |
719 | 722 | ||
720 | #ifdef CONFIG_X86_64 | ||
721 | /* | ||
722 | * This has nothing to do with segment registers, | ||
723 | * despite the name. This magic affects uaccess.h | ||
724 | * macros' behavior. Reset it to the normal setting. | ||
725 | */ | ||
726 | set_fs(USER_DS); | ||
727 | #endif | ||
728 | |||
729 | /* | 723 | /* |
730 | * Clear the direction flag as per the ABI for function entry. | 724 | * Clear the direction flag as per the ABI for function entry. |
731 | */ | 725 | */ |
@@ -767,7 +761,6 @@ static void do_signal(struct pt_regs *regs) | |||
767 | struct k_sigaction ka; | 761 | struct k_sigaction ka; |
768 | siginfo_t info; | 762 | siginfo_t info; |
769 | int signr; | 763 | int signr; |
770 | sigset_t *oldset; | ||
771 | 764 | ||
772 | /* | 765 | /* |
773 | * We want the common case to go fast, which is why we may in certain | 766 | * We want the common case to go fast, which is why we may in certain |
@@ -779,23 +772,10 @@ static void do_signal(struct pt_regs *regs) | |||
779 | if (!user_mode(regs)) | 772 | if (!user_mode(regs)) |
780 | return; | 773 | return; |
781 | 774 | ||
782 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | ||
783 | oldset = ¤t->saved_sigmask; | ||
784 | else | ||
785 | oldset = ¤t->blocked; | ||
786 | |||
787 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 775 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
788 | if (signr > 0) { | 776 | if (signr > 0) { |
789 | /* Whee! Actually deliver the signal. */ | 777 | /* Whee! Actually deliver the signal. */ |
790 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 778 | handle_signal(signr, &info, &ka, regs); |
791 | /* | ||
792 | * A signal was successfully delivered; the saved | ||
793 | * sigmask will have been stored in the signal frame, | ||
794 | * and will be restored by sigreturn, so we can simply | ||
795 | * clear the TS_RESTORE_SIGMASK flag. | ||
796 | */ | ||
797 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | ||
798 | } | ||
799 | return; | 779 | return; |
800 | } | 780 | } |
801 | 781 | ||
@@ -823,7 +803,7 @@ static void do_signal(struct pt_regs *regs) | |||
823 | */ | 803 | */ |
824 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { | 804 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { |
825 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 805 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
826 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 806 | set_current_blocked(¤t->saved_sigmask); |
827 | } | 807 | } |
828 | } | 808 | } |
829 | 809 | ||