diff options
Diffstat (limited to 'arch/alpha/kernel/signal.c')
-rw-r--r-- | arch/alpha/kernel/signal.c | 93 |
1 files changed, 21 insertions, 72 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 6f7feb5db271..a8c97d42ec8e 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -34,9 +34,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage void ret_from_sys_call(void); -static void do_signal(struct pt_regs *, struct switch_stack *, - unsigned long, unsigned long); - /* * The OSF/1 sigprocmask calling sequence is different from the @@ -120,17 +117,9 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, */ SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) { - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); } asmlinkage int @@ -237,11 +226,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, if (__get_user(set.sig[0], &sc->sc_mask)) goto give_sigsegv; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(sc, regs, sw)) goto give_sigsegv; @@ -275,11 +260,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) goto give_sigsegv; @@ -381,11 +362,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ @@ -401,7 +382,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, /* Check that everything was written properly. */ if (err) - goto give_sigsegv; + return err; /* "Return" to the handler */ regs->r26 = r26; @@ -415,12 +396,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->pc, regs->r26); #endif - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } static int @@ -433,7 +409,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return -EFAULT; err |= copy_siginfo_to_user(&frame->info, info); @@ -448,7 +424,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, set->sig[0], oldsp); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) - goto give_sigsegv; + return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ @@ -464,7 +440,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } if (err) - goto give_sigsegv; + return -EFAULT; /* "Return" to the handler */ regs->r26 = r26; @@ -480,20 +456,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, #endif return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; } /* * OK, we're invoking a handler. */ -static inline int +static inline void handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) + struct pt_regs * regs, struct switch_stack *sw) { + sigset_t *oldset = sigmask_to_save(); int ret; if (ka->sa.sa_flags & SA_SIGINFO) @@ -501,16 +474,11 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, else ret = setup_frame(sig, ka, oldset, regs, sw); - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + if (ret) { + force_sigsegv(sig, current); + return; } - - return ret; + signal_delivered(sig, info, ka, regs, 0); } static inline void @@ -558,12 +526,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, int signr; unsigned long single_stepping = ptrace_cancel_bpt(current); struct k_sigaction ka; - sigset_t *oldset; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; /* This lets the debugger run, ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -575,14 +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); - if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { - /* A signal was successfully delivered, and the - saved sigmask was stored on the signal frame, - and will be restored by sigreturn. So we can - simply clear the restore sigmask flag. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } + handle_signal(signr, &ka, &info, regs, sw); if (single_stepping) ptrace_set_bpt(current); /* re-set bpt */ return; @@ -607,11 +562,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, } /* If there's no signal to deliver, we just restore the saved mask. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - + restore_saved_sigmask(); if (single_stepping) ptrace_set_bpt(current); /* re-set breakpoint */ } @@ -621,13 +572,11 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, unsigned long thread_info_flags, unsigned long r0, unsigned long r19) { - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + 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); - if (current->replacement_session_keyring) - key_replace_session_keyring(); } } |