diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-07-10 14:22:03 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2011-07-15 00:22:11 -0400 |
commit | 9b429620740945363b746414e8b9a84b8119914c (patch) | |
tree | a977c052d347f885589b9994dd74141edb761eb1 | |
parent | 3982294b0342474ff91472b34c6afb701785f524 (diff) |
x86, do_signal: Simplify the TS_RESTORE_SIGMASK logic
1. do_signal() looks at TS_RESTORE_SIGMASK and calculates the
mask which should be stored in the signal frame, then it
passes "oldset" to the callees, down to setup_rt_frame().
This is ugly, setup_rt_frame() can do this itself and nobody
else needs this sigset_t. Move this code into setup_rt_frame.
2. do_signal() also clears TS_RESTORE_SIGMASK if handle_signal()
succeeds.
We can move this to setup_rt_frame() as well, this avoids the
unnecessary checks and makes the logic more clear.
3. use set_current_blocked() instead of sigprocmask(SIG_SETMASK),
sigprocmask() should be avoided.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Link: http://lkml.kernel.org/r/20110710182203.GA27979@redhat.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | arch/x86/kernel/signal.c | 29 |
1 files changed, 10 insertions, 19 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index bf9345da380b..8c55f97728cd 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -651,11 +651,15 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
651 | 651 | ||
652 | static int | 652 | static int |
653 | 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, |
654 | sigset_t *set, struct pt_regs *regs) | 654 | struct pt_regs *regs) |
655 | { | 655 | { |
656 | int usig = signr_convert(sig); | 656 | int usig = signr_convert(sig); |
657 | sigset_t *set = ¤t->blocked; | ||
657 | int ret; | 658 | int ret; |
658 | 659 | ||
660 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | ||
661 | set = ¤t->saved_sigmask; | ||
662 | |||
659 | /* Set up the stack frame */ | 663 | /* Set up the stack frame */ |
660 | if (is_ia32) { | 664 | if (is_ia32) { |
661 | if (ka->sa.sa_flags & SA_SIGINFO) | 665 | if (ka->sa.sa_flags & SA_SIGINFO) |
@@ -670,12 +674,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
670 | return -EFAULT; | 674 | return -EFAULT; |
671 | } | 675 | } |
672 | 676 | ||
677 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | ||
673 | return ret; | 678 | return ret; |
674 | } | 679 | } |
675 | 680 | ||
676 | static int | 681 | static int |
677 | 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, |
678 | sigset_t *oldset, struct pt_regs *regs) | 683 | struct pt_regs *regs) |
679 | { | 684 | { |
680 | sigset_t blocked; | 685 | sigset_t blocked; |
681 | int ret; | 686 | int ret; |
@@ -710,7 +715,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
710 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 715 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
711 | regs->flags &= ~X86_EFLAGS_TF; | 716 | regs->flags &= ~X86_EFLAGS_TF; |
712 | 717 | ||
713 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 718 | ret = setup_rt_frame(sig, ka, info, regs); |
714 | 719 | ||
715 | if (ret) | 720 | if (ret) |
716 | return ret; | 721 | return ret; |
@@ -765,7 +770,6 @@ static void do_signal(struct pt_regs *regs) | |||
765 | struct k_sigaction ka; | 770 | struct k_sigaction ka; |
766 | siginfo_t info; | 771 | siginfo_t info; |
767 | int signr; | 772 | int signr; |
768 | sigset_t *oldset; | ||
769 | 773 | ||
770 | /* | 774 | /* |
771 | * We want the common case to go fast, which is why we may in certain | 775 | * We want the common case to go fast, which is why we may in certain |
@@ -777,23 +781,10 @@ static void do_signal(struct pt_regs *regs) | |||
777 | if (!user_mode(regs)) | 781 | if (!user_mode(regs)) |
778 | return; | 782 | return; |
779 | 783 | ||
780 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | ||
781 | oldset = ¤t->saved_sigmask; | ||
782 | else | ||
783 | oldset = ¤t->blocked; | ||
784 | |||
785 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 784 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
786 | if (signr > 0) { | 785 | if (signr > 0) { |
787 | /* Whee! Actually deliver the signal. */ | 786 | /* Whee! Actually deliver the signal. */ |
788 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 787 | handle_signal(signr, &info, &ka, regs); |
789 | /* | ||
790 | * A signal was successfully delivered; the saved | ||
791 | * sigmask will have been stored in the signal frame, | ||
792 | * and will be restored by sigreturn, so we can simply | ||
793 | * clear the TS_RESTORE_SIGMASK flag. | ||
794 | */ | ||
795 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | ||
796 | } | ||
797 | return; | 788 | return; |
798 | } | 789 | } |
799 | 790 | ||
@@ -821,7 +812,7 @@ static void do_signal(struct pt_regs *regs) | |||
821 | */ | 812 | */ |
822 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { | 813 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) { |
823 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 814 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
824 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 815 | set_current_blocked(¤t->saved_sigmask); |
825 | } | 816 | } |
826 | } | 817 | } |
827 | 818 | ||