patch-2.2.7 linux/arch/alpha/kernel/time.c

Next file: linux/arch/alpha/lib/clear_user.S
Previous file: linux/arch/alpha/kernel/setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.6/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
@@ -18,6 +18,9 @@
  *      fixed tick loss calculation in timer_interrupt
  *      (round system clock to nearest tick instead of truncating)
  *      fixed algorithm in time_init for getting time from CMOS clock
+ * 1999-04-16	Thorsten Kranzkowski (dl8bcu@gmx.net)
+ *	fixed algorithm in do_gettimeofday() for calculating the precise time
+ *	from processor cycle counter (now taking lost_ticks into account)
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -223,7 +226,7 @@
 {
 	void (*irq_handler)(int, void *, struct pt_regs *);
 	unsigned int year, mon, day, hour, min, sec, cc1, cc2;
-	unsigned long cycle_freq;
+	unsigned long cycle_freq, diff, one_percent;
 
 	/*
 	 * The Linux interpretation of the CMOS clock register contents:
@@ -237,19 +240,30 @@
 	/* Read cycle counter exactly on falling edge of update flag */
 	cc1 = rpcc();
 
-	/* If our cycle frequency isn't valid, go another round and give
-	   a guess at what it should be.  */
-	cycle_freq = hwrpb->cycle_freq;
-	if (cycle_freq == 0) {
-		printk("HWRPB cycle frequency bogus.  Estimating... ");
-
+	if (!est_cycle_freq) {
+		/* Sometimes the hwrpb->cycle_freq value is bogus. 
+	   	Go another round to check up on it and see.  */
 		do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
 		do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
 		cc2 = rpcc();
-		est_cycle_freq = cycle_freq = cc2 - cc1;
+		est_cycle_freq = cc2 - cc1;
 		cc1 = cc2;
+	}
 
-		printk("%lu Hz\n", cycle_freq);
+	/* If the given value is within 1% of what we calculated, 
+	   accept it.  Otherwise, use what we found.  */
+	cycle_freq = hwrpb->cycle_freq;
+	one_percent = cycle_freq / 100;
+	diff = cycle_freq - est_cycle_freq;
+	if (diff < 0)
+		diff = -diff;
+	if (diff > one_percent) {
+		cycle_freq = est_cycle_freq;
+		printk("HWRPB cycle frequency bogus.  Estimated %lu Hz\n",
+		       cycle_freq);
+	}
+	else {
+		est_cycle_freq = 0;
 	}
 
 	/* From John Bowman <bowman@math.ualberta.ca>: allow the values
@@ -314,8 +328,10 @@
 void
 do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags, now, delta_cycles, delta_usec;
+	unsigned long flags, delta_cycles, delta_usec;
 	unsigned long sec, usec;
+	__u32 now;
+	extern volatile unsigned long lost_ticks;	/*kernel/sched.c*/
 
 	now = rpcc();
 	save_and_cli(flags);
@@ -337,8 +353,14 @@
 	 * with no clear gain.
 	 */
 
-	delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
+	delta_usec = (delta_cycles * state.scaled_ticks_per_cycle 
+			+ state.partial_tick
+			+ (lost_ticks << FIX_SHIFT) ) * 15625;
 	delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
+
+	/* the 'lost_tics' term above implements this:	
+	 * delta_usec += lost_ticks * (1000000 / HZ);
+	 */
 
 	usec += delta_usec;
 	if (usec >= 1000000) {

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