
From: george anzinger <george@mvista.com>

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);

_
