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)