patch-2.0.1 linux/arch/alpha/kernel/signal.c
Next file: linux/arch/i386/kernel/ksyms.c
Previous file: linux/arch/alpha/kernel/process.c
Back to the patch index
Back to the overall index
- Lines: 169
- Date:
Tue Jul 2 19:08:34 1996
- Orig file:
v2.0.0/linux/arch/alpha/kernel/signal.c
- Orig date:
Fri Apr 19 10:07:57 1996
diff -u --recursive --new-file v2.0.0/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
@@ -130,24 +130,28 @@
/*
* Set up a signal frame...
*/
-static void setup_frame(struct sigaction * sa, struct sigcontext_struct ** fp,
- unsigned long pc, struct pt_regs * regs,
+static void setup_frame(struct sigaction * sa,
+ struct pt_regs * regs,
struct switch_stack * sw, int signr,
unsigned long oldmask)
{
int i;
+ unsigned long oldsp;
struct sigcontext_struct * sc;
- sc = *fp;
+ oldsp = rdusp();
+ sc = ((struct sigcontext_struct *) oldsp) - 1;
+
/* check here if we would need to switch stacks.. */
- sc--;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
do_exit(SIGSEGV);
+ wrusp((unsigned long) sc);
+
put_fs_quad(oldmask, &sc->sc_mask);
put_fs_quad(8, &sc->sc_ps);
- put_fs_quad(pc, &sc->sc_pc);
- put_fs_quad((unsigned long)*fp, sc->sc_regs+30);
+ put_fs_quad(regs->pc, &sc->sc_pc);
+ put_fs_quad(oldsp, sc->sc_regs+30);
put_fs_quad(regs->r0 , sc->sc_regs+0);
put_fs_quad(regs->r1 , sc->sc_regs+1);
@@ -193,14 +197,51 @@
*/
put_fs_quad(0x43ecf40047de0410, sc->sc_retcode+0);
put_fs_quad(0x0000000000000083, sc->sc_retcode+1);
+ imb();
+
+ /* "return" to the handler */
+ regs->r27 = regs->pc = (unsigned long) sa->sa_handler;
regs->r26 = (unsigned long) sc->sc_retcode;
regs->r16 = signr; /* a0: signal number */
regs->r17 = 0; /* a1: exception code; see gentrap.h */
regs->r18 = (unsigned long) sc; /* a2: sigcontext pointer */
- *fp = sc;
}
/*
+ * OK, we're invoking a handler
+ */
+static inline void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs * regs, struct switch_stack *sw)
+{
+ setup_frame(sa,regs,sw,signr,oldmask);
+
+ if (sa->sa_flags & SA_ONESHOT)
+ sa->sa_handler = NULL;
+ if (!(sa->sa_flags & SA_NOMASK))
+ current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+}
+
+static inline void syscall_restart(unsigned long r0, unsigned long r19,
+ struct pt_regs * regs, struct sigaction * sa)
+{
+ switch (regs->r0) {
+ case ERESTARTNOHAND:
+ no_system_call_restart:
+ regs->r0 = EINTR;
+ break;
+ case ERESTARTSYS:
+ if (!(sa->sa_flags & SA_RESTART))
+ goto no_system_call_restart;
+ /* fallthrough */
+ case ERESTARTNOINTR:
+ regs->r0 = r0; /* reset v0 and a3 and replay syscall */
+ regs->r19 = r19;
+ regs->pc -= 4;
+ }
+}
+
+
+/*
* 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.
@@ -219,9 +260,6 @@
unsigned long r0, unsigned long r19)
{
unsigned long mask = ~current->blocked;
- unsigned long handler_signal = 0;
- struct sigcontext_struct *frame = NULL;
- unsigned long pc = 0;
unsigned long signr, single_stepping;
struct sigaction * sa;
@@ -264,7 +302,10 @@
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
- case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (is_orphaned_pgrp(current->pgrp))
+ continue;
+ case SIGSTOP:
if (current->flags & PF_PTRACED)
continue;
current->state = TASK_STOPPED;
@@ -289,16 +330,13 @@
do_exit(signr);
}
}
- /*
- * OK, we're invoking a handler
- */
- if (r0) {
- if (regs->r0 == ERESTARTNOHAND ||
- (regs->r0 == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
- regs->r0 = EINTR;
+ if (r0)
+ syscall_restart(r0, r19, regs, sa);
+ handle_signal(signr, sa, oldmask, regs, sw);
+ if (single_stepping) {
+ ptrace_set_bpt(current); /* re-set breakpoint */
}
- handler_signal |= 1 << (signr-1);
- mask &= ~sa->sa_mask;
+ return 1;
}
if (r0 &&
(regs->r0 == ERESTARTNOHAND ||
@@ -308,34 +346,8 @@
regs->r19 = r19;
regs->pc -= 4;
}
- if (!handler_signal) { /* no handler will be called - return 0 */
- if (single_stepping) {
- ptrace_set_bpt(current); /* re-set breakpoint */
- }
- return 0;
- }
- pc = regs->pc;
- frame = (struct sigcontext_struct *) rdusp();
- signr = 1;
- sa = current->sig->action;
- for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
- if (mask > handler_signal)
- break;
- if (!(mask & handler_signal))
- continue;
- setup_frame(sa,&frame,pc,regs,sw,signr,oldmask);
- pc = (unsigned long) sa->sa_handler;
- regs->r27 = pc;
- if (sa->sa_flags & SA_ONESHOT)
- sa->sa_handler = NULL;
- current->blocked |= sa->sa_mask;
- oldmask |= sa->sa_mask;
- }
- imb();
- wrusp((unsigned long) frame);
- regs->pc = pc; /* "return" to the first handler */
if (single_stepping) {
ptrace_set_bpt(current); /* re-set breakpoint */
}
- return 1;
+ return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov