patch-2.4.0-test3 linux/kernel/timer.c

Next file: linux/lib/Makefile
Previous file: linux/kernel/sysctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/kernel/timer.c linux/kernel/timer.c
@@ -160,7 +160,9 @@
 	list_add(&timer->list, vec->prev);
 }
 
+/* Initialize both explicitly - let's try to have them in the same cache line */
 spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
+volatile struct timer_list *running_timer = NULL;
 
 void add_timer(struct timer_list *timer)
 {
@@ -233,11 +235,12 @@
 		spin_lock_irqsave(&timerlist_lock, flags);
 		ret += detach_timer(timer);
 		timer->list.next = timer->list.prev = 0;
-		running = timer->running;
+		running = timer_is_running(timer);
 		spin_unlock_irqrestore(&timerlist_lock, flags);
 
 		if (!running)
-			return ret;
+			break;
+
 		timer_synchronize(timer);
 	}
 
@@ -295,10 +298,11 @@
 
 			detach_timer(timer);
 			timer->list.next = timer->list.prev = NULL;
-			timer_set_running(timer);
+			timer_enter(timer);
 			spin_unlock_irq(&timerlist_lock);
 			fn(data);
 			spin_lock_irq(&timerlist_lock);
+			timer_exit();
 			goto repeat;
 		}
 		++timer_jiffies; 
@@ -307,25 +311,6 @@
 	spin_unlock_irq(&timerlist_lock);
 }
 
-
-static inline void run_old_timers(void)
-{
-	struct timer_struct *tp;
-	unsigned long mask;
-
-	for (mask = 1, tp = timer_table+0 ; mask ; tp++,mask += mask) {
-		if (mask > timer_active)
-			break;
-		if (!(mask & timer_active))
-			continue;
-		if (time_after(tp->expires, jiffies))
-			continue;
-		timer_active &= ~mask;
-		tp->fn();
-		sti();
-	}
-}
-
 spinlock_t tqueue_lock = SPIN_LOCK_UNLOCKED;
 
 void tqueue_bh(void)
@@ -338,9 +323,6 @@
 	run_task_queue(&tq_immediate);
 }
 
-unsigned long timer_active;
-struct timer_struct timer_table[32];
-
 /*
  * this routine handles the overflow of the microsecond field
  *
@@ -577,27 +559,32 @@
 	do_it_prof(p, ticks);
 }	
 
-static void update_process_times(unsigned long ticks, unsigned long system)
+/*
+ * Called from the timer interrupt handler to charge one tick to the current 
+ * process.  user_tick is 1 if the tick is user time, 0 for system.
+ */
+static void update_process_times(int user_tick)
 {
 /*
  * SMP does this on a per-CPU basis elsewhere
  */
 #ifndef  CONFIG_SMP
-	struct task_struct * p = current;
-	unsigned long user = ticks - system;
+	struct task_struct *p = current;
+	int system = !user_tick;
+
 	if (p->pid) {
-		p->counter -= ticks;
-		if (p->counter <= 0) {
+		if (--p->counter <= 0) {
 			p->counter = 0;
 			p->need_resched = 1;
 		}
 		if (p->priority < DEF_PRIORITY)
-			kstat.cpu_nice += user;
+			kstat.cpu_nice += user_tick;
 		else
-			kstat.cpu_user += user;
+			kstat.cpu_user += user_tick;
 		kstat.cpu_system += system;
-	}
-	update_one_process(p, ticks, user, system, 0);
+	} else if (local_bh_count(0) || local_irq_count(0) > 1)
+		kstat.cpu_system += system;
+	update_one_process(p, 1, user_tick, system, 0);
 #endif
 }
 
@@ -642,8 +629,8 @@
 	}
 }
 
-volatile unsigned long lost_ticks;
-static unsigned long lost_ticks_system;
+/* jiffies at the most recent update of wall time */
+unsigned long wall_jiffies;
 
 /*
  * This spinlock protect us from races in SMP while playing with xtime. -arca
@@ -661,37 +648,26 @@
 	 */
 	write_lock_irq(&xtime_lock);
 
-	ticks = lost_ticks;
-	lost_ticks = 0;
-
+	ticks = jiffies - wall_jiffies;
 	if (ticks) {
-		unsigned long system;
-		system = xchg(&lost_ticks_system, 0);
-
-		calc_load(ticks);
+		wall_jiffies += ticks;
 		update_wall_time(ticks);
-		write_unlock_irq(&xtime_lock);
-		
-		update_process_times(ticks, system);
-
-	} else
-		write_unlock_irq(&xtime_lock);
+	}
+	write_unlock_irq(&xtime_lock);
+	calc_load(ticks);
 }
 
 void timer_bh(void)
 {
 	update_times();
-	run_old_timers();
 	run_timer_list();
 }
 
-void do_timer(struct pt_regs * regs)
+void do_timer(struct pt_regs *regs)
 {
 	(*(unsigned long *)&jiffies)++;
-	lost_ticks++;
+	update_process_times(user_mode(regs));
 	mark_bh(TIMER_BH);
-	if (!user_mode(regs))
-		lost_ticks_system++;
 	if (tq_timer)
 		mark_bh(TQUEUE_BH);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)