# 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 #include #include +#include #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 */