X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Fsignal.c;h=325705fcc5c12aa05b9e4f1602de8f6fd7485634;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=273d10c29d5f9bb0cb3219c07f87faae1c06ac1f;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 273d10c29..325705fcc 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,6 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage void do_syscall_trace(void); - /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -232,7 +231,7 @@ asmlinkage void sys_sigreturn(struct pt_regs regs) * Don't let your children do this ... */ if (current_thread_info()->flags & TIF_SYSCALL_TRACE) - do_syscall_trace(); + do_syscall_trace(®s, 1); __asm__ __volatile__( "move\t$29, %0\n\t" "j\tsyscall_exit" @@ -407,9 +406,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } #endif @@ -476,19 +473,15 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info); static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - switch(regs->regs[0]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: @@ -540,6 +533,7 @@ extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -549,15 +543,29 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) } #endif + /* + * We want the common case to go fast, which is why we may in certain + * cases get here from kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } + if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } +no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction,