diff -urN 2.3.46pre1/kernel/timer.c timer-robusteness/kernel/timer.c --- 2.3.46pre1/kernel/timer.c Fri Feb 11 00:05:39 2000 +++ timer-robusteness/kernel/timer.c Tue Feb 15 18:10:14 2000 @@ -101,6 +101,8 @@ (struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5 }; +static struct timer_list ** run_timer_list_running; + #define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0])) static unsigned long timer_jiffies = 0; @@ -125,7 +127,13 @@ unsigned long idx = expires - timer_jiffies; struct timer_list ** vec; - if (idx < TVR_SIZE) { + if (run_timer_list_running) { + if ((signed) idx < 0) + printk(KERN_WARNING __FUNCTION__ + ": potential recursion idx %ld from %p\n", + (signed) idx, __builtin_return_address(0)); + vec = run_timer_list_running; + } else if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { @@ -266,13 +274,14 @@ { spin_lock_irq(&timerlist_lock); while ((long)(jiffies - timer_jiffies) >= 0) { - struct timer_list *timer; + struct timer_list *timer, * queued = NULL; if (!tv1.index) { int n = 1; do { cascade_timers(tvecs[n]); } while (tvecs[n]->index == 1 && ++n < NOOF_TVECS); } + run_timer_list_running = &queued; while ((timer = tv1.vec[tv1.index])) { void (*fn)(unsigned long) = timer->function; unsigned long data = timer->data; @@ -283,8 +292,14 @@ fn(data); spin_lock_irq(&timerlist_lock); } + run_timer_list_running = NULL; ++timer_jiffies; tv1.index = (tv1.index + 1) & TVR_MASK; + while (queued) { + timer = queued; + queued = queued->next; + internal_add_timer(timer); + } } spin_unlock_irq(&timerlist_lock); }