patch-2.1.101 linux/arch/mips/kernel/signal.c
Next file: linux/arch/mips/kernel/syscall.c
Previous file: linux/arch/mips/kernel/setup.c
Back to the patch index
Back to the overall index
- Lines: 721
- Date:
Fri May 8 00:13:24 1998
- Orig file:
v2.1.100/linux/arch/mips/kernel/signal.c
- Orig date:
Wed Dec 10 10:31:09 1997
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
@@ -4,7 +4,9 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, 1995, 1996 Ralf Baechle
*
- * $Id: signal.c,v 1.8 1997/12/01 16:26:34 ralf Exp $
+ * $Id: signal.c,v 1.12 1998/05/01 01:34:28 ralf Exp $
+ *
+ * XXX Handle lazy fp context switches correctly.
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -23,82 +25,189 @@
#include <asm/pgtable.h>
#include <asm/uaccess.h>
-#define _S(nr) (1<<((nr)-1))
+#define DEBUG_SIG 0
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
int options, unsigned long *ru);
-asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
/*
* Atomically swap in the new signal mask, and wait for a signal.
- * Unlike on Intel we pass a sigset_t *, not sigset_t.
*/
-asmlinkage int sys_sigsuspend(struct pt_regs *regs)
+asmlinkage inline int
+sys_sigsuspend(struct pt_regs regs)
{
- unsigned long mask;
- sigset_t *uset, set;
+ sigset_t *uset, saveset, newset;
- uset = (sigset_t *) regs->regs[4];
- if (get_user(set, uset))
+ uset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, uset, sizeof(sigset_t)))
return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock);
- mask = current->blocked;
- current->blocked = set & _BLOCKABLE;
+ saveset = current->blocked;
+ current->blocked = newset;
spin_unlock_irq(¤t->sigmask_lock);
- regs->regs[2] = -EINTR;
+ regs.regs[2] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(mask, regs))
+ if (do_signal(&saveset, ®s))
return -EINTR;
}
- return -EINTR;
}
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs regs)
{
- struct sigcontext *context;
- unsigned long blocked;
- long long reg;
- int i;
+ sigset_t *uset, saveset, newset;
- context = (struct sigcontext *)(long) regs->regs[29];
- if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
- (regs->regs[29] & (SZREG - 1)))
- goto badframe;
+ uset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
- __get_user(blocked, &context->sc_sigset);
- current->blocked = blocked & _BLOCKABLE;
- __get_user(regs->cp0_epc, &context->sc_pc);
+ spin_lock_irq(¤t->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ spin_unlock_irq(¤t->sigmask_lock);
- /*
- * Restore all integer registers.
- */
- for(i = 31;i >= 0;i--) {
- __get_user(reg, &context->sc_regs[i]);
- regs->regs[i] = (int) reg;
+ regs.regs[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, ®s))
+ return -EINTR;
}
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ sigset_t mask;
+ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+ return -EFAULT;
+
+ __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
+ new_ka.ka_restorer = NULL;
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+ return -EFAULT;
+ __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
+ sizeof(sigset_t));
+ }
+
+ return ret;
+}
+
+/*
+ * To do: this entire function should be accessed over a function pointer
+ * such that we can handle stack frames for different ABIs.
+ */
+
+asmlinkage void
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *context)
+{
+ long long reg;
+ int owned_fp;
+
+ __get_user(regs->cp0_epc, &context->sc_pc);
+
__get_user(reg, &context->sc_mdhi);
regs->hi = (int) reg;
__get_user(reg, &context->sc_mdlo);
regs->lo = (int) reg;
- /*
- * FP depends on what FPU in what mode we have. Best done in
- * Assembler ...
- */
- restore_fp_context(context);
+#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \
+ regs->regs[i] = (int) reg;
+ restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+ restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+ restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+ restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+ restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+ restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+ restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+ restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+ restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+ restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+ restore_gp_reg(31);
+#undef restore_gp_reg
+
+ /* FP depends on what FPU in what mode we have. */
+ __get_user(owned_fp, &context->sc_ownedfp);
+#if 0
+ if (owned_fp) {
+ restore_fp_context(context);
+ last_task_used_math = current;
+ }
+#endif
+restore_fp_context(context);
+}
- /*
- * Disable syscall checks
- */
- regs->orig_reg2 = -1;
+/*
+ * The structure sc describes the stackframe on the userstack. The frames
+ * are identical for normal and realtime signal stackframes with the
+ * exception of the additional struct ucontext for rt frames.
+ */
+struct sigframe {
+ unsigned long ass[4]; /* argument save space for o32 */
+ unsigned int code[4]; /* signal trampoline */
+ struct sigcontext scc;
+};
+
+struct rt_sigframe {
+ unsigned long ass[4];
+ unsigned int code[4];
+ struct sigcontext scc;
+ // struct ucontext uc;
+};
+
+asmlinkage int sys_sigreturn(struct pt_regs regs)
+{
+ struct sigcontext *context;
+ sigset_t blocked;
+
+ context = (struct sigcontext *)(long) regs.regs[29];
+ if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
+ (regs.regs[29] & (SZREG - 1)))
+ goto badframe;
+
+#if 1
+ if (__get_user(blocked.sig[0], &context->sc_sigset[0]) ||
+ __get_user(blocked.sig[1], &context->sc_sigset[1]) ||
+ __get_user(blocked.sig[2], &context->sc_sigset[2]) ||
+ __get_user(blocked.sig[3], &context->sc_sigset[3]))
+ goto badframe;
+#else
+ if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked)))
+ goto badframe;
+#endif
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = blocked;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ restore_sigcontext(®s, context);
/*
* Don't let your children do this ...
@@ -107,7 +216,7 @@
"move\t$29,%0\n\t"
"j\tret_from_sys_call"
:/* no outputs */
- :"r" (regs));
+ :"r" (®s));
/* Unreached */
badframe:
@@ -116,103 +225,113 @@
unlock_kernel();
}
+/* same as sys_sigreturn for now */
+asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
+{
+ return -ENOSYS;
+}
+
+#define scc_offset ((size_t)&((struct sigframe *)0)->scc)
+
/*
- * Set up a signal frame...
- *
- * This routine is somewhat complicated by the fact that if the kernel may be
- * entered by an exception other than a system call; e.g. a bus error or other
- * "bad" exception. If this is the case, then *all* the context on the kernel
- * stack frame must be saved.
- *
- * For a large number of exceptions, the stack frame format is the same
- * as that which will be created when the process traps back to the kernel
- * when finished executing the signal handler. In this case, nothing
- * must be done. This information is saved on the user stack and restored
- * when the signal handler is returned.
- *
- * The signal handler will be called with ra pointing to code1 (see below) and
- * one parameters in a0 (signum).
+ * Set up the return code ...
*
- * usp -> [unused] ; first free word on stack
- * arg save space ; 16/32 bytes arg. save space
- * code1 (addiu sp,#1-offset) ; pop stackframe
- * code2 (li v0,__NR_sigreturn) ; syscall number
- * code3 (syscall) ; do sigreturn(2)
- * #1| $0, at, v0, v1, a0, a1, a2, a3 ; All integer registers
- * | t0, t1, t2, t3, t4, t5, t6, t7 ; $0, k0 and k1 are placeholders
- * | s0, s1, s2, s3, s4, s5, s6, s7
- * | k0, k1, t8, t9, gp, sp, fp, ra;
- * | epc ; old program counter
- * | cause ; CP0 cause register
- * | oldmask
+ * .set noreorder
+ * addiu sp,0x20
+ * li v0,__NR_sigreturn
+ * syscall
+ * .set reorder
*/
+static void inline
+setup_trampoline(unsigned int *code)
+{
+ __put_user(0x27bd0000 + scc_offset , code + 0);
+ __put_user(0x24020000 + __NR_sigreturn, code + 1);
+ __put_user(0x0000000c , code + 2);
-struct sc {
- unsigned long ass[4];
- unsigned int code[4];
- struct sigcontext scc;
-};
-#define scc_offset ((size_t)&((struct sc *)0)->scc)
+ /*
+ * Flush caches so that the instructions will be correctly executed.
+ */
+ flush_cache_sigtramp((unsigned long) code);
+}
+
+static void inline
+setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set)
+{
+ int owned_fp;
+
+ __put_user(regs->cp0_epc, &sc->sc_pc);
+ __put_user(regs->cp0_status, &sc->sc_status); /* Status register */
+
+#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)])
+ __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+ save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+ save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+ save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+ save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+ save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+ save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+ save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+ save_gp_reg(31);
+#undef save_gp_reg
+
+ __put_user(regs->hi, &sc->sc_mdhi);
+ __put_user(regs->lo, &sc->sc_mdlo);
+ __put_user(regs->cp0_cause, &sc->sc_cause);
+
+ owned_fp = (current == last_task_used_math);
+ __put_user(owned_fp, &sc->sc_ownedfp);
+
+#if 0
+ if (current->used_math) { /* fp is active. */
+ set_cp0_status(ST0_CU1, ST0_CU1);
+ save_fp_context(sc); /* cpu dependant */
+ last_task_used_math = NULL;
+ regs->cp0_status &= ~ST0_CU1;
+ current->used_math = 0;
+ }
+#endif
+set_cp0_status(ST0_CU1, ST0_CU1);
+save_fp_context(sc); /* cpu dependant */
-static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
- int signr, unsigned long oldmask)
+ __put_user(set->sig[0], &sc->sc_sigset[0]);
+ __put_user(set->sig[1], &sc->sc_sigset[1]);
+ __put_user(set->sig[2], &sc->sc_sigset[2]);
+ __put_user(set->sig[3], &sc->sc_sigset[3]);
+}
+
+static void inline
+setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *oldmask)
{
- struct sc *frame;
+ struct sigframe *frame;
struct sigcontext *sc;
- int i;
/* Align the stackframe to an adequate boundary for the architecture. */
- frame = (struct sc *) (long) regs->regs[29];
+ frame = (struct sigframe *) (long) regs->regs[29];
frame--;
- frame = (struct sc *)((unsigned long)frame & ALMASK);
+ frame = (struct sigframe *)((unsigned long)frame & ALMASK);
if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;
sc = &frame->scc;
- /*
- * Set up the return code ...
- *
- * .set noreorder
- * addiu sp,0x20
- * li v0,__NR_sigreturn
- * syscall
- * .set reorder
- */
- __put_user(0x27bd0000 + scc_offset, &frame->code[0]);
- __put_user(0x24020000 + __NR_sigreturn, &frame->code[1]);
- __put_user(0x0000000c, &frame->code[2]);
-
- /*
- * Flush caches so that the instructions will be correctly executed.
- */
- flush_cache_sigtramp((unsigned long) frame->code);
+ setup_trampoline(frame->code);
+ setup_sigcontext(regs, &frame->scc, oldmask);
- /*
- * Set up the "normal" sigcontext
- */
- __put_user(regs->cp0_epc, &sc->sc_pc);
- __put_user(regs->cp0_status, &sc->sc_status); /* Status register */
- for(i = 31;i >= 0;i--)
- __put_user(regs->regs[i], &sc->sc_regs[i]);
- save_fp_context(sc);
- __put_user(regs->hi, &sc->sc_mdhi);
- __put_user(regs->lo, &sc->sc_mdlo);
- __put_user(regs->cp0_cause, &sc->sc_cause);
- __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp);
- __put_user(oldmask, &sc->sc_sigset);
- __put_user(0, &sc->__pad0[0]);
- __put_user(0, &sc->__pad0[1]);
- __put_user(0, &sc->__pad0[2]);
-
- regs->regs[4] = signr; /* Arguments for handler */
- regs->regs[5] = 0; /* For now. */
- regs->regs[6] = (long) frame; /* Pointer to sigcontext */
- regs->regs[29] = (unsigned long) frame; /* Stack pointer */
- regs->regs[31] = (unsigned long) frame->code; /* Return address */
- regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */
- regs->regs[25] = regs->cp0_epc; /* PIC shit... */
- return;
+ regs->regs[4] = signr; /* arguments */
+ regs->regs[5] = 0; /* should be cause */
+ regs->regs[6] = (long) frame; /* ptr to sigcontext */
+ regs->regs[29] = (unsigned long) frame; /* Stack pointer */
+ regs->regs[31] = (unsigned long) frame->code; /* Return address */
+ regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */
+ regs->regs[25] = regs->cp0_epc; /* PIC shit... */
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
+ current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+#endif
+ return;
segv_and_exit:
lock_kernel();
@@ -220,96 +339,127 @@
unlock_kernel();
}
-static inline void handle_signal(unsigned long signr, struct sigaction *sa,
- unsigned long oldmask, struct pt_regs * regs)
+static void inline
+setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *oldmask, siginfo_t *info)
{
- setup_frame(sa, regs, signr, oldmask);
+ printk("Aiee: setup_tr_frame wants to be written");
+}
- if (sa->sa_flags & SA_ONESHOT)
- sa->sa_handler = NULL;
- if (!(sa->sa_flags & SA_NOMASK)) {
+/* ------------------------------------------------------------------------- */
+
+static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(ka, regs, sig, oldset, info);
+ else
+ setup_frame(ka, regs, sig, oldset);
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(¤t->sigmask_lock);
- current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
}
}
-static inline void syscall_restart(unsigned long r0, unsigned long or2,
- unsigned long or7, struct pt_regs *regs,
- struct sigaction *sa)
+static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
{
- switch(r0) {
+ switch(regs->regs[0]) {
case ERESTARTNOHAND:
- no_system_call_restart:
- regs->regs[0] = regs->regs[2] = EINTR;
+ regs->regs[2] = EINTR;
break;
case ERESTARTSYS:
- if(!(sa->sa_flags & SA_RESTART))
- goto no_system_call_restart;
+ if(!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
/* fallthrough */
- case ERESTARTNOINTR:
- regs->regs[0] = regs->regs[2] = or2;
- regs->regs[7] = or7;
+ case ERESTARTNOINTR: /* Userland will reload $v0. */
regs->cp0_epc -= 8;
}
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
}
-extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs);
+extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- *
- * Note that we go through the signals twice: once to check the signals that
- * the kernel can handle, and then we build all the user-level signal handling
- * stack-frames in one go after that.
- */
-asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
- unsigned long mask = ~current->blocked;
- unsigned long signr, r0 = regs->regs[0];
- unsigned long r7 = regs->orig_reg7;
- struct sigaction * sa;
+ struct k_sigaction *ka;
+ siginfo_t info;
#ifdef CONFIG_BINFMT_IRIX
- if(current->personality != PER_LINUX)
- return do_irix_signal(oldmask, regs);
+ if (current->personality != PER_LINUX) /* XXX */
+ return do_irix_signal(oldset, regs);
#endif
- while ((signr = current->signal & mask)) {
- signr = ffz(~signr);
- clear_bit(signr, ¤t->signal);
- sa = current->sig->action + signr;
- signr++;
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ for (;;) {
+ unsigned long signr;
+
+ spin_lock_irq(¤t->sigmask_lock);
+ signr = dequeue_signal(¤t->blocked, &info);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ if (!signr)
+ break;
+
if ((current->flags & PF_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;
- if (_S(signr) & current->blocked) {
- spin_lock_irq(¤t->sigmask_lock);
- current->signal |= _S(signr);
- spin_unlock_irq(¤t->sigmask_lock);
+
+ /* 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(¤t->blocked, signr)) {
+ send_sig_info(signr, &info, current);
continue;
}
- sa = current->sig->action + signr - 1;
}
- if (sa->sa_handler == SIG_IGN) {
+
+ ka = ¤t->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)
+ /* Check for SIGCHLD: it's special. */
+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
- if (sa->sa_handler == SIG_DFL) {
+
+ 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;
@@ -317,72 +467,55 @@
case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (is_orphaned_pgrp(current->pgrp))
continue;
+ /* FALLTHRU */
+
case SIGSTOP:
- if (current->flags & PF_PTRACED)
- continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
- SA_NOCLDSTOP))
+ 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:
lock_kernel();
- if (current->binfmt && current->binfmt->core_dump) {
- if (current->binfmt->core_dump(signr, regs))
- signr |= 0x80;
- }
+ if (current->binfmt
+ && current->binfmt->core_dump
+ && current->binfmt->core_dump(signr, regs))
+ exit_code |= 0x80;
unlock_kernel();
- /* fall through */
- default:
- spin_lock_irq(¤t->sigmask_lock);
- current->signal |= _S(signr & 0x7f);
- spin_unlock_irq(¤t->sigmask_lock);
+ /* FALLTHRU */
+ default:
+ lock_kernel();
+ sigaddset(¤t->signal, signr);
current->flags |= PF_SIGNALED;
-
- lock_kernel(); /* 8-( */
- do_exit(signr);
- unlock_kernel();
+ do_exit(exit_code);
+ /* NOTREACHED */
}
}
- /*
- * OK, we're invoking a handler
- */
- if(r0)
- syscall_restart(r0, regs->orig_reg2,
- r7, regs, sa);
- handle_signal(signr, sa, oldmask, regs);
+
+ if (regs->regs[0])
+ syscall_restart(regs, ka);
+ /* Whee! Actually deliver the signal. */
+ handle_signal(signr, ka, &info, oldset, regs);
return 1;
}
+
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
* must directly be followed by the syscall instruction.
*/
- if (r0 &&
- (regs->regs[2] == ERESTARTNOHAND ||
- regs->regs[2] == ERESTARTSYS ||
- regs->regs[2] == ERESTARTNOINTR)) {
- regs->regs[0] = regs->regs[2] = regs->orig_reg2;
- regs->regs[7] = r7;
- regs->cp0_epc -= 8;
+ if (regs->regs[0]) {
+ if (regs->regs[2] == ERESTARTNOHAND ||
+ regs->regs[2] == ERESTARTSYS ||
+ regs->regs[2] == ERESTARTNOINTR) {
+ regs->cp0_epc -= 8;
+ }
}
return 0;
-}
-
-/*
- * The signal(2) syscall is no longer available in the kernel
- * because GNU libc doesn't use it. Maybe I'll add it back to the
- * kernel for the binary compatibility stuff.
- */
-asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
-{
- return -ENOSYS;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov