From: Stephen Hemminger The original problem all this is solving is that when NTP is slowing the clock there existed real cases where time appeared to go backwards. Assuming NTP was slowing the clock, then it would update the xtime by 999us at the next timer interrupt. If a program read time three times: A: xtime = t0 B: A+1000 xtime = t0 + 1000 C: B+1 xtime = t0 + 999 To behave correctly C > B > A; but we were returning C < B The code does have bug if we are losing clock interrupts. The test for lost interrupts needs to be after the interval clamp. 25-akpm/arch/i386/kernel/time.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-) diff -puN arch/i386/kernel/time.c~gettimeofday-resolution-fix arch/i386/kernel/time.c --- 25/arch/i386/kernel/time.c~gettimeofday-resolution-fix Tue Oct 28 15:15:08 2003 +++ 25-akpm/arch/i386/kernel/time.c Tue Oct 28 15:15:08 2003 @@ -95,6 +95,7 @@ void do_gettimeofday(struct timeval *tv) { unsigned long seq; unsigned long usec, sec; + unsigned long max_ntp_tick = tick_usec - tickadj; do { unsigned long lost; @@ -103,16 +104,20 @@ void do_gettimeofday(struct timeval *tv) usec = cur_timer->get_offset(); lost = jiffies - wall_jiffies; - if (lost) - usec += lost * (1000000 / HZ); /* * If time_adjust is negative then NTP is slowing the clock * so make sure not to go into next possible interval. * Better to lose some accuracy than have time go backwards.. */ - if (unlikely(time_adjust < 0) && usec > tickadj) - usec = tickadj; + if (unlikely(time_adjust < 0)) { + usec = min(usec, max_ntp_tick); + + if (lost) + usec += lost * max_ntp_tick; + } + else if (unlikely(lost)) + usec += lost * tick_usec; sec = xtime.tv_sec; usec += (xtime.tv_nsec / 1000); _