linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Adjtime patch (to make large offset behavour more like *BSD systems)
@ 2001-06-18  4:43 Jon Peatfield
  0 siblings, 0 replies; only message in thread
From: Jon Peatfield @ 2001-06-18  4:43 UTC (permalink / raw)
  To: linux-kernel; +Cc: J.S.Peatfield

Here is a small patch for the adjtime behavour (strictly adjtimex when
called with ADJ_OFFSET_SINGLESHOT) to make it work more like the
adjtime found in *BSD based kernels where large deltas are allowed to
slew at a greater rate.

In the current Linux code (in 2.2 and 2.4) the slew rate is limited to
500ppm (5us per tick when HZ == 100), which is fine when making small
adjustments, but for larger ones it will take a very long time to take
effect (and one wants to avoid calling settimeofday() to ensure that
the clock is monotonic).  The BSD kernels (well I checked freebsd),
have code to handle large deltas (1000000 us or greater) specially,
allowing a much larger (10 times or 5000ppm), slew.  Of course the BSD
code then spoils it's effort by only moving the time to within one
deltatick of the time we asked for.

I have a small (tested on a dozen machines here for the past few
weeks) patch (against 2.2.19, but the 2.4 patch is fairly trivial to
derive, the code in kernel/sched.c seems to have moved to
kernel/timer.c).

--cut-here--
--- kernel/time.c.orig	Mon May 28 04:12:01 2001
+++ kernel/time.c	Mon May 28 04:19:50 2001
@@ -32,6 +32,10 @@
 
 #include <asm/uaccess.h>
 
+/* Don't completely fail for HZ > 500.  */
+int tickadj = 500/HZ ? : 1;		/* microsecs */
+int bigadj = 1000000;                   /* large adjustment */
+
 /* 
  * The timezone where the local system is located.  Used as a default by some
  * programs who obtain this value by using gettimeofday.
@@ -299,6 +303,11 @@
 		if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
 		    /* adjtime() is independent from ntp_adjtime() */
 		    time_adjust = txc->offset;
+		    if ((time_adjust > bigadj) || (time_adjust < -bigadj)) { /* Big adjust */
+			time_adjust_step = 10 * tickadj ; /* Larger slew rate for big corrections */
+		    } else {
+			time_adjust_step = tickadj ;      /* Max slew rate */
+		    }
 		}
 		else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
 		    ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
--- kernel/sched.c.orig	Mon May 28 04:11:53 2001
+++ kernel/sched.c	Mon May 28 04:19:13 2001
@@ -51,9 +51,6 @@
 /* The current time */
 volatile struct timeval xtime __attribute__ ((aligned (16)));
 
-/* Don't completely fail for HZ > 500.  */
-int tickadj = 500/HZ ? : 1;		/* microsecs */
-
 DECLARE_TASK_QUEUE(tq_timer);
 DECLARE_TASK_QUEUE(tq_immediate);
 DECLARE_TASK_QUEUE(tq_scheduler);
@@ -1368,21 +1365,20 @@
 /* in the NTP reference this is called "hardclock()" */
 static void update_wall_time_one_tick(void)
 {
-	if ( (time_adjust_step = time_adjust) != 0 ) {
+	if ( time_adjust != 0 ) {
 	    /* We are doing an adjtime thing. 
 	     *
-	     * Prepare time_adjust_step to be within bounds.
-	     * Note that a positive time_adjust means we want the clock
-	     * to run faster.
-	     *
-	     * Limit the amount of the step to be in the range
-	     * -tickadj .. +tickadj
+	     * Don't overshoot
 	     */
-	     if (time_adjust > tickadj)
-		time_adjust_step = tickadj;
-	     else if (time_adjust < -tickadj)
-		time_adjust_step = -tickadj;
-	     
+	    if (time_adjust > 0) {
+		if (time_adjust_step > time_adjust) {
+		    time_adjust_step = time_adjust;
+		}
+	    } else {
+		if (time_adjust_step < time_adjust) {
+		    time_adjust_step = time_adjust;
+		}
+	    }
 	    /* Reduce by this step the amount of time left  */
 	    time_adjust -= time_adjust_step;
 	}
--- include/linux/timex.h.orig	Sun Jan 21 06:18:30 2001
+++ include/linux/timex.h	Mon May 28 04:25:23 2001
@@ -261,6 +261,7 @@
 extern long time_reftime;	/* time at last adjustment (s) */
 
 extern long time_adjust;	/* The amount of adjtime left */
+extern long time_adjust_step;	/* The skew we are using */
 
 /* interface variables pps->timer interrupt */
 extern long pps_offset;		/* pps time offset (us) */
--cut-here--

As so few things actually use adjtimex in this mode (and even fewer us
it for large deltas) it is unlikely to cause any problems.  The
interface stays the same it just completes the adjustment a bit faster
for large deltas.
-- 
Jon Peatfield,  DAMTP,  Computer Officer,   University of Cambridge
Telephone: +44 1223  3 37852    Mail: J.S.Peatfield@damtp.cam.ac.uk

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-06-18  4:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-06-18  4:43 Adjtime patch (to make large offset behavour more like *BSD systems) Jon Peatfield

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).