diff -Naur -X exclude-files ac_cur/arch/um/include/process.h ac/arch/um/include/process.h
--- ac_cur/arch/um/include/process.h	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/include/process.h	Mon Jun 25 13:57:30 2001
@@ -10,6 +10,7 @@
 
 extern void sig_handler(int sig, struct sigcontext sc);
 extern void irq_handler(int sig, struct sigcontext sc);
+extern void alarm_handler(int sig, struct sigcontext sc);
 
 #endif
 
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	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/irq_user.c	Mon Jun 25 14:00:17 2001
@@ -147,10 +147,10 @@
 	int flags;
 
 	flags = on_sigstack ? SA_ONSTACK : 0;
-	set_handler(SIGVTALRM, (__sighandler_t) irq_handler, flags, SIGUSR1,
-		    SIGVTALRM, SIGALRM, SIGIO, SIGUSR2, -1);
+	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, 
+		    flags | SA_NODEFER, SIGUSR1, SIGIO, SIGUSR2, -1);
 	set_handler(SIGIO, (__sighandler_t) irq_handler, flags, SIGUSR1, 
-		    SIGVTALRM, SIGALRM, SIGIO, SIGUSR2, -1);
+		    SIGIO, SIGUSR2, -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	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/process.c	Mon Jun 25 14:01:45 2001
@@ -83,12 +83,12 @@
 		set_sigstack(sig_stack);
 		flags = SA_ONSTACK;
 	}
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, SIGVTALRM,
-		    SIGUSR1, SIGALRM, SIGIO, -1);
-	set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, SIGVTALRM, 
-		    SIGUSR1, SIGALRM, SIGIO, -1);
-	set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, SIGVTALRM, 
-		    SIGUSR1, SIGALRM, SIGIO, -1);
+	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+		    SIGUSR1, SIGIO, -1);
+	set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, 
+		    SIGUSR1, SIGIO, -1);
+	set_handler(SIGFPE, (__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);
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	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/signal_user.c	Mon Jun 25 14:02:05 2001
@@ -8,13 +8,20 @@
 #include "user_util.h"
 #include "user.h"
 
+extern int timer_on;
+
 static void change_signals(int type)
 {
 	sigset_t mask;
 
 	sigemptyset(&mask);
-	sigaddset(&mask, SIGVTALRM);
-	sigaddset(&mask, SIGALRM);
+	if(type == SIG_BLOCK)
+		timer_on = 0;
+	else {
+		timer_on = 1;
+		sigaddset(&mask, SIGVTALRM);
+		sigaddset(&mask, SIGALRM);
+	}
 	sigaddset(&mask, SIGIO);
 	if(sigprocmask(type, &mask, NULL) < 0)
 		panic("Failed to change signal mask");
@@ -40,6 +47,7 @@
 	sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
 	sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
 	sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
+	if(timer_on) sigs |= 1 << SIGVTALRM_BIT;
 	return(sigs);
 }
 
@@ -51,6 +59,7 @@
 	sigemptyset(&mask);
 	if(enable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO);
 	if(enable & (1 << SIGVTALRM_BIT)){
+		timer_on = 1;
 		sigaddset(&mask, SIGVTALRM);
 		sigaddset(&mask, SIGALRM);
 	}
@@ -60,8 +69,7 @@
 	sigemptyset(&mask);
 	if((enable & (1 << SIGIO_BIT)) == 0) sigaddset(&mask, SIGIO);
 	if((enable & (1 << SIGVTALRM_BIT)) == 0){
-		sigaddset(&mask, SIGVTALRM);
-		sigaddset(&mask, SIGALRM);
+		timer_on = 0;
 	}
 	if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
 		panic("Failed to block signals");
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	Mon Jun 25 13:45:45 2001
+++ ac/arch/um/kernel/syscall_user.c	Mon Jun 25 14:02:33 2001
@@ -56,6 +56,8 @@
 	return(0);
 }
 
+extern int timer_ready;
+
 int syscall_handler(void *unused)
 {
 	struct sys_pt_regs *regs;
@@ -63,6 +65,7 @@
 	int index, syscall, again;
 
 	kill(getpid(), SIGSTOP);
+	timer_ready = 1;
 	syscall_trace();
 	lock_syscall();
 	if(syscall_index == 1024) syscall_index = 0;
@@ -90,6 +93,7 @@
 	/* XXX 
 	 * This is a race, set_user_thread has to be called with signals off
 	 */
+	timer_ready = 0;
 	set_user_thread(NULL, 1, 1);
 	return(0);
 }
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	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/time.c	Mon Jun 25 14:36:15 2001
@@ -52,8 +52,8 @@
 {
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
-	set_handler(SIGALRM, (__sighandler_t) irq_handler, 0, SIGUSR1, 
-		    SIGVTALRM, SIGALRM, SIGIO, SIGUSR2, -1);
+	set_handler(SIGALRM, (__sighandler_t) alarm_handler, SA_NODEFER,
+		    SIGUSR1, SIGIO, SIGUSR2, -1);
 	set_interval(ITIMER_REAL);
 }
 
@@ -67,7 +67,8 @@
 void set_timers(int set_signal)
 {
 	if(set_signal){
-		if(signal(SIGVTALRM, (__sighandler_t) irq_handler) == SIG_ERR)
+		if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == 
+		   SIG_ERR)
 			panic("Couldn't set SIGVTALRM handler");
 		set_interval(ITIMER_VIRTUAL);
 	}
diff -Naur -X exclude-files ac_cur/arch/um/kernel/time_kern.c ac/arch/um/kernel/time_kern.c
--- ac_cur/arch/um/kernel/time_kern.c	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/time_kern.c	Mon Jun 25 14:09:22 2001
@@ -25,10 +25,16 @@
 
 int timer_irq_inited = 0;
 
+int timer_on = 0;
+int timer_ready = 0;
+int missed_ticks = 0;
+
 void timer_irq(int user_mode)
 {
-	if(!timer_irq_inited) return;
-	do_IRQ(TIMER_IRQ, user_mode);
+	int ticks = missed_ticks;
+
+	missed_ticks = 0;
+	while(ticks--) do_IRQ(TIMER_IRQ, user_mode);
 }
 
 void boot_timer_handler(int sig)
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	Mon Jun 25 13:30:40 2001
+++ ac/arch/um/kernel/trap_user.c	Mon Jun 25 14:09:54 2001
@@ -299,6 +299,8 @@
 	     usermode);
 }
 
+extern int timer_ready, timer_on;
+
 static void (*handlers[])(int, void *, int) = {
 	[ SIGTRAP ] relay_signal,
 	[ SIGFPE ] relay_signal,
@@ -310,9 +312,11 @@
 
 void irq_handler(int sig, struct sigcontext sc)
 {
-	int user_mode, save_errno = errno;
+	int user_mode, save_errno = errno, save_timer = timer_on;
 
+	timer_on = 0;
 	user_mode = user_context(SC_SP(&sc));
+	if(user_mode) timer_ready = 1;
 	change_sig(SIGUSR1, 1);
 	(*handlers[sig])(sig, &sc, user_mode);
 	if(user_mode) interrupt_end();
@@ -320,23 +324,42 @@
 	change_sig(SIGUSR1, 0);
 	set_user_thread(NULL, user_mode, 0);
 	errno = save_errno;
+	if(user_mode) timer_ready = 0;
+	timer_on = save_timer;
 }
 
 void sig_handler(int sig, struct sigcontext sc)
 {
-	int user_mode, save_errno = errno;
+	int user_mode, save_errno = errno, save_timer = timer_on;
 
+	timer_on = 0;
 	user_mode = user_context(SC_SP(&sc));
+	if(user_mode) timer_ready = 1;
 	change_sig(SIGUSR1, 1);
 	unblock_signals();
 	(*handlers[sig])(sig, &sc, user_mode);
-	if(user_mode){
-		interrupt_end();
-		block_signals();
-	}
+	if(user_mode) interrupt_end();
+	block_signals();
 	change_sig(SIGUSR1, 0);
 	set_user_thread(NULL, user_mode, 0);
 	errno = save_errno;
+	if(user_mode) timer_ready = 0;
+	timer_on = save_timer;
+}
+
+extern int timer_irq_inited, missed_ticks;
+
+void alarm_handler(int sig, struct sigcontext sc)
+{
+	int user_mode;
+
+	if(!timer_irq_inited) return;
+	missed_ticks++;
+	user_mode = user_context(SC_SP(&sc));
+	if(!user_mode && !timer_ready) return;
+	if(!timer_on) return;
+	irq_handler(sig, sc);
+	timer_ready = 1;
 }
 
 void do_longjmp(void *p)