From: george anzinger The recently-added code which avoids a lockup when a timer handler re-adds the timer right now can be simplified. If we change __run_timers() to increment base->timer_jiffies _before_ running the timers, then any re-additions will not be inserted in the list which __run_timers is presently walking. (forwarded by akpm@digeo.com) kernel/timer.c | 22 ++-------------------- 1 files changed, 2 insertions(+), 20 deletions(-) diff -puN kernel/timer.c~timer-lockup-fix-simplification kernel/timer.c --- 25/kernel/timer.c~timer-lockup-fix-simplification 2003-03-20 00:40:57.000000000 -0800 +++ 25-akpm/kernel/timer.c 2003-03-20 00:40:57.000000000 -0800 @@ -55,7 +55,6 @@ struct tvec_t_base_s { spinlock_t lock; unsigned long timer_jiffies; struct timer_list *running_timer; - struct list_head *run_timer_list_running; tvec_root_t tv1; tvec_t tv2; tvec_t tv3; @@ -100,12 +99,6 @@ static inline void check_timer(struct ti check_timer_failed(timer); } -/* - * If a timer handler re-adds the timer with expires == jiffies, the timer - * running code can lock up. So here we detect that situation and park the - * timer onto base->run_timer_list_running. It will be added to the main timer - * structures later, by __run_timers(). - */ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) { @@ -113,9 +106,7 @@ static void internal_add_timer(tvec_base unsigned long idx = expires - base->timer_jiffies; struct list_head *vec; - if (base->run_timer_list_running) { - vec = base->run_timer_list_running; - } else if (idx < TVR_SIZE) { + if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { @@ -405,7 +396,6 @@ static inline void __run_timers(tvec_bas spin_lock_irq(&base->lock); while (time_after_eq(jiffies, base->timer_jiffies)) { - LIST_HEAD(deferred_timers); struct list_head *head; int index = base->timer_jiffies & TVR_MASK; @@ -417,7 +407,7 @@ static inline void __run_timers(tvec_bas (!cascade(base, &base->tv3, INDEX(1))) && !cascade(base, &base->tv4, INDEX(2))) cascade(base, &base->tv5, INDEX(3)); - base->run_timer_list_running = &deferred_timers; + ++base->timer_jiffies; repeat: head = base->tv1.vec + index; if (!list_empty(head)) { @@ -436,14 +426,6 @@ repeat: spin_lock_irq(&base->lock); goto repeat; } - base->run_timer_list_running = NULL; - ++base->timer_jiffies; - while (!list_empty(&deferred_timers)) { - timer = list_entry(deferred_timers.prev, - struct timer_list, entry); - list_del(&timer->entry); - internal_add_timer(base, timer); - } } set_running_timer(base, NULL); spin_unlock_irq(&base->lock); _