--- time.c.orig Wed May 22 12:01:24 2002 +++ linux/arch/i386/kernel/time.c Wed May 22 20:38:29 2002 @@ -118,6 +118,14 @@ extern spinlock_t i8259A_lock; +static void smack_timer(void) +{ + outb_p(0x34, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); +} + + #ifndef CONFIG_X86_TSC /* This function must be called with interrupts disabled @@ -179,14 +187,6 @@ count |= inb_p(0x40) << 8; - /* VIA686a test code... reset the latch if count > max + 1 */ - if (count > LATCH) { - outb_p(0x34, 0x43); - outb_p(LATCH & 0xff, 0x40); - outb(LATCH >> 8, 0x40); - count = LATCH - 1; - } - spin_unlock(&i8253_lock); /* @@ -267,23 +267,49 @@ { unsigned long flags; unsigned long usec, sec; + unsigned long usec_overflow=0; + unsigned long lost; read_lock_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); - { - unsigned long lost = jiffies - wall_jiffies; - if (lost) - usec += lost * (1000000 / HZ); - } sec = xtime.tv_sec; usec += xtime.tv_usec; read_unlock_irqrestore(&xtime_lock, flags); + lost = jiffies - wall_jiffies; - while (usec >= 1000000) { - usec -= 1000000; - sec++; + /* if usec is overflowing calculate by how much */ + if (usec >= 1000000) { + usec_overflow = usec / 1000000; } + /* xtime.tv_usec could bring us almost to 1, so if we go over 2, + were're overflowing by over a second. */ + if (usec_overflow > 2) { +#ifdef CONFIG_X86_TSC + printk("gettimeofday bug(TSC): offset=0x%lx, sec=%lu, lost=%lu\n", usec, sec, lost); +#else + printk("gettimeofday bug: offset=0x%lx, sec=%lu, lost=%lu\n", usec, sec, lost); +#endif + smack_timer(); + } + + if (usec_overflow) { + usec = usec % 1000000; + } + + if (lost) { + usec += lost * (1000000 / HZ); + } + + /* this is a little redundant but now includes lost jiffies, + which I didn't want to count in the bug test above */ + if (usec >= 1000000) { + usec_overflow += usec / 1000000; + usec = usec % 1000000; + } + + sec+= usec_overflow; + tv->tv_sec = sec; tv->tv_usec = usec; }