From 6972d6f25d21e3da58ff1309256c787078405c7f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Sep 2012 18:30:34 -0400 Subject: alpha: take SIGPENDING/NOTIFY_RESUME loop into signal.c Turn the slow side of work_pending into C function, including all the looping. What we get out of that: * we do _not_ call get_signal_to_deliver() with IRQs disabled anymore * no need to save/restore volatiles on each pass if there turns to be more than one (unlikely, but still) * all double-restart prevention is in C now. * glue gets simpler. Signed-off-by: Al Viro --- arch/alpha/kernel/signal.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'arch/alpha/kernel/signal.c') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index a8c97d42ec8..235a8677eca 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -568,15 +568,24 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, } void -do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, - unsigned long thread_info_flags, +do_work_pending(struct pt_regs *regs, struct switch_stack *sw, + unsigned long thread_flags, unsigned long r0, unsigned long r19) { - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs, sw, r0, r19); - - if (thread_info_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } + do { + if (thread_flags & _TIF_NEED_RESCHED) { + schedule(); + } else { + local_irq_enable(); + if (thread_flags & _TIF_SIGPENDING) { + do_signal(regs, sw, r0, r19); + r0 = 0; + } else { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + } + local_irq_disable(); + thread_flags = current_thread_info()->flags; + } while (thread_flags & _TIF_WORK_MASK); } -- cgit v1.2.3 From d9d0738a898dd26a417d00a6923eef1015d33735 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Sep 2012 18:53:18 -0400 Subject: alpha: don't bother passing switch_stack separately from regs It's needed only in setup_sigcontext() and it's always reg - ; no point passing it all way down through the call chain. This is just the signal.c side of that stuff; next will come the asm glue one... Signed-off-by: Al Viro --- arch/alpha/kernel/signal.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'arch/alpha/kernel/signal.c') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 235a8677eca..d0b3507ec6b 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -298,8 +298,9 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - struct switch_stack *sw, unsigned long mask, unsigned long sp) + unsigned long mask, unsigned long sp) { + struct switch_stack *sw = (struct switch_stack *)regs - 1; long i, err = 0; err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); @@ -354,7 +355,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, - struct pt_regs *regs, struct switch_stack * sw) + struct pt_regs *regs) { unsigned long oldsp, r26, err = 0; struct sigframe __user *frame; @@ -364,7 +365,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); + err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp); if (err) return -EFAULT; @@ -401,7 +402,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) + sigset_t *set, struct pt_regs *regs) { unsigned long oldsp, r26, err = 0; struct rt_sigframe __user *frame; @@ -420,7 +421,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], oldsp); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) @@ -464,15 +465,15 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, */ static inline void handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, - struct pt_regs * regs, struct switch_stack *sw) + struct pt_regs * regs) { sigset_t *oldset = sigmask_to_save(); int ret; if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); + ret = setup_rt_frame(sig, ka, info, oldset, regs); else - ret = setup_frame(sig, ka, oldset, regs, sw); + ret = setup_frame(sig, ka, oldset, regs); if (ret) { force_sigsegv(sig, current); @@ -519,8 +520,7 @@ syscall_restart(unsigned long r0, unsigned long r19, * all (if we get here from anything but a syscall return, it will be 0) */ static void -do_signal(struct pt_regs * regs, struct switch_stack * sw, - unsigned long r0, unsigned long r19) +do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) { siginfo_t info; int signr; @@ -537,7 +537,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, /* Whee! Actually deliver the signal. */ if (r0) syscall_restart(r0, r19, regs, &ka); - handle_signal(signr, &ka, &info, regs, sw); + handle_signal(signr, &ka, &info, regs); if (single_stepping) ptrace_set_bpt(current); /* re-set bpt */ return; @@ -568,7 +568,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, } void -do_work_pending(struct pt_regs *regs, struct switch_stack *sw, +do_work_pending(struct pt_regs *regs, struct switch_stack *unused, unsigned long thread_flags, unsigned long r0, unsigned long r19) { @@ -578,7 +578,7 @@ do_work_pending(struct pt_regs *regs, struct switch_stack *sw, } else { local_irq_enable(); if (thread_flags & _TIF_SIGPENDING) { - do_signal(regs, sw, r0, r19); + do_signal(regs, r0, r19); r0 = 0; } else { clear_thread_flag(TIF_NOTIFY_RESUME); -- cgit v1.2.3 From cb450766bcafc7bd7d40e9a5a0050745e8c68b3e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Oct 2012 23:50:59 -0400 Subject: alpha: get rid of switch_stack argument of do_work_pending() ... and now the asm glue side of that. Signed-off-by: Al Viro --- arch/alpha/kernel/signal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/alpha/kernel/signal.c') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index d0b3507ec6b..32575f85507 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -568,8 +568,7 @@ do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) } void -do_work_pending(struct pt_regs *regs, struct switch_stack *unused, - unsigned long thread_flags, +do_work_pending(struct pt_regs *regs, unsigned long thread_flags, unsigned long r0, unsigned long r19) { do { -- cgit v1.2.3 From b960f303448969c6cb76b4df9291e9e6213e2b9f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 18 Oct 2012 01:43:27 -0400 Subject: alpha: don't pass useless arguments to do_{,rt_},sigreturn() Signed-off-by: Al Viro --- arch/alpha/kernel/signal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/alpha/kernel/signal.c') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 32575f85507..336393c9c11 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -160,10 +160,10 @@ extern char compile_time_assert #define INSN_CALLSYS 0x00000083 static long -restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - struct switch_stack *sw) +restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) { unsigned long usp; + struct switch_stack *sw = (struct switch_stack *)regs - 1; long i, err = __get_user(regs->pc, &sc->sc_pc); current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, registers and transfer control from userland. */ asmlinkage void -do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, - struct switch_stack *sw) +do_sigreturn(struct sigcontext __user *sc) { + struct pt_regs *regs = current_pt_regs(); sigset_t set; /* Verify that it's a good sigcontext before using it */ @@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, set_current_blocked(&set); - if (restore_sigcontext(sc, regs, sw)) + if (restore_sigcontext(sc, regs)) goto give_sigsegv; /* Send SIGTRAP if we're single-stepping: */ @@ -249,9 +249,9 @@ give_sigsegv: } asmlinkage void -do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, - struct switch_stack *sw) +do_rt_sigreturn(struct rt_sigframe __user *frame) { + struct pt_regs *regs = current_pt_regs(); sigset_t set; /* Verify that it's a good ucontext_t before using it */ @@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, set_current_blocked(&set); - if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) + if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) goto give_sigsegv; /* Send SIGTRAP if we're single-stepping: */ -- cgit v1.2.3 From 50ececcfa7d1acee085b2c518cad495062db6379 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 14 Dec 2012 15:25:43 -0500 Subject: alpha: switch to generic sigaltstack Signed-off-by: Al Viro --- arch/alpha/kernel/signal.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'arch/alpha/kernel/signal.c') diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 336393c9c11..02d02c047f1 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -122,12 +122,6 @@ SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) return sigsuspend(&blocked); } -asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, rdusp()); -} - /* * Do a signal return; undo the signal stack. */ @@ -418,9 +412,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= __save_altstack(&frame->uc.uc_stack, oldsp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], oldsp); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); -- cgit v1.2.3