diff options
Diffstat (limited to 'arch/cris/arch-v10/kernel/signal.c')
| -rw-r--r-- | arch/cris/arch-v10/kernel/signal.c | 128 |
1 files changed, 18 insertions, 110 deletions
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index b6be705c2a3..61ce6273a89 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -27,11 +27,10 @@ #include <asm/processor.h> #include <asm/ucontext.h> #include <asm/uaccess.h> +#include <arch/system.h> #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ /* manipulate regs so that upon return, it will be re-executed */ @@ -43,63 +42,6 @@ void do_signal(int canrestart, struct pt_regs *regs); /* - * Atomically swap in the new signal mask, and wait for a signal. Define - * dummy arguments to be able to reach the regs argument. (Note that this - * arrangement relies on old_sigset_t occupying one register.) - */ -int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, - long srp, struct pt_regs *regs) -{ - 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; -} - -int sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -int sys_sigaltstack(const stack_t *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, rdusp()); -} - - -/* * Do a signal return; undo the signal stack. */ @@ -159,11 +101,9 @@ badframe: return 1; } -/* Define dummy arguments to be able to reach the regs argument. */ - -asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, - long srp, struct pt_regs *regs) +asmlinkage int sys_sigreturn(void) { + struct pt_regs *regs = current_pt_regs(); struct sigframe __user *frame = (struct sigframe *)rdusp(); sigset_t set; @@ -183,11 +123,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, sizeof(frame->extramask)))) goto badframe; - 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(regs, &frame->sc)) goto badframe; @@ -201,11 +137,9 @@ badframe: return 0; } -/* Define dummy arguments to be able to reach the regs argument. */ - -asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, - long mof, long srp, struct pt_regs *regs) +asmlinkage int sys_rt_sigreturn(void) { + struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp(); sigset_t set; @@ -222,16 +156,12 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - 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(regs, &frame->uc.uc_mcontext)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return regs->r10; @@ -379,6 +309,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + err |= __save_altstack(&frame->uc.uc_stack, rdusp()); + if (err) goto give_sigsegv; @@ -428,10 +360,11 @@ give_sigsegv: * OK, we're invoking a handler */ -static inline int handle_signal(int canrestart, unsigned long sig, +static inline void handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - sigset_t *oldset, struct pt_regs *regs) + struct pt_regs *regs) { + sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -468,16 +401,8 @@ static inline int handle_signal(int canrestart, unsigned long sig, else ret = setup_frame(sig, ka, oldset, regs); - 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); - } - return ret; + if (ret == 0) + signal_delivered(sig, info, ka, regs, 0); } /* @@ -497,7 +422,6 @@ void do_signal(int canrestart, struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; - sigset_t *oldset; /* * We want the common case to go fast, which @@ -508,23 +432,10 @@ void do_signal(int canrestart, struct pt_regs *regs) if (!user_mode(regs)) return; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - if (handle_signal(canrestart, signr, &info, &ka, - oldset, regs)) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } + handle_signal(canrestart, signr, &info, &ka, regs); return; } @@ -537,15 +448,12 @@ void do_signal(int canrestart, struct pt_regs *regs) RESTART_CRIS_SYS(regs); } if (regs->r10 == -ERESTART_RESTARTBLOCK) { - regs->r10 = __NR_restart_syscall; + regs->r9 = __NR_restart_syscall; regs->irp -= 2; } } /* if there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + restore_saved_sigmask(); } |
