# Use the genirq infrastructure correctly.
#
# Get rid of init_irq_signals
#	init_new_thread_signals
#		start_uml_skas
#		userspace_tramp
#		exec_tramp - tt
#		do_new_thread_handler - tt
# init_new_thread_signals should probably go away, except that this requires
#    tt mode to go away first
#
# See why a separate boot_timer_handler is needed
#	do_boot_timer_handler
#		boot_timer_handler
#	* merge_time_init
#
# See why SIGIO and SIGVTALRM mask off different sets of signals
#	* they don't any more
#
# See if they need to mask off other signals at all
#
# user_time_init should probably go away
#	* merge-time-init
#
# Look at signal enabling/disabling in unblock_signals and the handlers
#
# Get rid of timer_irq_inited
#	* no-timer-irq-inited
#
# Merge timer_init and time_init
#	* merge-time-init
#
# startup_sigvtalrm needs to call set_interval
#	* genirq
#
# disable_timer should return int and not play with signals
#	disable_timer
#		error path of setup_sigvtalrm
#		just before exiting
#	* genirq
#
#	enable_timer
#		tt exec, separate from unblock_signals
#		tt new thread, separate from local_irq_enable
#		tt finish fork, separate from local_irq_enable
#		skas userspace_tramp
#
# uml_idle_timer move to tt
#	* idle-timer

Index: linux-2.6.17/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.17.orig/arch/um/kernel/irq.c	2007-11-19 16:42:39.000000000 -0500
+++ linux-2.6.17/arch/um/kernel/irq.c	2007-11-19 21:41:03.000000000 -0500
@@ -363,45 +363,42 @@ EXPORT_SYMBOL(reactivate_fd);
  * hw_interrupt_type must define (startup || enable) &&
  * (shutdown || disable) && end
  */
-static void dummy(unsigned int irq)
+static void noop(unsigned int irq)
 {
 }
 
 /* This is used for everything else than the timer. */
-static struct hw_interrupt_type normal_irq_type = {
-	.typename = "SIGIO",
-	.release = free_irq_by_irq_and_dev,
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+static struct irq_chip SIGIO_irq_type = {
+	.typename	= "SIGIO",
+	.release	= free_irq_by_irq_and_dev,
+	.startup	= startup_sigio,
+	.shutdown	= shutdown_sigio,
+	.ack		= noop, /* Required, but doesn't need to do anything */
+	.unmask		= mask_sigio,
+	.mask		= unmask_sigio,
+	.end		= noop,
 };
 
-static struct hw_interrupt_type SIGVTALRM_irq_type = {
+static struct irq_chip SIGVTALRM_irq_type = {
 	.typename = "SIGVTALRM",
 	.release = free_irq_by_irq_and_dev,
-	.shutdown = dummy, /* never called */
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+	.startup	= startup_sigvtalrm,
+	.shutdown	= shutdown_sigvtalrm,
+	.ack		= noop, /* Required, but doesn't need to do anything */
+	.unmask		= unmask_sigvtalrm,
+	.mask		= mask_sigvtalrm,
+	.end		= noop,
 };
 
 void __init init_IRQ(void)
 {
+	struct irq_chip *chip;
 	int i;
 
-	irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
-	irq_desc[TIMER_IRQ].action = NULL;
-	irq_desc[TIMER_IRQ].depth = 1;
-	irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
-	enable_irq(TIMER_IRQ);
-	for (i = 1; i < NR_IRQS; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].chip = &normal_irq_type;
-		enable_irq(i);
+	for(i = 0; i < NR_IRQS; i++){
+		chip = (i == TIMER_IRQ) ? &SIGVTALRM_irq_type :
+			&SIGIO_irq_type;
+		set_irq_chip_and_handler(i, chip, handle_edge_irq);
 	}
 }
 
Index: linux-2.6.17/arch/um/os-Linux/signal.c
===================================================================
--- linux-2.6.17.orig/arch/um/os-Linux/signal.c	2007-11-19 21:40:33.000000000 -0500
+++ linux-2.6.17/arch/um/os-Linux/signal.c	2007-11-19 21:45:47.000000000 -0500
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <strings.h>
+#include <sys/time.h>
 #include "os.h"
 #include "sysdep/barrier.h"
 #include "sysdep/sigcontext.h"
@@ -279,3 +280,97 @@ int set_signals(int enable)
 
 	return ret;
 }
+
+static int masked[] = { SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM };
+
+static int enable_signal(int sig, void (*handler)(int, struct sigcontext *))
+{
+	struct sigaction action;
+	sigset_t sig_mask;
+	int i, err;
+
+	handlers[sig] = handler;
+	action.sa_handler = hard_handler;
+
+	sigemptyset(&action.sa_mask);
+	for(i = 0; i < sizeof(masked) / sizeof(masked[0]); i++)
+		sigaddset(&action.sa_mask, masked[i]);
+
+	action.sa_flags = SA_ONSTACK;
+	action.sa_restorer = NULL;
+	err = sigaction(sig, &action, NULL);
+	if(err){
+		err = -errno;
+		printk("sigaction failed - errno = %d\n", errno);
+		goto err_ign;
+	}
+
+	sigemptyset(&sig_mask);
+	sigaddset(&sig_mask, sig);
+	if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0){
+		err = -errno;
+		printk("sigprocmask failed - errno = %d\n", errno);
+		goto err;
+	}
+
+	return 0;
+
+err_ign:
+	signal(sig, SIG_IGN);
+err:
+	return err;
+}
+
+/* XXX Need to ensure that these only execute on CPU 0 */
+
+unsigned int startup_sigio(unsigned int irq)
+{
+	return enable_signal(SIGIO, sig_handler);
+}
+
+void shutdown_sigio(unsigned int irq)
+{
+}
+
+void unmask_sigio(unsigned int irq)
+{
+	signals_enabled |= SIGIO_MASK;
+}
+
+void mask_sigio(unsigned int irq)
+{
+	signals_enabled &= ~SIGIO_MASK;
+}
+
+unsigned int startup_sigvtalrm(unsigned int irq)
+{
+	int err;
+
+	err = enable_signal(SIGVTALRM, alarm_handler);
+	if(err)
+		return err;
+
+	err = set_interval();
+	if (err)
+		goto out_ign_vtalrm;
+
+	return 0;
+
+out_ign_vtalrm:
+	signal(SIGALRM, SIG_IGN);
+	return err;
+}
+
+void shutdown_sigvtalrm(unsigned int irq)
+{
+}
+
+void unmask_sigvtalrm(unsigned int irq)
+{
+	signals_enabled |= SIGVTALRM_MASK;
+}
+
+void mask_sigvtalrm(unsigned int irq)
+{
+	signals_enabled &= ~SIGVTALRM_MASK;
+}
Index: linux-2.6.17/arch/um/include/os.h
===================================================================
--- linux-2.6.17.orig/arch/um/include/os.h	2007-11-19 21:36:34.000000000 -0500
+++ linux-2.6.17/arch/um/include/os.h	2008-01-07 12:50:58.000000000 -0500
@@ -278,6 +278,14 @@ extern void block_signals(void);
 extern void unblock_signals(void);
 extern int get_signals(void);
 extern int set_signals(int enable);
+extern unsigned int startup_sigio(unsigned int irq);
+extern void shutdown_sigio(unsigned int irq);
+extern void unmask_sigio(unsigned int irq);
+extern void mask_sigio(unsigned int irq);
+extern unsigned int startup_sigvtalrm(unsigned int irq);
+extern void shutdown_sigvtalrm(unsigned int irq);
+extern void unmask_sigvtalrm(unsigned int irq);
+extern void mask_sigvtalrm(unsigned int irq);
 
 /* trap.c */
 extern void os_fill_handlinfo(struct kern_handlers h);
@@ -292,11 +300,11 @@ extern void os_dump_core(void);
 
 /* time.c */
 extern void idle_sleep(unsigned long long nsecs);
-extern int set_interval(void);
 extern int timer_one_shot(int ticks);
 extern long long disable_timer(void);
 extern void uml_idle_timer(void);
 extern long long os_nsecs(void);
+extern int set_interval(void);
 
 /* skas/mem.c */
 extern long run_syscall_stub(struct mm_id * mm_idp,
Index: linux-2.6.17/arch/um/os-Linux/main.c
===================================================================
--- linux-2.6.17.orig/arch/um/os-Linux/main.c	2007-11-19 11:58:10.000000000 -0500
+++ linux-2.6.17/arch/um/os-Linux/main.c	2007-11-19 21:41:03.000000000 -0500
@@ -161,7 +161,7 @@ int __init main(int argc, char **argv, c
 	 * some time) and cause a segfault.
 	 */
 
-	/* stop timers and set SIGVTALRM to be ignored */
+	/* stop timers */
 	disable_timer();
 
 	/* disable SIGIO for the fds and set SIGIO to be ignored */