diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-02-15 06:40:37 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-02-18 16:31:35 -0500 |
commit | 151fd6acd94e12ef3a7d5fa0911a2590690c493f (patch) | |
tree | 33623a4cf6c6ce7c134f3cc5624dbcac26817238 /arch/mips/kernel/signal32.c | |
parent | 38201fb23cd554f942702cd938c3215a76296c87 (diff) |
[MIPS] signals: Share even more code.
native and compat do_signal and handle_signal are identical and can easily
be unified.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 118 |
1 files changed, 11 insertions, 107 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 9f829f63024b..02062fc59f77 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -104,7 +104,7 @@ typedef struct compat_siginfo { | |||
104 | */ | 104 | */ |
105 | #define __NR_O32_sigreturn 4119 | 105 | #define __NR_O32_sigreturn 4119 |
106 | #define __NR_O32_rt_sigreturn 4193 | 106 | #define __NR_O32_rt_sigreturn 4193 |
107 | #define __NR_O32_restart_syscall 4253 | 107 | #define __NR_O32_restart_syscall 4253 |
108 | 108 | ||
109 | /* 32-bit compatibility types */ | 109 | /* 32-bit compatibility types */ |
110 | 110 | ||
@@ -598,7 +598,7 @@ badframe: | |||
598 | force_sig(SIGSEGV, current); | 598 | force_sig(SIGSEGV, current); |
599 | } | 599 | } |
600 | 600 | ||
601 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 601 | static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
602 | int signr, sigset_t *set) | 602 | int signr, sigset_t *set) |
603 | { | 603 | { |
604 | struct sigframe32 __user *frame; | 604 | struct sigframe32 __user *frame; |
@@ -644,7 +644,7 @@ give_sigsegv: | |||
644 | return -EFAULT; | 644 | return -EFAULT; |
645 | } | 645 | } |
646 | 646 | ||
647 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 647 | static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
648 | int signr, sigset_t *set, siginfo_t *info) | 648 | int signr, sigset_t *set, siginfo_t *info) |
649 | { | 649 | { |
650 | struct rt_sigframe32 __user *frame; | 650 | struct rt_sigframe32 __user *frame; |
@@ -704,110 +704,14 @@ give_sigsegv: | |||
704 | return -EFAULT; | 704 | return -EFAULT; |
705 | } | 705 | } |
706 | 706 | ||
707 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 707 | /* |
708 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) | 708 | * o32 compatibility on 64-bit kernels, without DSP ASE |
709 | { | 709 | */ |
710 | int ret; | 710 | struct mips_abi mips_abi_32 = { |
711 | 711 | .setup_frame = setup_frame_32, | |
712 | switch (regs->regs[0]) { | 712 | .setup_rt_frame = setup_rt_frame_32, |
713 | case ERESTART_RESTARTBLOCK: | 713 | .restart = __NR_O32_restart_syscall |
714 | case ERESTARTNOHAND: | 714 | }; |
715 | regs->regs[2] = EINTR; | ||
716 | break; | ||
717 | case ERESTARTSYS: | ||
718 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
719 | regs->regs[2] = EINTR; | ||
720 | break; | ||
721 | } | ||
722 | /* fallthrough */ | ||
723 | case ERESTARTNOINTR: /* Userland will reload $v0. */ | ||
724 | regs->regs[7] = regs->regs[26]; | ||
725 | regs->cp0_epc -= 8; | ||
726 | } | ||
727 | |||
728 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
729 | |||
730 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
731 | ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); | ||
732 | else | ||
733 | ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); | ||
734 | |||
735 | spin_lock_irq(¤t->sighand->siglock); | ||
736 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
737 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
738 | sigaddset(¤t->blocked,sig); | ||
739 | recalc_sigpending(); | ||
740 | spin_unlock_irq(¤t->sighand->siglock); | ||
741 | |||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | void do_signal32(struct pt_regs *regs) | ||
746 | { | ||
747 | struct k_sigaction ka; | ||
748 | sigset_t *oldset; | ||
749 | siginfo_t info; | ||
750 | int signr; | ||
751 | |||
752 | /* | ||
753 | * We want the common case to go fast, which is why we may in certain | ||
754 | * cases get here from kernel mode. Just return without doing anything | ||
755 | * if so. | ||
756 | */ | ||
757 | if (!user_mode(regs)) | ||
758 | return; | ||
759 | |||
760 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
761 | oldset = ¤t->saved_sigmask; | ||
762 | else | ||
763 | oldset = ¤t->blocked; | ||
764 | |||
765 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
766 | if (signr > 0) { | ||
767 | /* Whee! Actually deliver the signal. */ | ||
768 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||
769 | /* | ||
770 | * A signal was successfully delivered; the saved | ||
771 | * sigmask will have been stored in the signal frame, | ||
772 | * and will be restored by sigreturn, so we can simply | ||
773 | * clear the TIF_RESTORE_SIGMASK flag. | ||
774 | */ | ||
775 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
776 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
777 | } | ||
778 | |||
779 | return; | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Who's code doesn't conform to the restartable syscall convention | ||
784 | * dies here!!! The li instruction, a single machine instruction, | ||
785 | * must directly be followed by the syscall instruction. | ||
786 | */ | ||
787 | if (regs->regs[0]) { | ||
788 | if (regs->regs[2] == ERESTARTNOHAND || | ||
789 | regs->regs[2] == ERESTARTSYS || | ||
790 | regs->regs[2] == ERESTARTNOINTR) { | ||
791 | regs->regs[7] = regs->regs[26]; | ||
792 | regs->cp0_epc -= 8; | ||
793 | } | ||
794 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | ||
795 | regs->regs[2] = __NR_O32_restart_syscall; | ||
796 | regs->regs[7] = regs->regs[26]; | ||
797 | regs->cp0_epc -= 4; | ||
798 | } | ||
799 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * If there's no signal to deliver, we just put the saved sigmask | ||
804 | * back | ||
805 | */ | ||
806 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
807 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
808 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
809 | } | ||
810 | } | ||
811 | 715 | ||
812 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, | 716 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, |
813 | struct sigaction32 __user *oact, | 717 | struct sigaction32 __user *oact, |