[parisc-linux] [davem@redhat.com: reminder, do_gettimeofday() fix]
Matthew Wilcox
willy@debian.org
Thu, 23 Oct 2003 12:14:30 +0100
Not sure whether we need this or not ...
----- Forwarded message from "David S. Miller" <davem@redhat.com> -----
Date: Thu, 23 Oct 2003 01:44:01 -0700
From: "David S. Miller" <davem@redhat.com>
Subject: reminder, do_gettimeofday() fix
X-Mailer: Sylpheed version 0.9.7 (GTK+ 1.2.6; sparc-unknown-linux-gnu)
Just a reminder to folks that they need to check and add this
fix to their do_gettimeofday() implementation in 2.6.x if necessary.
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1347.1.16 -> 1.1347.1.17
# include/linux/timex.h 1.8 -> 1.9
# kernel/time.c 1.17 -> 1.18
# arch/i386/kernel/time.c 1.41 -> 1.42
# kernel/timer.c 1.71 -> 1.72
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/10/22 akpm@osdl.org 1.1347.1.17
# [PATCH] Time precision, adjtime(x) vs. gettimeofday
#
# From: Stephen Hemminger <shemminger@osdl.org>
#
# The following will prevent adjtime from causing time regression. It delays
# starting the adjtime mechanism for one tick, and keeps gettimeofday inside
# the window.
#
# Only fixes i386, but changes to other arch would be similar.
#
# Running a simple clock test program and playing with adjtime demonstrates
# that this fixes the problem (and 2.6.0-test6 is broken). But given the
# fragile nature of the timer code, it should go through some more testing
# before inclusion.
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c Thu Oct 23 00:11:17 2003
+++ b/arch/i386/kernel/time.c Thu Oct 23 00:11:17 2003
@@ -104,6 +104,15 @@
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;
+
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
} while (read_seqretry(&xtime_lock, seq));
diff -Nru a/include/linux/timex.h b/include/linux/timex.h
--- a/include/linux/timex.h Thu Oct 23 00:11:17 2003
+++ b/include/linux/timex.h Thu Oct 23 00:11:17 2003
@@ -302,6 +302,7 @@
extern long time_reftime; /* time at last adjustment (s) */
extern long time_adjust; /* The amount of adjtime left */
+extern long time_next_adjust; /* Value for time_adjust at next tick */
/* interface variables pps->timer interrupt */
extern long pps_offset; /* pps time offset (us) */
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c Thu Oct 23 00:11:17 2003
+++ b/kernel/time.c Thu Oct 23 00:11:17 2003
@@ -236,7 +236,7 @@
result = time_state; /* mostly `TIME_OK' */
/* Save for later - semantics of adjtime is to return old value */
- save_adjust = time_adjust;
+ save_adjust = time_next_adjust ? time_next_adjust : time_adjust;
#if 0 /* STA_CLOCKERR is never set yet */
time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */
@@ -283,7 +283,8 @@
if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
/* adjtime() is independent from ntp_adjtime() */
- time_adjust = txc->offset;
+ if ((time_next_adjust = txc->offset) == 0)
+ time_adjust = 0;
}
else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c Thu Oct 23 00:11:17 2003
+++ b/kernel/timer.c Thu Oct 23 00:11:17 2003
@@ -474,6 +474,7 @@
long time_adj; /* tick adjust (scaled 1 / HZ) */
long time_reftime; /* time at last adjustment (s) */
long time_adjust;
+long time_next_adjust;
/*
* this routine handles the overflow of the microsecond field
@@ -654,6 +655,12 @@
}
xtime.tv_nsec += delta_nsec;
time_interpolator_update(delta_nsec);
+
+ /* Changes by adjtime() do not take effect till next tick. */
+ if (time_next_adjust != 0) {
+ time_adjust = time_next_adjust;
+ time_next_adjust = 0;
+ }
}
/*
----- End forwarded message -----
--
"It's not Hollywood. War is real, war is primarily not about defeat or
victory, it is about death. I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk