Commit e9946e06 authored by Stephen Rothwell's avatar Stephen Rothwell Committed by Linus Torvalds

[PATCH] consolidate do_signal

11 out of our 17 architectures have basically the same code
in arch/../kernel/signal.c:do_signal.  This patch creates a
common function for that bit of code and uses it in the places
it can be.

The 2.5.15 version of this patch builds and runs on i386 and PPC and has
been briefly looked at by the CRIS, PARISC, PPC64 and x86_64 maintainers.

As a bonus, this fixes the "ignore SIGURG" bug for 9 more architectures
(i386 and PPC already were fixed).
parent 6ba85d4c
...@@ -518,9 +518,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -518,9 +518,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static inline void static inline void
handle_signal(int canrestart, unsigned long sig, struct k_sigaction *ka, handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (canrestart) { if (canrestart) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -580,7 +582,7 @@ handle_signal(int canrestart, unsigned long sig, struct k_sigaction *ka, ...@@ -580,7 +582,7 @@ handle_signal(int canrestart, unsigned long sig, struct k_sigaction *ka,
int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -594,98 +596,10 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) ...@@ -594,98 +596,10 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
lock_kernel();
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(canrestart, signr, ka, &info, oldset, regs); handle_signal(canrestart, signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -18,9 +18,7 @@ ...@@ -18,9 +18,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/tty.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -535,9 +533,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -535,9 +533,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->orig_eax >= 0) { if (regs->orig_eax >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -584,7 +584,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -584,7 +584,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
int do_signal(struct pt_regs *regs, sigset_t *oldset) int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -603,98 +603,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -603,98 +603,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP: {
struct signal_struct *sig;
current->state = TASK_STOPPED;
current->exit_code = signr;
sig = current->parent->sig;
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
}
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Reenable any watchpoints before delivering the /* Reenable any watchpoints before delivering the
* signal to user space. The processor register will * signal to user space. The processor register will
* have been cleared if the watchpoint triggered * have been cleared if the watchpoint triggered
...@@ -703,7 +613,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -703,7 +613,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
__asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7])); __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -522,9 +522,11 @@ setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -522,9 +522,11 @@ setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
} }
static inline void static inline void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(ka, regs, sig, oldset, info); setup_rt_frame(ka, regs, sig, oldset, info);
else else
...@@ -566,8 +568,8 @@ extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); ...@@ -566,8 +568,8 @@ extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
asmlinkage int do_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; siginfo_t info;
int sig_nr;
#ifdef CONFIG_BINFMT_IRIX #ifdef CONFIG_BINFMT_IRIX
if (current->personality != PER_LINUX) if (current->personality != PER_LINUX)
...@@ -577,99 +579,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -577,99 +579,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -543,10 +543,11 @@ static void inline setup_rt_frame(struct k_sigaction * ka, ...@@ -543,10 +543,11 @@ static void inline setup_rt_frame(struct k_sigaction * ka,
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, static inline void handle_signal(unsigned long sig, siginfo_t *info,
siginfo_t *info, sigset_t *oldset, sigset_t *oldset, struct pt_regs *regs)
struct pt_regs *regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(ka, regs, sig, oldset, info); setup_rt_frame(ka, regs, sig, oldset, info);
else else
...@@ -589,8 +590,8 @@ extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); ...@@ -589,8 +590,8 @@ extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
asmlinkage int do_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; siginfo_t info;
int signr;
#ifdef CONFIG_BINFMT_ELF32 #ifdef CONFIG_BINFMT_ELF32
if (current->thread.mflags & MF_32BIT) { if (current->thread.mflags & MF_32BIT) {
...@@ -601,99 +602,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -601,99 +602,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -625,9 +625,11 @@ setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -625,9 +625,11 @@ setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
} }
static inline void static inline void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(ka, regs, sig, oldset, info); setup_rt_frame(ka, regs, sig, oldset, info);
else else
...@@ -667,105 +669,18 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) ...@@ -667,105 +669,18 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs) asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs)
{ {
struct k_sigaction *ka;
siginfo_t info; siginfo_t info;
int signr;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -432,10 +432,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -432,10 +432,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static long static long
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, int in_syscall) struct pt_regs *regs, int in_syscall)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
#if DEBUG_SIG #if DEBUG_SIG
printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n", printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
sig, ka, info, oldset, regs); sig, ka, info, oldset, regs);
...@@ -473,6 +474,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -473,6 +474,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; struct k_sigaction *ka;
int signr;
#if DEBUG_SIG #if DEBUG_SIG
printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n", printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
...@@ -490,102 +492,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -490,102 +492,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]); printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]);
#endif #endif
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
#if DEBUG_SIG
printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid);
#endif
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
#if DEBUG_SIG
printk("sa_handler is %lx\n", ka->sa.sa_handler);
#endif
if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) {
if (signr != SIGCHLD)
continue;
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
set_current_state(TASK_STOPPED);
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (signr == SIGQUIT) /* Userspace debugging */
show_regs(regs);
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Restart a system call if necessary. */ /* Restart a system call if necessary. */
if (in_syscall) { if (in_syscall) {
/* Check the return code */ /* Check the return code */
...@@ -598,6 +506,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -598,6 +506,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
ka = &current->sig->action[signr-1];
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART)) {
#if DEBUG_SIG #if DEBUG_SIG
printk("ERESTARTSYS: putting -EINTR\n"); printk("ERESTARTSYS: putting -EINTR\n");
...@@ -619,7 +528,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -619,7 +528,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
/* Whee! Actually deliver the signal. If the /* Whee! Actually deliver the signal. If the
delivery failed, we need to continue to iterate in delivery failed, we need to continue to iterate in
this loop so we can deliver the SIGSEGV... */ this loop so we can deliver the SIGSEGV... */
if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) { if (handle_signal(signr, &info, oldset, regs, in_syscall)) {
#if DEBUG_SIG #if DEBUG_SIG
printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]); printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]);
#endif #endif
......
...@@ -426,12 +426,12 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -426,12 +426,12 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, struct pt_regs * regs, unsigned long *newspp, unsigned long frame)
unsigned long *newspp, unsigned long frame)
{ {
struct sigcontext_struct *sc; struct sigcontext_struct *sc;
struct rt_sigframe *rt_sf; struct rt_sigframe *rt_sf;
struct k_sigaction *ka = &current->sig->action[sig-1];
if (TRAP(regs) == 0x0C00 /* System Call! */ if (TRAP(regs) == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
...@@ -515,101 +515,16 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -515,101 +515,16 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; struct k_sigaction *ka;
unsigned long frame, newsp; unsigned long frame, newsp;
int signr;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
newsp = frame = 0; newsp = frame = 0;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
if ( (ka->sa.sa_flags & SA_ONSTACK) if ( (ka->sa.sa_flags & SA_ONSTACK)
&& (! on_sig_stack(regs->gpr[1]))) && (! on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
...@@ -618,8 +533,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -618,8 +533,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = newsp - sizeof(struct sigregs); newsp = frame = newsp - sizeof(struct sigregs);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs, &newsp, frame); handle_signal(signr, &info, oldset, regs, &newsp, frame);
break;
} }
if (TRAP(regs) == 0x0C00 /* System Call! */ && if (TRAP(regs) == 0x0C00 /* System Call! */ &&
......
...@@ -544,12 +544,12 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -544,12 +544,12 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, struct pt_regs * regs, unsigned long *newspp, unsigned long frame)
unsigned long *newspp, unsigned long frame)
{ {
struct sigcontext_struct *sc; struct sigcontext_struct *sc;
struct rt_sigframe *rt_sf; struct rt_sigframe *rt_sf;
struct k_sigaction *ka = &current->sig->action[sig-1];
if (regs->trap == 0x0C00 /* System Call! */ if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
...@@ -633,6 +633,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -633,6 +633,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; struct k_sigaction *ka;
unsigned long frame, newsp; unsigned long frame, newsp;
int signr;
/* /*
* If the current thread is 32 bit - invoke the * If the current thread is 32 bit - invoke the
...@@ -646,103 +647,9 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -646,103 +647,9 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = 0; newsp = frame = 0;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
PPCDBG(PPCDBG_SIGNAL, "do_signal - (pre) dequeueing signal - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
PPCDBG(PPCDBG_SIGNAL, "do_signal - (aft) dequeueing signal - signal=%lx - pid=%ld current=%lx comm=%s \n", signr, current->pid, current, current->comm);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
PPCDBG(PPCDBG_SIGNAL, "do_signal - ka=%p, action handler=%lx \n", ka, ka->sa.sa_handler);
if (ka->sa.sa_handler == SIG_IGN) {
PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_IGN logic \n");
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_DFL logic \n");
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
if ( (ka->sa.sa_flags & SA_ONSTACK) if ( (ka->sa.sa_flags & SA_ONSTACK)
&& (! on_sig_stack(regs->gpr[1]))) && (! on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
...@@ -753,9 +660,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -753,9 +660,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
handle_signal(signr, ka, &info, oldset, regs, &newsp, frame); handle_signal(signr, &info, oldset, regs, &newsp, frame);
PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
break;
} }
if (regs->trap == 0x0C00 /* System Call! */ && if (regs->trap == 0x0C00 /* System Call! */ &&
......
...@@ -1187,13 +1187,13 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -1187,13 +1187,13 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame,
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal32(unsigned long sig, struct k_sigaction *ka, handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, struct pt_regs * regs, unsigned int *newspp, unsigned int frame)
unsigned int *newspp, unsigned int frame)
{ {
struct sigcontext32_struct *sc; struct sigcontext32_struct *sc;
struct rt_sigframe_32 *rt_stack_frame; struct rt_sigframe_32 *rt_stack_frame;
siginfo_t32 siginfo32bit; siginfo_t32 siginfo32bit;
struct k_sigaction *ka = &current->sig->action[sig-1];
if (regs->trap == 0x0C00 /* System Call! */ if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
...@@ -1337,114 +1337,23 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1337,114 +1337,23 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; struct k_sigaction *ka;
unsigned int frame, newsp; unsigned int frame, newsp;
int signr;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
newsp = frame = 0; newsp = frame = 0;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
ifppcdebug(PPCDBG_SYS32) {
if (signr)
udbg_printf("do_signal32 - processing signal=%2lx - pid=%ld, comm=%s \n", signr, current->pid, current->comm);
}
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
PPCDBG(PPCDBG_SIGNAL, " do signal :sigaction flags = %lx \n" ,ka->sa.sa_flags); PPCDBG(PPCDBG_SIGNAL, " do signal :sigaction flags = %lx \n" ,ka->sa.sa_flags);
PPCDBG(PPCDBG_SIGNAL, " do signal :on sig stack = %lx \n" ,on_sig_stack(regs->gpr[1])); PPCDBG(PPCDBG_SIGNAL, " do signal :on sig stack = %lx \n" ,on_sig_stack(regs->gpr[1]));
PPCDBG(PPCDBG_SIGNAL, " do signal :reg1 = %lx \n" ,regs->gpr[1]); PPCDBG(PPCDBG_SIGNAL, " do signal :reg1 = %lx \n" ,regs->gpr[1]);
PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack = %lx \n" ,current->sas_ss_sp); PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack = %lx \n" ,current->sas_ss_sp);
PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack size = %lx \n" ,current->sas_ss_size); PPCDBG(PPCDBG_SIGNAL, " do signal :alt stack size = %lx \n" ,current->sas_ss_size);
if ( (ka->sa.sa_flags & SA_ONSTACK) if ( (ka->sa.sa_flags & SA_ONSTACK)
&& (! on_sig_stack(regs->gpr[1]))) && (! on_sig_stack(regs->gpr[1])))
{ {
...@@ -1454,8 +1363,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1454,8 +1363,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = newsp - sizeof(struct sigregs32); newsp = frame = newsp - sizeof(struct sigregs32);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal32(signr, ka, &info, oldset, regs, &newsp, frame); handle_signal32(signr, &info, oldset, regs, &newsp, frame);
break;
} }
if (regs->trap == 0x0C00 /* System Call! */ && if (regs->trap == 0x0C00 /* System Call! */ &&
...@@ -1468,9 +1376,8 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1468,9 +1376,8 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
} }
if (newsp == frame) if (newsp == frame)
{
return 0; /* no signals delivered */ return 0; /* no signals delivered */
}
// Invoke correct stack setup routine // Invoke correct stack setup routine
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp);
......
...@@ -409,9 +409,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -409,9 +409,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->trap == __LC_SVC_OLD_PSW) { if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -462,7 +464,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -462,7 +464,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
int do_signal(struct pt_regs *regs, sigset_t *oldset) int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -476,100 +478,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -476,100 +478,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->p_pptr->sig;
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
}
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -409,9 +409,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -409,9 +409,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->trap == __LC_SVC_OLD_PSW) { if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -462,7 +464,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -462,7 +464,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
int do_signal(struct pt_regs *regs, sigset_t *oldset) int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -482,100 +483,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -482,100 +483,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
} }
#endif #endif
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->p_pptr->sig;
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
}
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -548,9 +548,11 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -548,9 +548,11 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal32(unsigned long sig, struct k_sigaction *ka, handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->trap == __LC_SVC_OLD_PSW) { if (regs->trap == __LC_SVC_OLD_PSW) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -601,7 +603,7 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -601,7 +603,7 @@ handle_signal32(unsigned long sig, struct k_sigaction *ka,
int do_signal32(struct pt_regs *regs, sigset_t *oldset) int do_signal32(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -615,97 +617,10 @@ int do_signal32(struct pt_regs *regs, sigset_t *oldset) ...@@ -615,97 +617,10 @@ int do_signal32(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
set_current_state(TASK_STOPPED);
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal32(signr, ka, &info, oldset, regs); handle_signal32(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -522,9 +522,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -522,9 +522,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -575,7 +577,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -575,7 +577,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
int do_signal(struct pt_regs *regs, sigset_t *oldset) int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -589,97 +591,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -589,97 +591,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -380,9 +380,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -380,9 +380,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1];
#if DEBUG_SIG #if DEBUG_SIG
printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig,
regs->rip, regs->rsp, regs); regs->rip, regs->rsp, regs);
...@@ -438,7 +440,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -438,7 +440,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
int do_signal(struct pt_regs *regs, sigset_t *oldset) int do_signal(struct pt_regs *regs, sigset_t *oldset)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -453,101 +455,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -453,101 +455,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs);
unsigned long signr; if (signr > 0) {
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr) {
break;
}
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info.si_signo) {
info.si_signo = signr;
info.si_errno = 0;
info.si_code = SI_USER;
info.si_pid = current->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP: {
struct signal_struct *sig;
preempt_disable();
current->state = TASK_STOPPED;
current->exit_code = signr;
sig = current->parent->sig;
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
preempt_enable();
continue;
}
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOTREACHED */
}
}
/* Reenable any watchpoints before delivering the /* Reenable any watchpoints before delivering the
* signal to user space. The processor register will * signal to user space. The processor register will
* have been cleared if the watchpoint triggered * have been cleared if the watchpoint triggered
...@@ -556,7 +465,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -556,7 +465,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
__asm__("movq %0,%%db7" : : "r" (current->thread.debugreg[7])); __asm__("movq %0,%%db7" : : "r" (current->thread.debugreg[7]));
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -185,6 +185,9 @@ struct sigstack { ...@@ -185,6 +185,9 @@ struct sigstack {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif #endif
#endif #endif
...@@ -187,6 +187,8 @@ typedef struct sigaltstack { ...@@ -187,6 +187,8 @@ typedef struct sigaltstack {
#define sigmask(sig) (1UL << ((sig) - 1)) #define sigmask(sig) (1UL << ((sig) - 1))
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif #endif
#endif #endif
...@@ -166,6 +166,8 @@ struct k_sigaction { ...@@ -166,6 +166,8 @@ struct k_sigaction {
# include <asm/sigcontext.h> # include <asm/sigcontext.h>
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
# endif /* !__ASSEMBLY__ */ # endif /* !__ASSEMBLY__ */
......
...@@ -215,6 +215,8 @@ extern __inline__ int sigfindinword(unsigned long word) ...@@ -215,6 +215,8 @@ extern __inline__ int sigfindinword(unsigned long word)
return word ^ 31; return word ^ 31;
} }
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _M68K_SIGNAL_H */ #endif /* _M68K_SIGNAL_H */
...@@ -216,6 +216,8 @@ typedef struct sigaltstack { ...@@ -216,6 +216,8 @@ typedef struct sigaltstack {
size_t ss_size; size_t ss_size;
} stack_t; } stack_t;
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
#endif /* !(_ASMSPARC_SIGNAL_H) */ #endif /* !(_ASMSPARC_SIGNAL_H) */
...@@ -252,6 +252,9 @@ typedef struct sigaltstack32 { ...@@ -252,6 +252,9 @@ typedef struct sigaltstack32 {
int ss_flags; int ss_flags;
__kernel_size_t32 ss_size; __kernel_size_t32 ss_size;
} stack_t32; } stack_t32;
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
#endif #endif
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
......
...@@ -220,6 +220,10 @@ static inline void init_sigpending(struct sigpending *sig) ...@@ -220,6 +220,10 @@ static inline void init_sigpending(struct sigpending *sig)
extern long do_sigpending(void *, unsigned long); extern long do_sigpending(void *, unsigned long);
#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs);
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_SIGNAL_H */ #endif /* _LINUX_SIGNAL_H */
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -824,6 +826,110 @@ notify_parent(struct task_struct *tsk, int sig) ...@@ -824,6 +826,110 @@ notify_parent(struct task_struct *tsk, int sig)
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
} }
#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
{
for (;;) {
unsigned long signr;
struct k_sigaction *ka;
spin_lock_irq(&current->sigmask_lock);
signr = dequeue_signal(&current->blocked, info);
spin_unlock_irq(&current->sigmask_lock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
/* We're back. Did the debugger cancel the sig? */
signr = current->exit_code;
if (signr == 0)
continue;
current->exit_code = 0;
/* The debugger continued. Ignore SIGSTOP. */
if (signr == SIGSTOP)
continue;
/* Update the siginfo structure. Is this good? */
if (signr != info->si_signo) {
info->si_signo = signr;
info->si_errno = 0;
info->si_code = SI_USER;
info->si_pid = current->parent->pid;
info->si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, info, current);
continue;
}
}
ka = &current->sig->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* Check for SIGCHLD: it's special. */
while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
if (ka->sa.sa_handler == SIG_DFL) {
int exit_code = signr;
/* Init gets no signals it doesn't want. */
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
continue;
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
/* FALLTHRU */
case SIGSTOP: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->parent->sig;
if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
}
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, info);
/* NOTREACHED */
}
}
return signr;
}
return 0;
}
#endif
EXPORT_SYMBOL(dequeue_signal); EXPORT_SYMBOL(dequeue_signal);
EXPORT_SYMBOL(flush_signals); EXPORT_SYMBOL(flush_signals);
EXPORT_SYMBOL(force_sig); EXPORT_SYMBOL(force_sig);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment