diff -Naur -X exclude-files ac_cur/arch/um/include/kern_util.h ac/arch/um/include/kern_util.h
--- ac_cur/arch/um/include/kern_util.h	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/include/kern_util.h	Fri Oct  5 15:01:48 2001
@@ -70,11 +70,7 @@
 extern void *process_state(void *t, unsigned long *cr2_out, int *err_out);
 extern struct sys_pt_regs *syscall_state(void *t, void **stack_out, 
 					 int *size_out);
-extern int have_signals(void *t, int altstack);
 extern void syscall_trace(void);
-extern void save_altstack(void *t, unsigned long sp);
-extern struct sys_pt_regs *altstack_state(void *t, void **stack_out, 
-					  int *size_out);
 extern int hz(void);
 extern int switching_modes(void *t);
 extern void idle_timer(void);
@@ -85,7 +81,6 @@
 extern void tracing_reboot(void);
 extern void tracing_halt(void);
 extern void tracing_cb(void (*proc)(void *), void *arg);
-extern void probe_stack(unsigned long sp);
 extern void debugger_signal(int status, int pid);
 extern void child_signal(int pid, int status);
 extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
@@ -98,7 +93,6 @@
 extern void finish_fork_handler(int sig);
 extern int user_context(unsigned long sp);
 extern void timer_irq(int user_mode);
-extern void signal_deliverer(void);
 extern void set_repeat_syscall(int again);
 extern int get_repeat_syscall(void *t);
 extern void set_sigreturn_syscall(int syscall);
@@ -111,7 +105,6 @@
 extern void *round_up(unsigned long addr);
 extern void *round_down(unsigned long addr);
 extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
-extern void handling_signal(void *t);
 extern int config_gdb(char *str);
 extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
@@ -119,6 +112,10 @@
 extern void protect_kernel_mem(void);
 extern unsigned long get_kmem_end(void);
 extern void set_kmem_end(unsigned long);
+extern void *diff_stacks(int size, char *stack1, struct sys_pt_regs *regs1, 
+			 char *stack2, struct sys_pt_regs *regs2, 
+			 char **mask_out, struct sys_pt_regs *regs_out, 
+			 struct sys_pt_regs *regs_out_mask);
 #endif
 
 /*
diff -Naur -X exclude-files ac_cur/arch/um/include/signal_kern.h ac/arch/um/include/signal_kern.h
--- ac_cur/arch/um/include/signal_kern.h	Wed Dec 31 19:00:00 1969
+++ ac/arch/um/include/signal_kern.h	Fri Oct  5 15:01:48 2001
@@ -0,0 +1,27 @@
+/* 
+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SIGNAL_KERN_H__
+#define __SIGNAL_KERN_H__
+
+#include "sysdep/ptrace.h"
+
+extern void signal_deliverer(int sig);
+extern struct sys_pt_regs *signal_state(void *t);
+extern int probe_stack(unsigned long sp, int delta);
+extern int have_signals(void *t);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Naur -X exclude-files ac_cur/arch/um/include/signal_user.h ac/arch/um/include/signal_user.h
--- ac_cur/arch/um/include/signal_user.h	Wed Dec 31 19:00:00 1969
+++ ac/arch/um/include/signal_user.h	Fri Oct  5 15:01:48 2001
@@ -0,0 +1,29 @@
+/* 
+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SIGNAL_USER_H__
+#define __SIGNAL_USER_H__
+
+extern int signal_stack_size;
+
+extern void change_sig(int signal, int on);
+extern void signal_handler(void *task, unsigned long handler, int sig);
+extern void set_sigstack(void *stack, int size);
+extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern void setup_stack(unsigned long stack_top, struct sys_pt_regs *regs_out);
+extern void setup_signal_stack(void);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Naur -X exclude-files ac_cur/arch/um/include/user_util.h ac/arch/um/include/user_util.h
--- ac_cur/arch/um/include/user_util.h	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/include/user_util.h	Fri Oct  5 15:01:48 2001
@@ -66,7 +66,6 @@
 extern void usr1_pid(int pid);
 extern void cont_pid(int pid);
 extern int __personality(int);
-extern void signal_handler(void *task, unsigned long handler, int sig);
 extern int syscall_handler(void *unused);
 extern int do_syscall(void *task, int pid);
 extern int wait_for_stop(int pid, int sig, int cont_type);
@@ -82,8 +81,6 @@
 extern void set_timers(int set_signal);
 extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
 extern int input_loop(void);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
-extern void set_sigstack(void *stack);
 extern void continue_execing_proc(int pid);
 extern int linux_main(int argc, char **argv);
 extern void remap_data(void *segment_start, void *segment_end);
@@ -91,13 +88,9 @@
 extern void continue_fork(void *task, int pid, struct sys_pt_regs *regs);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
 extern void setup_input(void);
-extern int exit_kernel(int pid, void *task, int *signal_out);
-extern int alt_stack_handler(void *arg);
-extern int setup_altstack(unsigned long stack, int stack_size);
-extern void process_stack_handler(int sig);
+extern int exit_kernel(int pid, void *task);
 extern int get_pty(void);
 extern void save_signal_state(int *sig_ptr);
-extern void change_sig(int signal, int on);
 extern void fill_in_sigcontext(void *sc, struct sys_pt_regs *regs,
 			       unsigned long cr2, int err);
 extern int activate_fd(int irq, int fd, void *dev_id);
@@ -110,7 +103,8 @@
 extern void cooked(int fd);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void idle_sleep(int secs);
-extern int get_one_stack(char **stack_out, struct sys_pt_regs *regs_out);
+extern int get_one_stack(int (*proc)(void *), void *arg, char **stack_out, 
+			 struct sys_pt_regs *regs_out);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(void);
 extern void add_arg(char *cmd_line, char *arg);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/irq_user.c ac/arch/um/kernel/irq_user.c
--- ac_cur/arch/um/kernel/irq_user.c	Fri Oct  5 14:15:35 2001
+++ ac/arch/um/kernel/irq_user.c	Fri Oct  5 15:01:48 2001
@@ -14,6 +14,7 @@
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
+#include "signal_user.h"
 
 struct irq_fd {
 	struct irq_fd *next;
@@ -147,10 +148,9 @@
 
 	flags = on_sigstack ? SA_ONSTACK : 0;
 	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, 
-		    flags | SA_NODEFER | SA_RESTART, SIGUSR1, SIGIO, 
-		    SIGUSR2, -1);
+		    flags | SA_NODEFER | SA_RESTART, SIGUSR1, SIGIO, -1);
 	set_handler(SIGIO, (__sighandler_t) irq_handler, flags | SA_RESTART,
-		    SIGUSR1, SIGIO, SIGUSR2, -1);
+		    SIGUSR1, SIGIO, -1);
 }
 
 /*
diff -Naur -X exclude-files ac_cur/arch/um/kernel/process.c ac/arch/um/kernel/process.c
--- ac_cur/arch/um/kernel/process.c	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/kernel/process.c	Fri Oct  5 15:01:48 2001
@@ -24,6 +24,8 @@
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
+#include "signal_kern.h"
+#include "signal_user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
 
@@ -47,41 +49,12 @@
 	kill(pid, SIGCONT);
 }
 
-void set_sigstack(void *sig_stack)
-{
-	stack_t stack;
-
-	stack.ss_sp = (__ptr_t) sig_stack;
-	stack.ss_flags = 0;
-	stack.ss_size = 2 * page_size() - sizeof(void *);
-	if(sigaltstack(&stack, NULL) != 0)
-		panic("sigaltstack failed");
-}
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
-{
-	struct sigaction action;
-	va_list ap;
-	int mask;
-
-	va_start(ap, flags);
-	action.sa_handler = handler;
-	sigemptyset(&action.sa_mask);
-	while((mask = va_arg(ap, int)) != -1){
-		sigaddset(&action.sa_mask, mask);
-	}
-	action.sa_flags = flags;
-	action.sa_restorer = NULL;
-	if(sigaction(sig, &action, NULL) < 0)
-		panic("sigaction failed");
-}
-
 void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
 {
 	int flags = 0;
 
 	if(sig_stack != NULL){
-		set_sigstack(sig_stack);
+		set_sigstack(sig_stack, 2 * page_size());
 		flags = SA_ONSTACK;
 	}
 	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
@@ -94,11 +67,10 @@
 		    SIGUSR1, SIGIO, -1);
 	set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, -1);
-	set_handler(SIGUSR2, process_stack_handler, SA_NODEFER, SIGUSR1, -1);
-	change_sig(SIGUSR2, 1);
 	if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
 	signal(SIGCHLD, SIG_IGN);
-	set_timers(1);
+        signal(SIGHUP, SIG_IGN);
+	set_timers(1);  /* XXX A bit of a race here */
 	init_irq_signals(sig_stack != NULL);
 }
 
@@ -185,20 +157,6 @@
 		panic("ptrace failed in trace_myself");
 }
 
-void signal_handler(void *task, unsigned long h, int sig)
-{
-	void (*handler)(int, struct sigcontext);
-	void *regs;
-	unsigned long cr2;
-	int err;
-	UM_ALLOCATE_SC(sc);
-
-	regs = process_state(task, &cr2, &err);
-	fill_in_sigcontext(&sc, regs, cr2, err);
-	handler = (void (*)(int, struct sigcontext)) h;
-	(*handler)(sig, sc);
-}
-
 void continue_fork(void *task, int pid, struct sys_pt_regs *regs)
 {
 	if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0)
@@ -208,38 +166,8 @@
 		tracer_panic("Couldn't restore registers");
 }
 
-int setup_altstack(unsigned long stack, int stack_size)
-{
-	struct sys_pt_regs *regs;
-	unsigned long sp;
-	int pid;
-
-	sp = stack + stack_size - sizeof(void *);
-	pid = clone(alt_stack_handler, (void *) sp, 
-		    CLONE_VM | CLONE_FILES | SIGCHLD, NULL);
-	if(pid < 0) return(-errno);
-	wait_for_stop(pid, SIGSTOP, PTRACE_CONT);
-	regs = altstack_state(NULL, NULL, NULL);
-	if(ptrace_getregs(pid, regs) < 0)
-		panic("Couldn't get altstack state");
-	save_altstack(NULL, UM_SP(regs));
-	kill(pid, SIGKILL);
-	if(waitpid(pid, NULL, WNOHANG) < 0) 
-		printk("setup_altstack : waitpid failed, errno = %d\n",
-		       errno);
-	return(0);
-}
-
-void change_sig(int signal, int on)
-{
-	sigset_t sigset;
-
-	sigemptyset(&sigset);
-	sigaddset(&sigset, signal);
-	sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL);
-}
-
-int get_one_stack(char **stack_out, struct sys_pt_regs *regs_out)
+int get_one_stack(int (*proc)(void *), void *arg, char **stack_out, 
+		  struct sys_pt_regs *regs_out)
 {
 	void *stack;
 	unsigned long sp;
@@ -252,7 +180,7 @@
 		exit(1);		
 	}
 	sp = stack_sp((unsigned long) stack);
-	pid = clone(syscall_handler, (void *) sp, SIGCHLD, NULL);
+	pid = clone(proc, (void *) sp, SIGCHLD | CLONE_VM, arg);
 	if(pid < 0){
 		perror("get_one_stack : couldn't start thread");
 		exit(1);
@@ -265,13 +193,6 @@
 	if(ptrace_getregs(pid, regs_out) < 0){
 		perror("get_one_stack : couldn't get registers");
 		exit(1);
-	}
-	sp = UM_SP(regs_out);
-	sp &= ~sizeof(unsigned long);
-	while(sp < (unsigned long) stack + page_size()){
-		*((unsigned long *) sp) = ptrace(PTRACE_PEEKDATA, pid, 
-						  (void *) sp, NULL);
-		sp += sizeof(unsigned long);
 	}
 	kill(pid, SIGKILL);
 	kill(pid, SIGCONT);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/process_kern.c ac/arch/um/kernel/process_kern.c
--- ac_cur/arch/um/kernel/process_kern.c	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/kernel/process_kern.c	Fri Oct  5 15:06:00 2001
@@ -27,6 +27,8 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
+#include "signal_kern.h"
+#include "signal_user.h"
 
 struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
@@ -236,6 +238,7 @@
 }
 
 char *generic_stack = NULL;
+char *generic_stack_mask = NULL;
 int generic_stack_size = 0;
 struct sys_pt_regs generic_regs;
 struct sys_pt_regs generic_regs_mask;
@@ -251,7 +254,7 @@
 		task->thread.syscall_regs.regs[i] = generic_regs.regs[i];
 		if(generic_regs_mask.regs[i]) 
 			task->thread.syscall_regs.regs[i] += 
-				task->thread.kernel_stack + PAGE_SIZE;
+				task->thread.kernel_stack + 2 * PAGE_SIZE;
 	}
 }
 
@@ -554,72 +557,10 @@
 	current->thread.repeat_syscall = again;
 }
 
-void save_altstack(void *t, unsigned long sp)
-{
-	struct task_struct *task;
-	void *stack;
-	int n;
-
-	if(t == NULL) task = current;
-	else task = t;
-	if(task->thread.altstack != NULL) kfree(task->thread.altstack);
-	n = PAGE_SIZE - (sp & ~PAGE_MASK);
-	stack = kmalloc(n, GFP_KERNEL);
-	if(stack == NULL) panic("save_altstack : kmalloc failed");
-	memcpy(stack, (void *) sp, n);
-	task->thread.altstack = stack;
-	task->thread.altstack_size = n;
-}
-
-struct sys_pt_regs *altstack_state(void *t, void **stack_out, int *size_out)
-{
-	struct task_struct *task;
-
-	if(t == NULL) task = current;
-	else task = t;
-	if(stack_out != NULL) *stack_out = task->thread.altstack;
-	if(size_out != NULL) *size_out = task->thread.altstack_size;
-	return(&task->thread.altstack_regs);
-}
-
-extern int signal_frame_size;
-
-void probe_stack(unsigned long sp)
-{
-	int n, delta;
-
-	delta = signal_frame_size;
-	get_user(n, (int *) sp);
-	put_user(n, (int *) sp);
-	get_user(n, (int *) (sp - delta));
-	put_user(n, (int *) (sp - delta));
-}
-
 void dump_thread(struct pt_regs *regs, struct user *u)
 {
 }
 
-void handling_signal(void *t)
-{
-	struct task_struct *task = t;
-
-	task->thread.signal.state = SIGNAL_HANDLING;
-}
-
-int have_signals(void *t, int altstack)
-{
-	struct task_struct *task;
-
-	if(t == NULL) task = current;
-	else task = t;
-	if(task->thread.signal.state == SIGNAL_PENDING){
-		if((altstack && (task->thread.signal.sp != 0)) ||
-		    (!altstack && (task->thread.signal.sp == 0)))
-			return(1);
-	}
-	return(0);
-}
-
 int switching_modes(void *t)
 {
 	struct task_struct *task;
@@ -638,12 +579,12 @@
 	panic("disable_hlt");
 }
 
+extern int signal_frame_size;
+
 void interrupt_end(void)
 {
 	if(current->need_resched) schedule();
 	do_signal(NULL, NULL);
-	if(current->thread.signal.state != SIGNAL_NONE)
-		probe_stack(UM_SP(&current->thread.process_regs));
 }
 
 void *um_kmalloc(int size)
@@ -676,26 +617,24 @@
 
 EXPORT_SYMBOL(not_implemented);
 
-void setup_kernel_stack(void)
-{
-	struct sys_pt_regs regs1, regs2;
-	char *stack1, *stack2;
-	unsigned long s1, s2, n1, n2, off1, off2;
-	int size, i;
+void *diff_stacks(int size, char *stack1, struct sys_pt_regs *regs1, 
+		  char *stack2, struct sys_pt_regs *regs2, char **mask_out,
+		  struct sys_pt_regs *regs_out, 
+		  struct sys_pt_regs *regs_mask_out)
+{
+	char *mask;
+	void *new;
+	unsigned long s1, s2, n1, n2, off1, off2, i;
 
-	size = get_one_stack(&stack1, &regs1);
-	if(get_one_stack(&stack2, &regs2) != size){
-		printf("setup_kernel_stack : differing stack sizes\n");
-		exit(1);
-	}
 	s1 = (unsigned long) stack1;
 	s2 = (unsigned long) stack2;
-	generic_stack = malloc(size);
-	generic_stack_size = size;
-	if(generic_stack == NULL){
-		perror("setup_kernel_stack : allocating new stack");
+	new = malloc(size);
+	mask = malloc(size);
+	if((new == NULL) || (mask == NULL)){
+		perror("diff_stacks : allocating new stack and mask");
 		exit(1);
 	}
+	memset(mask, 0, size);
 	for(i = PAGE_SIZE - size; i < PAGE_SIZE - sizeof(void *); i++){
 		/* This is horribly word-length- and byte-order-dependent */
 		n1 = stack1[i] | (stack1[i + 1] << 8) |
@@ -716,29 +655,51 @@
 		off1 = n1 & ~PAGE_MASK;
 		off2 = n2 & ~PAGE_MASK;
 		if((off1 == off2) && (off1 > PAGE_SIZE - size)){
-			printf("Found a frame pointer on the stack\n");
-			exit(1);
+			*((unsigned long *) &stack1[i]) -= s1 + PAGE_SIZE;
+			mask[i - (PAGE_SIZE - size)] = 1;
+			i += sizeof(unsigned long);
+		}
+	}
+	memcpy((char *) new, &stack1[PAGE_SIZE - size], size);
+	for(i = 0; i < sizeof(regs1->regs)/sizeof(regs1->regs[0]); i++){
+		regs_out->regs[i] = regs1->regs[i];
+		regs_mask_out->regs[i] = 0;
+		if((regs1->regs[i] == regs2->regs[i]) || 
+		   ((regs1->regs[i] & PAGE_MASK) != s1) || 
+		   ((regs2->regs[i] & PAGE_MASK) != s2)) continue;
+		off1 = regs1->regs[i] & ~PAGE_MASK;
+		off2 = regs2->regs[i] & ~PAGE_MASK;
+		if((off1 == off2) && (off1 >= PAGE_SIZE - size)){
+			regs_out->regs[i] = regs1->regs[i] - s1 - PAGE_SIZE;
+			regs_mask_out->regs[i] = 1;
 		}
 	}
-	memcpy(generic_stack, &stack1[PAGE_SIZE - size], size);
+	*mask_out = mask;
+	return(new);
+}
+
+void setup_kernel_stack(void)
+{
+	struct sys_pt_regs regs1, regs2;
+	char *stack1, *stack2;
+	int size;
+
+	size = get_one_stack(syscall_handler, NULL, &stack1, &regs1);
+	if(get_one_stack(syscall_handler, NULL, &stack2, &regs2) != size){
+		printf("setup_kernel_stack : differing stack sizes\n");
+		exit(1);
+	}
+
+	generic_stack = diff_stacks(size, stack1, &regs1, stack2, &regs2, 
+				    &generic_stack_mask, &generic_regs, 
+				    &generic_regs_mask);
+	generic_stack_size = size;
+
 	if((munmap(stack1, PAGE_SIZE) < 0) || 
 	   (munmap(stack2, PAGE_SIZE) < 0)){
 		perror("setup_kernel_stack : unmapping temp stacks");
 		exit(1);
 	}
-	for(i = 0; i < sizeof(regs1.regs)/sizeof(regs1.regs[0]); i++){
-		generic_regs.regs[i] = regs1.regs[i];
-		generic_regs_mask.regs[i] = 0;
-		if((regs1.regs[i] == regs2.regs[i]) || 
-		   ((regs1.regs[i] & PAGE_MASK) != s1) || 
-		   ((regs2.regs[i] & PAGE_MASK) != s2)) continue;
-		off1 = regs1.regs[i] & ~PAGE_MASK;
-		off2 = regs2.regs[i] & ~PAGE_MASK;
-		if((off1 == off2) && (off1 >= PAGE_SIZE - size)){
-			generic_regs.regs[i] = regs1.regs[i] - s1;
-			generic_regs_mask.regs[i] = 1;
-		}
-	}
 }
 
 int user_context(unsigned long sp)
@@ -791,8 +752,9 @@
 {
 	unsigned long start_stack, end_stack;
 
-	start_stack = (unsigned long) current;
-	end_stack = start_stack + PAGE_SIZE * 4;
+	if(current_task == &init_task) return;
+	start_stack = (unsigned long) current + PAGE_SIZE;
+	end_stack = (unsigned long) current + PAGE_SIZE * 4;
 	protect(physmem, start_stack - physmem, 1, 1, 1);
 	protect(end_stack, high_physmem - end_stack, 1, 1, 1);
 }
@@ -801,10 +763,11 @@
 {
 	unsigned long start_stack, end_stack;
 
-	start_stack = (unsigned long) current;
-	end_stack = start_stack + PAGE_SIZE * 4;
-	protect(physmem, start_stack - physmem, 1, 1, 1);
-	protect(end_stack, high_physmem - end_stack, 1, 1, 1);
+	if(current_task == &init_task) return;
+	start_stack = (unsigned long) current + PAGE_SIZE;
+	end_stack = (unsigned long) current + PAGE_SIZE * 4;
+	protect(physmem, start_stack - physmem, 1, 0, 1);
+	protect(end_stack, high_physmem - end_stack, 1, 0, 1);
 }
 
 /*
diff -Naur -X exclude-files ac_cur/arch/um/kernel/signal_kern.c ac/arch/um/kernel/signal_kern.c
--- ac_cur/arch/um/kernel/signal_kern.c	Fri Oct  5 14:16:42 2001
+++ ac/arch/um/kernel/signal_kern.c	Fri Oct  5 15:15:57 2001
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
@@ -11,15 +11,49 @@
 #include "linux/kernel.h"
 #include "linux/smp_lock.h"
 #include "linux/module.h"
+#include "linux/slab.h"
 #include "asm/signal.h"
 #include "asm/uaccess.h"
 #include "user_util.h"
 #include "kern_util.h"
+#include "signal_kern.h"
+#include "signal_user.h"
 #include "kern.h"
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
+struct sys_pt_regs *signal_state(void *t)
+{
+	struct task_struct *task = t;
+
+	return(&task->thread.altstack_regs);
+}
+
+int probe_stack(unsigned long sp, int delta)
+{
+	int n;
+
+	if((get_user(n, (int *) sp) != 0) ||
+	   (put_user(n, (int *) sp) != 0) ||
+	   (get_user(n, (int *) (sp - delta)) != 0) ||
+	   (put_user(n, (int *) (sp - delta)) != 0))
+		return(-EFAULT);
+	return(0);
+}
+
+int have_signals(void *t)
+{
+	struct task_struct *task;
+	int ret;
+
+	if(t == NULL) task = current;
+	else task = t;
+	ret = (task->thread.signal.state == SIGNAL_PENDING);
+	task->thread.signal.state = SIGNAL_NONE;
+	return(ret);
+}
+
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
 	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
@@ -62,14 +96,17 @@
 /*
  * OK, we're invoking a handler
  */	
-static int handle_signal(struct task_struct *task, unsigned long signr, 
-			 struct k_sigaction *ka, sigset_t *oldset, 
-			 unsigned long *error)
+static int handle_signal(unsigned long signr, struct k_sigaction *ka, 
+			 sigset_t *oldset, unsigned long *error, 
+			 int *again_out)
 {
+	struct signal_context *context;
         __sighandler_t handler;
+	unsigned long sp;
 	sigset_t save;
-        int ret = 0;
+	int frame_size;
 
+	if(again_out) *again_out = 0;
         if((error != NULL) && (*error != 0)){
 		switch (*error) {
 		case -ERESTARTNOHAND:
@@ -83,50 +120,67 @@
 			}
 			/* fallthrough */
 		case -ERESTARTNOINTR:
-			ret = 1;
+			if(again_out) *again_out = 1;
 			break;
 		}
 	}
 	handler = ka->sa.sa_handler;
-
 	save = *oldset;
 
 	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
 
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
-		spin_lock_irq(&task->sigmask_lock);
-		sigorsets(&task->blocked,&current->blocked,&ka->sa.sa_mask);
-		sigaddset(&task->blocked,signr);
-		recalc_sigpending(task);
-		spin_unlock_irq(&task->sigmask_lock);
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,signr);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
 	}
 
-	if(task->thread.signal.state != SIGNAL_NONE)
-		panic("Too many queued signals");
-	task->thread.signal.signal = signr;
-	task->thread.signal.sp = 0;
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! on_sig_stack(UM_SP(&current->thread.process_regs)))
-			task->thread.signal.sp = 
-				current->sas_ss_sp + current->sas_ss_size;
+	sp = UM_SP(&current->thread.process_regs);
+
+	if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+	
+	frame_size = 4 * sizeof(void *) + sizeof(*context) + 
+		4 * sizeof(void *) + signal_stack_size;
+
+	if(probe_stack(sp - sizeof(void *), frame_size) < 0){
+		if(signr == SIGSEGV){
+			struct k_sigaction *ka;
+
+			ka = &current->sig->action[SIGSEGV - 1];
+			ka->sa.sa_handler = SIG_DFL;
+		}
+		force_sig(SIGSEGV, current);
+		return(1);
 	}
 
-	task->thread.signal.handler = (unsigned long) handler;
-	task->thread.signal.state = SIGNAL_PENDING;
-	task->thread.saved_sigs = save;
+	current->thread.signal.signal = signr;
+	current->thread.signal.handler = (unsigned long) handler;
+	current->thread.signal.state = SIGNAL_PENDING;
+
+	sp -= 4 * sizeof(void *) + sizeof(*context);
+	context = (struct signal_context *) sp;
+	if(error != NULL) 
+		UM_SET_SYSCALL_RETURN(&current->thread.process_regs, *error);
+	context->regs = current->thread.process_regs;
+	context->repeat = current->thread.repeat_syscall;
+	context->sigs = save;
+	context->prev = current->thread.signal_context;
+	current->thread.signal_context = context;
 
-	return(ret);
+	sp -= 4 * sizeof(void *);
+	setup_stack(sp, &current->thread.altstack_regs);
+
+	return(0);
 }
 
 /*
  * 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.
  */
 
 static int kern_do_signal(sigset_t *oldset, unsigned long *error, 
@@ -134,7 +188,7 @@
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
-	int again;
+	int err;
 
 	if (!oldset)
 		oldset = &current->blocked;
@@ -235,18 +289,15 @@
 		}
 
 		/* Whee!  Actually deliver the signal.  */
-		again = handle_signal(current, signr, ka, oldset, error);
-		if(again_out && (*again_out == 0)) *again_out = again;
-		return(1);
+		err = handle_signal(signr, ka, oldset, error, again_out);
+		if(!err) return(1);
 	}
 	return(0);
 }
 
 int do_signal(unsigned long *error, int *again_out)
 {
-	if(current->thread.signal.state == SIGNAL_NONE)
-		return(kern_do_signal(NULL, error, again_out));
-	return(0);
+	return(kern_do_signal(NULL, error, again_out));
 }
 
 /*
@@ -299,29 +350,15 @@
 	}
 }
 
-void signal_deliverer(void)
+void signal_deliverer(int sig)
 {
-	struct task_struct *task;
-	struct sys_pt_regs regs;
-	sigset_t sigs;
 	unsigned long handler;
-	int repeat, signal;
+	int signal;
 
-#ifdef CONFIG_SMP
-#error signal_deliverer needs some SMP work
-#else
-	task = current;
-#endif
-	regs = task->thread.process_regs;
-	repeat = task->thread.repeat_syscall;
-	sigs = task->thread.saved_sigs;
-	signal = task->thread.signal.signal;
-	handler = task->thread.signal.handler;
-	task->thread.signal.state = SIGNAL_NONE;
-	signal_handler(task, handler, signal);
-	task->thread.process_regs = regs;
-	task->thread.repeat_syscall = repeat;
-	task->thread.saved_sigs = sigs;
+	stop_pid(getpid());
+	signal = current->thread.signal.signal;
+	handler = current->thread.signal.handler;
+	signal_handler(current, handler, signal);
 }
 
 void set_sigreturn_syscall(int syscall)
@@ -331,14 +368,19 @@
 
 int sys_sigreturn(struct sys_pt_regs regs)
 {
-	sigdelsetmask(&current->thread.saved_sigs, ~_BLOCKABLE);
+	struct signal_context *context = current->thread.signal_context;
+
+	sigdelsetmask(&context->sigs, ~_BLOCKABLE);
 	spin_lock_irq(&current->sigmask_lock);
-	current->blocked = current->thread.saved_sigs;
+	current->blocked = context->sigs;
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
+	current->thread.process_regs = context->regs;
+	current->thread.repeat_syscall = context->repeat;
+	current->thread.signal_context = context->prev;
 	UM_SYSCALL_NR(&current->thread.process_regs) = 
 		current->thread.sigreturn_syscall;
-	return(UM_SYSCALL_RET(&regs));
+	return(UM_SYSCALL_RET(&current->thread.process_regs));
 }
 
 /*
diff -Naur -X exclude-files ac_cur/arch/um/kernel/signal_user.c ac/arch/um/kernel/signal_user.c
--- ac_cur/arch/um/kernel/signal_user.c	Fri Oct  5 14:15:35 2001
+++ ac/arch/um/kernel/signal_user.c	Fri Oct  5 15:01:48 2001
@@ -3,13 +3,150 @@
  * Licensed under the GPL
  */
 
+#include <stdio.h>
+#include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/mman.h>
 #include "user_util.h"
+#include "kern_util.h"
 #include "user.h"
+#include "signal_user.h"
+#include "signal_kern.h"
+#include "sysdep/sigcontext.h"
 
 extern int timer_on;
+
+char *signal_stack = NULL;
+char *signal_stack_mask = NULL;
+int signal_stack_size = 0;
+struct sys_pt_regs signal_regs;
+struct sys_pt_regs signal_regs_mask;
+
+static int setup_signal_tramp(void *stack)
+{
+	set_sigstack(stack, page_size());
+	set_handler(SIGUSR1, signal_deliverer, SA_ONSTACK, -1);
+	usr1_pid(getpid());
+}
+
+void setup_signal_stack(void)
+{
+	struct sys_pt_regs regs1, regs2;
+	char *sigstack1, *sigstack2, *stack1, *stack2;
+	int size;
+
+	sigstack1 = mmap(NULL, page_size(), PROT_READ | PROT_WRITE | PROT_EXEC,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	sigstack2 = mmap(NULL, page_size(), PROT_READ | PROT_WRITE | PROT_EXEC,
+			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if((sigstack1 == MAP_FAILED) || (sigstack2 == MAP_FAILED)){
+		perror("setup_signal_stack : couldn't mmap stacks");
+		exit(1);		
+	}
+	size = get_one_stack(setup_signal_tramp, sigstack1, &stack1, &regs1);
+	if(get_one_stack(setup_signal_tramp, sigstack2, &stack2, 
+			 &regs2) != size){
+		printf("setup_signal_stack : differing stack sizes\n");
+		exit(1);
+	}
+
+	signal_stack = diff_stacks(size, sigstack1, &regs1, sigstack2, &regs2, 
+				   &signal_stack_mask, &signal_regs, 
+				   &signal_regs_mask);
+	signal_stack_size = size;
+
+	if((munmap(sigstack1, page_size()) < 0) || 
+	   (munmap(sigstack2, page_size()) < 0) || 
+	   (munmap(stack1, page_size()) < 0) || 
+	   (munmap(stack2, page_size()) < 0)){
+		perror("setup_signal_stack : unmapping temp stacks");
+		exit(1);
+	}	
+}
+
+void setup_stack(unsigned long stack_top, struct sys_pt_regs *regs_out)
+{
+	char *frame;
+	unsigned long val;
+	int i, n;
+
+	n = sizeof(signal_regs.regs)/sizeof(signal_regs.regs[0]);
+	for(i = 0; i < n; i++){
+		regs_out->regs[i] = signal_regs.regs[i];
+		if(signal_regs_mask.regs[i]) 
+			regs_out->regs[i] += stack_top;
+	}
+
+	frame = (char *) (stack_top - signal_stack_size);
+	for(i = 0; i < signal_stack_size;){
+		if(signal_stack_mask[i] == 0){
+			frame[i] = signal_stack[i];
+			i++;
+		}
+		else {
+			val = *((unsigned long *) &signal_stack[i]);
+			val += stack_top;
+			*((unsigned long *) &frame[i]) = val;
+			i += sizeof(unsigned long);
+		}
+	}
+}
+
+void set_sigstack(void *sig_stack, int size)
+{
+	stack_t stack;
+
+	stack.ss_sp = (__ptr_t) sig_stack;
+	stack.ss_flags = 0;
+	stack.ss_size = size - sizeof(void *);
+	if(sigaltstack(&stack, NULL) != 0)
+		panic("sigaltstack failed");
+}
+
+void set_handler(int sig, void (*handler)(int), int flags, ...)
+{
+	struct sigaction action;
+	va_list ap;
+	int mask;
+
+	va_start(ap, flags);
+	action.sa_handler = handler;
+	sigemptyset(&action.sa_mask);
+	while((mask = va_arg(ap, int)) != -1){
+		sigaddset(&action.sa_mask, mask);
+	}
+	action.sa_flags = flags;
+	action.sa_restorer = NULL;
+	if(sigaction(sig, &action, NULL) < 0)
+		panic("sigaction failed");
+}
+
+void change_sig(int signal, int on)
+{
+	sigset_t sigset;
+
+	sigemptyset(&sigset);
+	sigaddset(&sigset, signal);
+	sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL);
+}
+
+void signal_handler(void *task, unsigned long h, int sig)
+{
+	void (*handler)(int, struct sigcontext);
+	void *regs;
+	unsigned long cr2;
+	int err;
+	UM_ALLOCATE_SC(sc);
+
+	regs = process_state(task, &cr2, &err);
+	fill_in_sigcontext(&sc, regs, cr2, err);
+	handler = (void (*)(int, struct sigcontext)) h;
+	(*handler)(sig, sc);
+}
 
 static void change_signals(int type)
 {
diff -Naur -X exclude-files ac_cur/arch/um/kernel/syscall_kern.c ac/arch/um/kernel/syscall_kern.c
--- ac_cur/arch/um/kernel/syscall_kern.c	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/kernel/syscall_kern.c	Fri Oct  5 15:01:48 2001
@@ -12,6 +12,7 @@
 #include "linux/shm.h"
 #include "linux/sys.h"
 #include "linux/unistd.h"
+#include "linux/slab.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/ipc.h"
@@ -300,17 +301,8 @@
 
 int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 {
-        unsigned long old_sp = current->sas_ss_sp;
-	int old_size = current->sas_ss_size, res;
-
-	res = do_sigaltstack(uss, uoss, UM_SP(&current->thread.process_regs));
-	if((res == 0) && (current->sas_ss_sp != 0) && 
-	   ((current->sas_ss_sp != old_sp) || 
-	    (current->sas_ss_size != old_size))){
-	        res = setup_altstack(current->sas_ss_sp, 
-				     current->sas_ss_size);
-	}
-	return(res);
+	return(do_sigaltstack(uss, uoss, 
+			      UM_SP(&current->thread.process_regs)));
 }
 
 int nsyscalls = 0;
diff -Naur -X exclude-files ac_cur/arch/um/kernel/syscall_user.c ac/arch/um/kernel/syscall_user.c
--- ac_cur/arch/um/kernel/syscall_user.c	Fri Oct  5 14:15:35 2001
+++ ac/arch/um/kernel/syscall_user.c	Fri Oct  5 15:01:48 2001
@@ -5,7 +5,6 @@
 
 /* XXX FIXME : Ensure that SIGIO and SIGVTALRM can't happen immediately
  * after setting up syscall stack
- * SIGIO and SIGVTALRM should block SIGUSR2
  * block SIGVTALRM in any code that's under wait_for_stop
  */
 
@@ -26,6 +25,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
+#include "signal_kern.h"
 #include "sysdep/ptrace.h"
 
 /* XXX Bogus */
@@ -43,20 +43,8 @@
 
 int syscall_index = 0;
 
-void process_stack_handler(int sig)
-{
-	signal_deliverer();
-}
-
-int alt_stack_handler(void *arg)
-{
-	ptrace(PTRACE_TRACEME, 0, 0, 0);
-	kill(getpid(), SIGSTOP);
-	signal_deliverer();
-	return(0);
-}
-
 extern int timer_ready;
+extern int signal_frame_size;
 
 int syscall_handler(void *unused)
 {
@@ -90,7 +78,7 @@
 	syscall_record[index].result = result;
 	gettimeofday(&syscall_record[index].end, NULL);
 	ret_from_sys_call(NULL);
-	if(have_signals(NULL, 0)) probe_stack(UM_SP(regs));
+
 	/* XXX 
 	 * This is a race, set_user_thread has to be called with signals off
 	 */
@@ -99,15 +87,13 @@
 	return(0);
 }
 
-int exit_kernel(int pid, void *task, int *signal_out)
+int exit_kernel(int pid, void *task)
 {
 	void *stack;
 	struct sys_pt_regs *regs;
-	unsigned long sp;
 	int tracing, again, n, restore;
 
 	tracing = 1;
-	*signal_out = 0;
 	again = get_repeat_syscall(task);
 	set_repeat_syscall(0);
 	restore = get_restore_regs(task);
@@ -116,19 +102,11 @@
 		if(ptrace_setregs(pid, regs) < 0)
 			tracer_panic("Couldn't restore registers");
 	}
-	if(have_signals(task, 0)){
-		handling_signal(task);
-		if(!restore) ptrace_getregs(pid, regs);
-		*signal_out = SIGUSR2;
-	}
-	else if(have_signals(task, 1)){
-		handling_signal(task);
+	if(have_signals(task)){
 		if(!restore) ptrace_getregs(pid, regs);
-		regs = altstack_state(task, &stack, &n);
+		regs = signal_state(task);
 		if(ptrace_setregs(pid, regs) < 0)
 			panic("Couldn't set alternate stack state");
-		sp = um_virt_to_phys(task, UM_SP(regs));
-		memcpy((void *) sp, stack, n);
 	}
 	else if(again){
 		regs = syscall_state(task, &stack, &n);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/time.c ac/arch/um/kernel/time.c
--- ac_cur/arch/um/kernel/time.c	Fri Oct  5 14:15:35 2001
+++ ac/arch/um/kernel/time.c	Fri Oct  5 15:01:48 2001
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
@@ -16,6 +16,7 @@
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
+#include "signal_user.h"
 
 extern struct timeval xtime;
 
@@ -60,8 +61,7 @@
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
 	set_handler(SIGALRM, (__sighandler_t) alarm_handler, 
-		    SA_NODEFER | SA_RESTART,
-		    SIGUSR1, SIGIO, SIGUSR2, -1);
+		    SA_NODEFER | SA_RESTART, SIGUSR1, SIGIO, -1);
 	set_interval(ITIMER_REAL);
 }
 
diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_kern.c ac/arch/um/kernel/trap_kern.c
--- ac_cur/arch/um/kernel/trap_kern.c	Fri Oct  5 14:43:33 2001
+++ ac/arch/um/kernel/trap_kern.c	Fri Oct  5 15:01:48 2001
@@ -49,20 +49,6 @@
 		else if(expand_stack(vma, address)) ok = 0;
 	}
 	if(!ok){
-		if(current->thread.signal.state == SIGNAL_HANDLING){
-			/* The signal delivery failed because the SIGUSR2
-			 * frame couldn't be constructed
-			 */
-			current->thread.signal.state = SIGNAL_NONE;
-			if(current->thread.signal.signal == SIGSEGV){
-				struct k_sigaction *ka;
-
-				ka = &current->sig->action[SIGSEGV - 1];
-				ka->sa.sa_handler = SIG_DFL;
-			}
-			force_sig(SIGSEGV, current);
-			return(0);
-		}
 		if (current->thread.fault_catcher != NULL) {
 			current->thread.fault_addr = (void *) address;
 			up_read(&mm->mmap_sem);
diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_user.c ac/arch/um/kernel/trap_user.c
--- ac_cur/arch/um/kernel/trap_user.c	Fri Oct  5 14:51:24 2001
+++ ac/arch/um/kernel/trap_user.c	Fri Oct  5 15:01:48 2001
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
@@ -102,6 +102,7 @@
 	int last_index, proc_id, save_errno = 0;
 
 	setup_kernel_stack();
+	setup_signal_stack();
 	calc_sigframe_size();
 	signal(SIGSEGV, signal_segv);
 	signal(SIGUSR1, signal_usr1);
@@ -183,7 +184,7 @@
 				case OP_SWITCH:
 					continue;
 				case OP_TRACE_ON:
-					tracing = exit_kernel(pid, task, &sig);
+					tracing = exit_kernel(pid, task);
 					break;
 				case OP_TRACE_OFF:
 					tracing = 0;
@@ -251,6 +252,7 @@
 					child_signal(pid, status);
 					continue;
 				}
+                                tracing = 0;
 				break;
 			}
 			set_tracing(task, tracing);
@@ -324,6 +326,7 @@
 {
 	int user_mode, save_errno = errno, save_timer = timer_on;
 
+	unprotect_kernel_mem();
 	timer_on = 0;
 	user_mode = user_context(SC_SP(&sc));
 	if(user_mode) timer_ready = 1;
@@ -343,6 +346,7 @@
 {
 	int user_mode, save_errno = errno, save_timer = timer_on;
 
+	unprotect_kernel_mem();
 	timer_on = 0;
 	user_mode = user_context(SC_SP(&sc));
 	if(user_mode) timer_ready = 1;
diff -Naur -X exclude-files ac_cur/include/asm-um/processor-generic.h ac/include/asm-um/processor-generic.h
--- ac_cur/include/asm-um/processor-generic.h	Fri Oct  5 14:45:08 2001
+++ ac/include/asm-um/processor-generic.h	Fri Oct  5 15:07:24 2001
@@ -11,9 +11,9 @@
 struct task_struct;
 
 #include "linux/config.h"
+#include "linux/signal.h"
 #include "asm/segment.h"
 #include "asm/ptrace.h"
-#include "asm/arch/signal.h"
 
 struct mm_struct;
 
@@ -21,7 +21,6 @@
 
 #define SIGNAL_NONE 0
 #define SIGNAL_PENDING 1
-#define SIGNAL_HANDLING 2
 
 struct thread_struct {
 	int extern_pid;
@@ -31,16 +30,13 @@
 	struct {
 		int state;
 		int signal;
-		unsigned long sp;
 		unsigned long handler;
 	} signal;
-	sigset_t saved_sigs;
+	struct signal_context *signal_context;
 	int nsyscalls;
 	struct sys_pt_regs process_regs;
 	struct sys_pt_regs syscall_regs;
 	struct sys_pt_regs altstack_regs;
-	void *altstack;
-	int altstack_size;
 	unsigned long cr2;
 	int err;
 	int repeat_syscall;
@@ -110,16 +106,12 @@
 	signal: { \
                 state:	SIGNAL_NONE, \
 		signal: 0, \
-		sp:	0, \
 		handler:0 \
 	}, \
-        saved_sigs:     { { 0 } }, \
 	nsyscalls:	0, \
         process_regs:   EMPTY_REGS, \
 	syscall_regs:	EMPTY_REGS, \
 	altstack_regs:	EMPTY_REGS, \
-	altstack:	NULL, \
-	altstack_size:	0, \
 	cr2:		0, \
 	err:		0, \
 	repeat_syscall:	0, \
diff -Naur -X exclude-files ac_cur/include/asm-um/signal.h ac/include/asm-um/signal.h
--- ac_cur/include/asm-um/signal.h	Fri Oct  5 14:45:08 2001
+++ ac/include/asm-um/signal.h	Fri Oct  5 15:07:24 2001
@@ -1,6 +1,14 @@
 #ifndef __UM_SIGNAL_H
 #define __UM_SIGNAL_H
 
+#include "sysdep/ptrace.h"
 #include "asm/arch/signal.h"
+
+struct signal_context {
+	struct sys_pt_regs regs;
+	sigset_t sigs;
+	int repeat;
+	struct signal_context *prev;
+};
 
 #endif