* [RFC - 0/12] NTP cleanup work (v. B4)
@ 2005-07-16 2:55 john stultz
2005-07-16 2:57 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c john stultz
2005-07-17 18:00 ` [RFC - 0/12] NTP cleanup work (v. B4) Roman Zippel
0 siblings, 2 replies; 19+ messages in thread
From: john stultz @ 2005-07-16 2:55 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, zippel
All,
In my attempts to rework the timeofday subsystem, it was suggested I
try to avoid mixing cleanups with functional changes. In response to the
suggestion I've tried to break out the majority of the NTP cleanups I've
been working out of my larger patch and try to feed it in piece meal.
The goal of this patch set is to isolate the in kernel NTP state machine
in the hope of simplifying the current timeofday code.
Patches 1-10 should be fairly straight forward only moving and cleaning
up various bits of code.
Patches 11 and 12 are somewhat more functional changes and should be
reviewed more carefully. Especially by someone who knows the PPC64
ppc_adjtimex() function in depth.
I haven't been able to test this code, only checking that the code
builds on a number of arches, but since I may not have access to my
cogito repositories while I'm at OLS, I thought it might be worth while
to send this out for discussion.
Shortly after I send out these patches I hope to send out the rest of my
timeofday changes with apply on top of this patch set.
thanks
-john
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c
2005-07-16 2:55 [RFC - 0/12] NTP cleanup work (v. B4) john stultz
@ 2005-07-16 2:57 ` john stultz
2005-07-16 2:57 ` [RFC][PATCH - 2/12] NTP cleanup: Move arches to new ntp interfaces john stultz
2005-07-18 11:42 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c Pavel Machek
2005-07-17 18:00 ` [RFC - 0/12] NTP cleanup work (v. B4) Roman Zippel
1 sibling, 2 replies; 19+ messages in thread
From: john stultz @ 2005-07-16 2:57 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch moves the generic NTP code from time.c and timer.c into
ntp.c. It makes most of the NTP variables static providing more
understandable interfaces like ntp_synced() and ntp_clear().
Since some of the newly made static variables are used in arch generic
code, this patch alone will not compile. Thus this patch requires part 2
of the series which fixes the arch specific uses of the newly static
variables.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part1_B4.patch
============================================
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
new file mode 100644
--- /dev/null
+++ b/include/linux/ntp.h
@@ -0,0 +1,28 @@
+/* linux/include/linux/ntp.h
+ *
+ * This file NTP state machine accessor functions.
+ */
+
+#ifndef _LINUX_NTP_H
+#define _LINUX_NTP_H
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+/* NTP state machine interfaces */
+int ntp_advance(void);
+int ntp_adjtimex(struct timex*);
+void second_overflow(void);
+void ntp_clear(void);
+int ntp_synced(void);
+
+/* Due to ppc64 having its own NTP code,
+ * these variables cannot be made static just yet
+ */
+extern int tickadj;
+extern long time_offset;
+extern long time_freq;
+extern long time_adjust;
+extern long time_constant;
+
+#endif
diff --git a/include/linux/timex.h b/include/linux/timex.h
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -226,39 +226,6 @@ struct timex {
*/
extern unsigned long tick_usec; /* USER_HZ period (usec) */
extern unsigned long tick_nsec; /* ACTHZ period (nsec) */
-extern int tickadj; /* amount of adjustment per tick */
-
-/*
- * phase-lock loop variables
- */
-extern int time_state; /* clock status */
-extern int time_status; /* clock synchronization status bits */
-extern long time_offset; /* time adjustment (us) */
-extern long time_constant; /* pll time constant */
-extern long time_tolerance; /* frequency tolerance (ppm) */
-extern long time_precision; /* clock precision (us) */
-extern long time_maxerror; /* maximum error */
-extern long time_esterror; /* estimated error */
-
-extern long time_freq; /* frequency offset (scaled ppm) */
-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) */
-extern long pps_jitter; /* time dispersion (jitter) (us) */
-extern long pps_freq; /* frequency offset (scaled ppm) */
-extern long pps_stabil; /* frequency dispersion (scaled ppm) */
-extern long pps_valid; /* pps signal watchdog counter */
-
-/* interface variables pps->adjtimex */
-extern int pps_shift; /* interval duration (s) (shift) */
-extern long pps_jitcnt; /* jitter limit exceeded */
-extern long pps_calcnt; /* calibration intervals */
-extern long pps_errcnt; /* calibration errors */
-extern long pps_stbcnt; /* stability limit exceeded */
#ifdef CONFIG_TIME_INTERPOLATION
diff --git a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -7,7 +7,7 @@ obj-y = sched.o fork.o exec_domain.o
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o intermodule.o extable.o params.o posix-timers.o \
- kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
+ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o ntp.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
diff --git a/kernel/ntp.c b/kernel/ntp.c
new file mode 100644
--- /dev/null
+++ b/kernel/ntp.c
@@ -0,0 +1,490 @@
+/********************************************************************
+* linux/kernel/ntp.c
+*
+* NTP state machine and time scaling code.
+*
+* Code moved from kernel/time.c and kernel/timer.c
+* Please see those files for original copyrights.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Notes:
+*
+* Hopefully you should never have to understand or touch
+* any of the code below. but don't let that keep you from trying!
+*
+* This code is loosely based on David Mills' RFC 1589 and its
+* updates. Please see the following for more details:
+* http://www.eecis.udel.edu/~mills/database/rfc/rfc1589.txt
+* http://www.eecis.udel.edu/~mills/database/reports/kern/kernb.pdf
+*
+* NOTE: To simplify the code, we do not implement any of
+* the PPS code, as the code that uses it never was merged.
+* -johnstul@us.ibm.com
+*
+*********************************************************************/
+
+#include <linux/ntp.h>
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+
+#ifdef CONFIG_TIME_INTERPOLATION
+void time_interpolator_update(long delta_nsec);
+#else
+#define time_interpolator_update(x)
+#endif
+
+
+static long pps_offset; /* pps time offset (us) */
+static long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
+
+static long pps_freq; /* frequency offset (scaled ppm) */
+static long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
+
+static long pps_valid = PPS_VALID; /* pps signal watchdog counter */
+
+static int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
+
+static long pps_jitcnt; /* jitter limit exceeded */
+static long pps_calcnt; /* calibration intervals */
+static long pps_errcnt; /* calibration errors */
+static long pps_stbcnt; /* stability limit exceeded */
+
+/* Don't completely fail for HZ > 500. */
+int tickadj = 500/HZ ? : 1; /* microsecs */
+
+
+/*
+ * phase-lock loop variables
+ */
+/* TIME_ERROR prevents overwriting the CMOS clock */
+static int time_state = TIME_OK; /* clock synchronization status */
+static int time_status = STA_UNSYNC; /* clock status bits */
+long time_offset; /* time adjustment (us) */
+long time_constant = 2; /* pll time constant */
+static long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
+static long time_precision = 1; /* clock precision (us) */
+static long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
+static long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
+static long time_phase; /* phase offset (scaled us) */
+long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
+ /* frequency offset (scaled ppm) */
+static long time_adj; /* tick adjust (scaled 1 / HZ) */
+static long time_reftime; /* time at last adjustment (s) */
+long time_adjust;
+static long time_next_adjust;
+
+int ntp_advance(void)
+{
+ long time_adjust_step, delta_nsec;
+
+ if ( (time_adjust_step = 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
+ */
+ if (time_adjust > tickadj)
+ time_adjust_step = tickadj;
+ else if (time_adjust < -tickadj)
+ time_adjust_step = -tickadj;
+
+ /* Reduce by this step the amount of time left */
+ time_adjust -= time_adjust_step;
+ }
+ delta_nsec = time_adjust_step * 1000;
+
+ /*
+ * Advance the phase, once it gets to one microsecond, then
+ * advance the tick more.
+ */
+ time_phase += time_adj;
+ if (time_phase <= -FINENSEC) {
+ long ltemp = -time_phase >> (SHIFT_SCALE - 10);
+ time_phase += ltemp << (SHIFT_SCALE - 10);
+ delta_nsec -= ltemp;
+ } else if (time_phase >= FINENSEC) {
+ long ltemp = time_phase >> (SHIFT_SCALE - 10);
+ time_phase -= ltemp << (SHIFT_SCALE - 10);
+ delta_nsec += ltemp;
+ }
+
+ /* Changes by adjtime() do not take effect till next tick. */
+ if (time_next_adjust != 0) {
+ time_adjust = time_next_adjust;
+ time_next_adjust = 0;
+ }
+
+ return delta_nsec;
+}
+
+
+/*
+ * this routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+ * They were originally developed for SUN and DEC kernels.
+ * All the kudos should go to Dave for this stuff.
+ *
+ */
+void second_overflow(void)
+{
+ long ltemp;
+
+ /* Bump the maxerror field */
+ time_maxerror += time_tolerance >> SHIFT_USEC;
+ if ( time_maxerror > NTP_PHASE_LIMIT ) {
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_status |= STA_UNSYNC;
+ }
+
+ /*
+ * Leap second processing. If in leap-insert state at
+ * the end of the day, the system clock is set back one
+ * second; if in leap-delete state, the system clock is
+ * set ahead one second. The microtime() routine or
+ * external clock driver will insure that reported time
+ * is always monotonic. The ugly divides should be
+ * replaced.
+ */
+ switch (time_state) {
+
+ case TIME_OK:
+ if (time_status & STA_INS)
+ time_state = TIME_INS;
+ else if (time_status & STA_DEL)
+ time_state = TIME_DEL;
+ break;
+
+ case TIME_INS:
+ if (xtime.tv_sec % 86400 == 0) {
+ xtime.tv_sec--;
+ wall_to_monotonic.tv_sec++;
+ /* The timer interpolator will make time change gradually instead
+ * of an immediate jump by one second.
+ */
+ time_interpolator_update(-NSEC_PER_SEC);
+ time_state = TIME_OOP;
+ clock_was_set();
+ printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
+ }
+ break;
+
+ case TIME_DEL:
+ if ((xtime.tv_sec + 1) % 86400 == 0) {
+ xtime.tv_sec++;
+ wall_to_monotonic.tv_sec--;
+ /* Use of time interpolator for a gradual change of time */
+ time_interpolator_update(NSEC_PER_SEC);
+ time_state = TIME_WAIT;
+ clock_was_set();
+ printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
+ }
+ break;
+
+ case TIME_OOP:
+ time_state = TIME_WAIT;
+ break;
+
+ case TIME_WAIT:
+ if (!(time_status & (STA_INS | STA_DEL)))
+ time_state = TIME_OK;
+ }
+
+ /*
+ * Compute the phase adjustment for the next second. In
+ * PLL mode, the offset is reduced by a fixed factor
+ * times the time constant. In FLL mode the offset is
+ * used directly. In either mode, the maximum phase
+ * adjustment for each second is clamped so as to spread
+ * the adjustment over not more than the number of
+ * seconds between updates.
+ */
+ if (time_offset < 0) {
+ ltemp = -time_offset;
+ if (!(time_status & STA_FLL))
+ ltemp >>= SHIFT_KG + time_constant;
+ if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
+ ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
+ time_offset += ltemp;
+ time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+ } else {
+ ltemp = time_offset;
+ if (!(time_status & STA_FLL))
+ ltemp >>= SHIFT_KG + time_constant;
+ if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
+ ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
+ time_offset -= ltemp;
+ time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+ }
+
+ /*
+ * Compute the frequency estimate and additional phase
+ * adjustment due to frequency error for the next
+ * second. When the PPS signal is engaged, gnaw on the
+ * watchdog counter and update the frequency computed by
+ * the pll and the PPS signal.
+ */
+ pps_valid++;
+ if (pps_valid == PPS_VALID) { /* PPS signal lost */
+ pps_jitter = MAXTIME;
+ pps_stabil = MAXFREQ;
+ time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
+ STA_PPSWANDER | STA_PPSERROR);
+ }
+ ltemp = time_freq + pps_freq;
+ if (ltemp < 0)
+ time_adj -= -ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+ else
+ time_adj += ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+
+#if HZ == 100
+ /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
+ * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
+ */
+ if (time_adj < 0)
+ time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
+ else
+ time_adj += (time_adj >> 2) + (time_adj >> 5);
+#endif
+#if HZ == 1000
+ /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
+ * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
+ */
+ if (time_adj < 0)
+ time_adj -= (-time_adj >> 6) + (-time_adj >> 7);
+ else
+ time_adj += (time_adj >> 6) + (time_adj >> 7);
+#endif
+}
+
+/* adjtimex mainly allows reading (and writing, if superuser) of
+ * kernel time-keeping variables. used by xntpd.
+ */
+int ntp_adjtimex(struct timex *txc)
+{
+ long ltemp, mtemp, save_adjust;
+ int result;
+
+ /* Now we validate the data before disabling interrupts */
+
+ if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+ /* singleshot must not be used with any other mode bits */
+ if (txc->modes != ADJ_OFFSET_SINGLESHOT)
+ return -EINVAL;
+
+ if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
+ /* adjustment Offset limited to +- .512 seconds */
+ if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
+ return -EINVAL;
+
+ /* if the quartz is off by more than 10% something is VERY wrong ! */
+ if (txc->modes & ADJ_TICK)
+ if (txc->tick < 900000/USER_HZ ||
+ txc->tick > 1100000/USER_HZ)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+ result = time_state; /* mostly `TIME_OK' */
+
+ /* Save for later - semantics of adjtime is to return old value */
+ 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 */
+#endif
+
+ /* If there are input parameters, then process them */
+ if (txc->modes) {
+ if (txc->modes & ADJ_STATUS) /* only set allowed bits */
+ time_status = (txc->status & ~STA_RONLY) |
+ (time_status & STA_RONLY);
+
+ if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */
+ if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
+ result = -EINVAL;
+ goto leave;
+ }
+ time_freq = txc->freq - pps_freq;
+ }
+
+ if (txc->modes & ADJ_MAXERROR) {
+ if (txc->maxerror < 0
+ || txc->maxerror >= NTP_PHASE_LIMIT) {
+ result = -EINVAL;
+ goto leave;
+ }
+ time_maxerror = txc->maxerror;
+ }
+
+ if (txc->modes & ADJ_ESTERROR) {
+ if (txc->esterror < 0
+ || txc->esterror >= NTP_PHASE_LIMIT) {
+ result = -EINVAL;
+ goto leave;
+ }
+ time_esterror = txc->esterror;
+ }
+
+ if (txc->modes & ADJ_TIMECONST) { /* p. 24 */
+ if (txc->constant < 0) { /* NTP v4 uses values > 6 */
+ result = -EINVAL;
+ goto leave;
+ }
+ time_constant = txc->constant;
+ }
+
+ if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
+ if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
+ /* adjtime() is independent from ntp_adjtime() */
+ 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))
+ == (STA_PPSTIME | STA_PPSSIGNAL) ?
+ pps_offset : txc->offset;
+
+ /*
+ * Scale the phase adjustment and
+ * clamp to the operating range.
+ */
+ if (ltemp > MAXPHASE)
+ time_offset = MAXPHASE << SHIFT_UPDATE;
+ else if (ltemp < -MAXPHASE)
+ time_offset = -(MAXPHASE
+ << SHIFT_UPDATE);
+ else
+ time_offset = ltemp << SHIFT_UPDATE;
+
+ /*
+ * Select whether the frequency is to be controlled
+ * and in which mode (PLL or FLL). Clamp to the operating
+ * range. Ugly multiply/divide should be replaced someday.
+ */
+
+ if (time_status & STA_FREQHOLD || time_reftime == 0)
+ time_reftime = xtime.tv_sec;
+
+ mtemp = xtime.tv_sec - time_reftime;
+ time_reftime = xtime.tv_sec;
+
+ if (time_status & STA_FLL) {
+ if (mtemp >= MINSEC) {
+ ltemp = (time_offset / mtemp) << (SHIFT_USEC -
+ SHIFT_UPDATE);
+ if (ltemp < 0)
+ time_freq -= -ltemp >> SHIFT_KH;
+ else
+ time_freq += ltemp >> SHIFT_KH;
+ } else /* calibration interval too short (p. 12) */
+ result = TIME_ERROR;
+ } else { /* PLL mode */
+ if (mtemp < MAXSEC) {
+ ltemp *= mtemp;
+ if (ltemp < 0)
+ time_freq -= -ltemp >> (time_constant +
+ time_constant +
+ SHIFT_KF - SHIFT_USEC);
+ else
+ time_freq += ltemp >> (time_constant +
+ time_constant +
+ SHIFT_KF - SHIFT_USEC);
+ } else /* calibration interval too long (p. 12) */
+ result = TIME_ERROR;
+ }
+
+ if (time_freq > time_tolerance)
+ time_freq = time_tolerance;
+ else if (time_freq < -time_tolerance)
+ time_freq = -time_tolerance;
+ } /* STA_PLL || STA_PPSTIME */
+ } /* txc->modes & ADJ_OFFSET */
+
+ if (txc->modes & ADJ_TICK) {
+ tick_usec = txc->tick;
+ tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
+ }
+ } /* txc->modes */
+leave:
+
+ if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
+ || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
+ && (time_status & STA_PPSSIGNAL) == 0)
+ /* p. 24, (b) */
+ || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
+ == (STA_PPSTIME|STA_PPSJITTER))
+ /* p. 24, (c) */
+ || ((time_status & STA_PPSFREQ) != 0
+ && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
+ /* p. 24, (d) */
+ result = TIME_ERROR;
+
+ if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+ txc->offset = save_adjust;
+ else {
+ if (time_offset < 0)
+ txc->offset = -(-time_offset >> SHIFT_UPDATE);
+ else
+ txc->offset = time_offset >> SHIFT_UPDATE;
+ }
+ txc->freq = time_freq + pps_freq;
+ txc->maxerror = time_maxerror;
+ txc->esterror = time_esterror;
+ txc->status = time_status;
+ txc->constant = time_constant;
+ txc->precision = time_precision;
+ txc->tolerance = time_tolerance;
+ txc->tick = tick_usec;
+ txc->ppsfreq = pps_freq;
+ txc->jitter = pps_jitter >> PPS_AVG;
+ txc->shift = pps_shift;
+ txc->stabil = pps_stabil;
+ txc->jitcnt = pps_jitcnt;
+ txc->calcnt = pps_calcnt;
+ txc->errcnt = pps_errcnt;
+ txc->stbcnt = pps_stbcnt;
+ write_sequnlock_irq(&xtime_lock);
+ do_gettimeofday(&txc->time);
+ return result;
+}
+
+/**
+ * ntp_clear - Clears the NTP state machine.
+ *
+ * Must be called while holding a write on the xtime_lock
+ */
+void ntp_clear(void)
+{
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+}
+
+/**
+ * ntp_synced - Returns 1 if the NTP status is not UNSYNC
+ *
+ */
+int ntp_synced(void)
+{
+ return !(time_status & STA_UNSYNC);
+}
+
diff --git a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -35,6 +35,7 @@
#include <linux/security.h>
#include <linux/fs.h>
#include <linux/module.h>
+#include <linux/ntp.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -198,20 +199,6 @@ asmlinkage long sys_settimeofday(struct
return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
}
-long pps_offset; /* pps time offset (us) */
-long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
-
-long pps_freq; /* frequency offset (scaled ppm) */
-long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
-
-long pps_valid = PPS_VALID; /* pps signal watchdog counter */
-
-int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
-
-long pps_jitcnt; /* jitter limit exceeded */
-long pps_calcnt; /* calibration intervals */
-long pps_errcnt; /* calibration errors */
-long pps_stbcnt; /* stability limit exceeded */
/* hook for a loadable hardpps kernel module */
void (*hardpps_ptr)(struct timeval *);
@@ -229,184 +216,14 @@ void __attribute__ ((weak)) notify_arch_
*/
int do_adjtimex(struct timex *txc)
{
- long ltemp, mtemp, save_adjust;
int result;
/* In order to modify anything, you gotta be super-user! */
if (txc->modes && !capable(CAP_SYS_TIME))
return -EPERM;
- /* Now we validate the data before disabling interrupts */
-
- if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
- /* singleshot must not be used with any other mode bits */
- if (txc->modes != ADJ_OFFSET_SINGLESHOT)
- return -EINVAL;
-
- if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
- /* adjustment Offset limited to +- .512 seconds */
- if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
- return -EINVAL;
-
- /* if the quartz is off by more than 10% something is VERY wrong ! */
- if (txc->modes & ADJ_TICK)
- if (txc->tick < 900000/USER_HZ ||
- txc->tick > 1100000/USER_HZ)
- return -EINVAL;
-
- write_seqlock_irq(&xtime_lock);
- result = time_state; /* mostly `TIME_OK' */
-
- /* Save for later - semantics of adjtime is to return old value */
- 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 */
-#endif
- /* If there are input parameters, then process them */
- if (txc->modes)
- {
- if (txc->modes & ADJ_STATUS) /* only set allowed bits */
- time_status = (txc->status & ~STA_RONLY) |
- (time_status & STA_RONLY);
-
- if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */
- if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
- result = -EINVAL;
- goto leave;
- }
- time_freq = txc->freq - pps_freq;
- }
-
- if (txc->modes & ADJ_MAXERROR) {
- if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
- result = -EINVAL;
- goto leave;
- }
- time_maxerror = txc->maxerror;
- }
-
- if (txc->modes & ADJ_ESTERROR) {
- if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
- result = -EINVAL;
- goto leave;
- }
- time_esterror = txc->esterror;
- }
-
- if (txc->modes & ADJ_TIMECONST) { /* p. 24 */
- if (txc->constant < 0) { /* NTP v4 uses values > 6 */
- result = -EINVAL;
- goto leave;
- }
- time_constant = txc->constant;
- }
-
- if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
- if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
- /* adjtime() is independent from ntp_adjtime() */
- 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)) ==
- (STA_PPSTIME | STA_PPSSIGNAL) ?
- pps_offset : txc->offset;
-
- /*
- * Scale the phase adjustment and
- * clamp to the operating range.
- */
- if (ltemp > MAXPHASE)
- time_offset = MAXPHASE << SHIFT_UPDATE;
- else if (ltemp < -MAXPHASE)
- time_offset = -(MAXPHASE << SHIFT_UPDATE);
- else
- time_offset = ltemp << SHIFT_UPDATE;
-
- /*
- * Select whether the frequency is to be controlled
- * and in which mode (PLL or FLL). Clamp to the operating
- * range. Ugly multiply/divide should be replaced someday.
- */
-
- if (time_status & STA_FREQHOLD || time_reftime == 0)
- time_reftime = xtime.tv_sec;
- mtemp = xtime.tv_sec - time_reftime;
- time_reftime = xtime.tv_sec;
- if (time_status & STA_FLL) {
- if (mtemp >= MINSEC) {
- ltemp = (time_offset / mtemp) << (SHIFT_USEC -
- SHIFT_UPDATE);
- if (ltemp < 0)
- time_freq -= -ltemp >> SHIFT_KH;
- else
- time_freq += ltemp >> SHIFT_KH;
- } else /* calibration interval too short (p. 12) */
- result = TIME_ERROR;
- } else { /* PLL mode */
- if (mtemp < MAXSEC) {
- ltemp *= mtemp;
- if (ltemp < 0)
- time_freq -= -ltemp >> (time_constant +
- time_constant +
- SHIFT_KF - SHIFT_USEC);
- else
- time_freq += ltemp >> (time_constant +
- time_constant +
- SHIFT_KF - SHIFT_USEC);
- } else /* calibration interval too long (p. 12) */
- result = TIME_ERROR;
- }
- if (time_freq > time_tolerance)
- time_freq = time_tolerance;
- else if (time_freq < -time_tolerance)
- time_freq = -time_tolerance;
- } /* STA_PLL || STA_PPSTIME */
- } /* txc->modes & ADJ_OFFSET */
- if (txc->modes & ADJ_TICK) {
- tick_usec = txc->tick;
- tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
- }
- } /* txc->modes */
-leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
- || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
- && (time_status & STA_PPSSIGNAL) == 0)
- /* p. 24, (b) */
- || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
- == (STA_PPSTIME|STA_PPSJITTER))
- /* p. 24, (c) */
- || ((time_status & STA_PPSFREQ) != 0
- && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
- /* p. 24, (d) */
- result = TIME_ERROR;
+ result = ntp_adjtimex(txc);
- if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
- txc->offset = save_adjust;
- else {
- if (time_offset < 0)
- txc->offset = -(-time_offset >> SHIFT_UPDATE);
- else
- txc->offset = time_offset >> SHIFT_UPDATE;
- }
- txc->freq = time_freq + pps_freq;
- txc->maxerror = time_maxerror;
- txc->esterror = time_esterror;
- txc->status = time_status;
- txc->constant = time_constant;
- txc->precision = time_precision;
- txc->tolerance = time_tolerance;
- txc->tick = tick_usec;
- txc->ppsfreq = pps_freq;
- txc->jitter = pps_jitter >> PPS_AVG;
- txc->shift = pps_shift;
- txc->stabil = pps_stabil;
- txc->jitcnt = pps_jitcnt;
- txc->calcnt = pps_calcnt;
- txc->errcnt = pps_errcnt;
- txc->stbcnt = pps_stbcnt;
- write_sequnlock_irq(&xtime_lock);
- do_gettimeofday(&txc->time);
notify_arch_cmos_timer();
return(result);
}
@@ -522,10 +339,8 @@ int do_settimeofday (struct timespec *tv
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
+
time_interpolator_reset();
}
write_sequnlock_irq(&xtime_lock);
diff --git a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -33,6 +33,7 @@
#include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
+#include <linux/ntp.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -41,7 +42,7 @@
#include <asm/io.h>
#ifdef CONFIG_TIME_INTERPOLATION
-static void time_interpolator_update(long delta_nsec);
+void time_interpolator_update(long delta_nsec);
#else
#define time_interpolator_update(x)
#endif
@@ -597,219 +598,17 @@ struct timespec wall_to_monotonic __attr
EXPORT_SYMBOL(xtime);
-/* Don't completely fail for HZ > 500. */
-int tickadj = 500/HZ ? : 1; /* microsecs */
-
-
-/*
- * phase-lock loop variables
- */
-/* TIME_ERROR prevents overwriting the CMOS clock */
-int time_state = TIME_OK; /* clock synchronization status */
-int time_status = STA_UNSYNC; /* clock status bits */
-long time_offset; /* time adjustment (us) */
-long time_constant = 2; /* pll time constant */
-long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
-long time_precision = 1; /* clock precision (us) */
-long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
-long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
-static long time_phase; /* phase offset (scaled us) */
-long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
- /* frequency offset (scaled ppm)*/
-static 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
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- *
- */
-static void second_overflow(void)
-{
- long ltemp;
-
- /* Bump the maxerror field */
- time_maxerror += time_tolerance >> SHIFT_USEC;
- if ( time_maxerror > NTP_PHASE_LIMIT ) {
- time_maxerror = NTP_PHASE_LIMIT;
- time_status |= STA_UNSYNC;
- }
-
- /*
- * Leap second processing. If in leap-insert state at
- * the end of the day, the system clock is set back one
- * second; if in leap-delete state, the system clock is
- * set ahead one second. The microtime() routine or
- * external clock driver will insure that reported time
- * is always monotonic. The ugly divides should be
- * replaced.
- */
- switch (time_state) {
-
- case TIME_OK:
- if (time_status & STA_INS)
- time_state = TIME_INS;
- else if (time_status & STA_DEL)
- time_state = TIME_DEL;
- break;
-
- case TIME_INS:
- if (xtime.tv_sec % 86400 == 0) {
- xtime.tv_sec--;
- wall_to_monotonic.tv_sec++;
- /* The timer interpolator will make time change gradually instead
- * of an immediate jump by one second.
- */
- time_interpolator_update(-NSEC_PER_SEC);
- time_state = TIME_OOP;
- clock_was_set();
- printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
- }
- break;
-
- case TIME_DEL:
- if ((xtime.tv_sec + 1) % 86400 == 0) {
- xtime.tv_sec++;
- wall_to_monotonic.tv_sec--;
- /* Use of time interpolator for a gradual change of time */
- time_interpolator_update(NSEC_PER_SEC);
- time_state = TIME_WAIT;
- clock_was_set();
- printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
- }
- break;
-
- case TIME_OOP:
- time_state = TIME_WAIT;
- break;
-
- case TIME_WAIT:
- if (!(time_status & (STA_INS | STA_DEL)))
- time_state = TIME_OK;
- }
-
- /*
- * Compute the phase adjustment for the next second. In
- * PLL mode, the offset is reduced by a fixed factor
- * times the time constant. In FLL mode the offset is
- * used directly. In either mode, the maximum phase
- * adjustment for each second is clamped so as to spread
- * the adjustment over not more than the number of
- * seconds between updates.
- */
- if (time_offset < 0) {
- ltemp = -time_offset;
- if (!(time_status & STA_FLL))
- ltemp >>= SHIFT_KG + time_constant;
- if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
- ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
- time_offset += ltemp;
- time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- } else {
- ltemp = time_offset;
- if (!(time_status & STA_FLL))
- ltemp >>= SHIFT_KG + time_constant;
- if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
- ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
- time_offset -= ltemp;
- time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- }
-
- /*
- * Compute the frequency estimate and additional phase
- * adjustment due to frequency error for the next
- * second. When the PPS signal is engaged, gnaw on the
- * watchdog counter and update the frequency computed by
- * the pll and the PPS signal.
- */
- pps_valid++;
- if (pps_valid == PPS_VALID) { /* PPS signal lost */
- pps_jitter = MAXTIME;
- pps_stabil = MAXFREQ;
- time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
- STA_PPSWANDER | STA_PPSERROR);
- }
- ltemp = time_freq + pps_freq;
- if (ltemp < 0)
- time_adj -= -ltemp >>
- (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
- else
- time_adj += ltemp >>
- (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
-
-#if HZ == 100
- /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
- * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
- */
- if (time_adj < 0)
- time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
- else
- time_adj += (time_adj >> 2) + (time_adj >> 5);
-#endif
-#if HZ == 1000
- /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
- * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
- */
- if (time_adj < 0)
- time_adj -= (-time_adj >> 6) + (-time_adj >> 7);
- else
- time_adj += (time_adj >> 6) + (time_adj >> 7);
-#endif
-}
/* in the NTP reference this is called "hardclock()" */
static void update_wall_time_one_tick(void)
{
- long time_adjust_step, delta_nsec;
+ long delta_nsec;
- if ( (time_adjust_step = 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
- */
- if (time_adjust > tickadj)
- time_adjust_step = tickadj;
- else if (time_adjust < -tickadj)
- time_adjust_step = -tickadj;
+ delta_nsec = tick_nsec + ntp_advance();
- /* Reduce by this step the amount of time left */
- time_adjust -= time_adjust_step;
- }
- delta_nsec = tick_nsec + time_adjust_step * 1000;
- /*
- * Advance the phase, once it gets to one microsecond, then
- * advance the tick more.
- */
- time_phase += time_adj;
- if (time_phase <= -FINENSEC) {
- long ltemp = -time_phase >> (SHIFT_SCALE - 10);
- time_phase += ltemp << (SHIFT_SCALE - 10);
- delta_nsec -= ltemp;
- }
- else if (time_phase >= FINENSEC) {
- long ltemp = time_phase >> (SHIFT_SCALE - 10);
- time_phase -= ltemp << (SHIFT_SCALE - 10);
- delta_nsec += ltemp;
- }
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;
- }
}
/*
@@ -1473,7 +1272,7 @@ unsigned long time_interpolator_get_offs
#define INTERPOLATOR_ADJUST 65536
#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
-static void time_interpolator_update(long delta_nsec)
+void time_interpolator_update(long delta_nsec)
{
u64 counter;
unsigned long offset;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 2/12] NTP cleanup: Move arches to new ntp interfaces
2005-07-16 2:57 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c john stultz
@ 2005-07-16 2:57 ` john stultz
2005-07-16 2:58 ` [RFC][PATCH - 3/12] NTP cleanup: Remove unused NTP PPS code john stultz
2005-07-18 11:42 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c Pavel Machek
1 sibling, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 2:57 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch converts all of arch specific code to use the new ntp_synced
() and ntp_clear() interfaces. This patch is required for the patch 1 of
the series to build.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part2_B4.patch
============================================
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -42,6 +42,7 @@
#include <linux/init.h>
#include <linux/bcd.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -149,7 +150,7 @@ irqreturn_t timer_interrupt(int irq, voi
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0
+ if (ntp_synced()
&& xtime.tv_sec > state.last_rtc_update + 660
&& xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
&& xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -502,10 +503,7 @@ do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -28,6 +28,7 @@
#include <linux/profile.h>
#include <linux/sysdev.h>
#include <linux/timer.h>
+#include <linux/ntp.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -102,7 +103,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
- if (time_status & STA_UNSYNC || set_rtc == NULL)
+ if (!ntp_synced() || set_rtc == NULL)
return;
if (next_rtc_update &&
@@ -292,10 +293,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -28,6 +28,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -114,7 +115,7 @@ static unsigned long next_rtc_update;
*/
static inline void do_set_rtc(void)
{
- if (time_status & STA_UNSYNC || set_rtc == NULL)
+ if (!ntp_synced() || set_rtc == NULL)
return;
//FIXME - timespec.tv_sec is a time_t not unsigned long
@@ -189,10 +190,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -240,7 +240,7 @@ timer_interrupt(int irq, void *dev_id, s
* The division here is not time critical since it will run once in
* 11 minutes
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - (tick_nsec / 1000) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + (tick_nsec / 1000) / 2) {
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -30,6 +30,7 @@
#include <linux/bcd.h>
#include <linux/timex.h>
#include <linux/init.h>
+#include <linux/ntp.h>
u64 jiffies_64 = INITIAL_JIFFIES;
@@ -113,10 +114,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -21,6 +21,7 @@
#include <linux/profile.h>
#include <linux/irq.h>
#include <linux/mm.h>
+#include <linux/ntp.h>
#include <asm/io.h>
#include <asm/timer-regs.h>
@@ -85,7 +86,7 @@ static irqreturn_t timer_interrupt(int i
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2
@@ -216,10 +217,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -26,6 +26,7 @@
#include <linux/mm.h>
#include <linux/timex.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/io.h>
#include <asm/target_time.h>
@@ -116,10 +117,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -46,6 +46,7 @@
#include <linux/bcd.h>
#include <linux/efi.h>
#include <linux/mca.h>
+#include <linux/ntp.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -194,10 +195,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
@@ -348,7 +346,7 @@ static void sync_cmos_clock(unsigned lon
* This code is run on a timer. If the clock is set, that timer
* may not expire at the correct time. Thus, we adjust...
*/
- if ((time_status & STA_UNSYNC) != 0)
+ if (!ntp_synced())
/*
* Not synced, exit, do not restart a timer (if one is
* running, let it run out).
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/io.h>
#include <asm/m32r.h>
@@ -171,10 +172,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -221,7 +219,7 @@ do_timer_interrupt(int irq, void *dev_id
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0
+ if (ntp_synced()
&& xtime.tv_sec > last_rtc_update + 660
&& (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
&& (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/rtc.h>
+#include <linux/ntp.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -166,10 +167,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -21,6 +21,7 @@
#include <linux/profile.h>
#include <linux/time.h>
#include <linux/timex.h>
+#include <linux/ntp.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -68,7 +69,7 @@ static irqreturn_t timer_interrupt(int i
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -178,10 +179,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -30,6 +30,7 @@
#include <linux/socket.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/ntp.h>
#include <asm/ptrace.h>
#include <asm/page.h>
@@ -632,10 +633,7 @@ asmlinkage int irix_stime(int value)
write_seqlock_irq(&xtime_lock);
xtime.tv_sec = value;
xtime.tv_nsec = 0;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
return 0;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/ntp.h>
#include <asm/bootinfo.h>
#include <asm/compiler.h>
@@ -223,10 +224,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -442,7 +440,7 @@ irqreturn_t timer_interrupt(int irq, voi
* called as close as possible to 500 ms before the new second starts.
*/
write_seqlock(&xtime_lock);
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -12,6 +12,7 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/mm.h>
+#include <linux/ntp.h>
#include <asm/time.h>
#include <asm/pgtable.h>
@@ -118,7 +119,7 @@ again:
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to when a second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -188,10 +189,7 @@ do_settimeofday (struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
}
write_sequnlock_irq(&xtime_lock);
clock_was_set();
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -57,6 +57,7 @@
#include <linux/time.h>
#include <linux/init.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/segment.h>
#include <asm/io.h>
@@ -169,7 +170,7 @@ void timer_interrupt(struct pt_regs * re
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
- if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
+ if ( ppc_md.set_rtc_time && ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ &&
jiffies - wall_jiffies == 1) {
@@ -271,10 +272,7 @@ int do_settimeofday(struct timespec *tv)
*/
last_rtc_update = new_sec - 658;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irqrestore(&xtime_lock, flags);
clock_was_set();
return 0;
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -50,6 +50,7 @@
#include <linux/profile.h>
#include <linux/cpu.h>
#include <linux/security.h>
+#include <linux/ntp.h>
#include <asm/segment.h>
#include <asm/io.h>
@@ -128,7 +129,7 @@ static __inline__ void timer_check_rtc(v
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
- if ( (time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
jiffies - wall_jiffies == 1) {
@@ -437,10 +438,7 @@ int do_settimeofday(struct timespec *tv)
*/
last_rtc_update = new_sec - 658;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
do_gtod.varp->tb_to_xs );
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -29,6 +29,7 @@
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/notifier.h>
+#include <linux/ntp.h>
#include <asm/uaccess.h>
#include <asm/delay.h>
@@ -139,10 +140,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0;
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
@@ -215,10 +216,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -252,7 +250,7 @@ static inline void do_timer_interrupt(in
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/profile.h>
#include <linux/smp.h>
+#include <linux/ntp.h>
#include <asm/registers.h> /* required by inline __asm__ stmt. */
@@ -247,10 +248,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -328,7 +326,7 @@ static inline void do_timer_interrupt(in
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
+#include <linux/ntp.h>
#include <asm/ebus.h>
#include <asm/sbus.h> /* for sanity check... */
@@ -840,10 +841,7 @@ static int pci_do_settimeofday(struct ti
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
return 0;
}
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -30,6 +30,7 @@
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/oplib.h>
#include <asm/segment.h>
@@ -140,7 +141,7 @@ irqreturn_t timer_interrupt(int irq, voi
/* Determine when to update the Mostek clock. */
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -555,10 +556,7 @@ static int sbus_do_settimeofday(struct t
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
return 0;
}
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -30,6 +30,7 @@
#include <linux/cpufreq.h>
#include <linux/percpu.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/oplib.h>
#include <asm/mostek.h>
@@ -449,7 +450,7 @@ static inline void timer_check_rtc(void)
static long last_rtc_update;
/* Determine when to update the Mostek clock. */
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -21,6 +21,7 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/profile.h>
+#include <linux/ntp.h>
#include <asm/io.h>
@@ -66,7 +67,7 @@ static irqreturn_t timer_interrupt (int
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
@@ -169,10 +170,7 @@ int do_settimeofday(struct timespec *tv)
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
- time_adjust = 0; /* stop active adjtime () */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq (&xtime_lock);
clock_was_set();
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -27,6 +27,8 @@
#include <linux/bcd.h>
#include <linux/kallsyms.h>
#include <linux/acpi.h>
+#include <linux/ntp.h>
+
#ifdef CONFIG_ACPI
#include <acpi/achware.h> /* for PM timer frequency */
#endif
@@ -176,10 +178,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
clock_was_set();
@@ -471,7 +470,7 @@ static irqreturn_t timer_interrupt(int i
* off) isn't likely to go away much sooner anyway.
*/
- if ((~time_status & STA_UNSYNC) && xtime.tv_sec > rtc_update &&
+ if (ntp_synced() && xtime.tv_sec > rtc_update &&
abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
set_rtc_mmss(xtime.tv_sec);
rtc_update = xtime.tv_sec + 660;
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/profile.h>
#include <linux/delay.h>
+#include <linux/ntp.h>
#include <asm/timex.h>
#include <asm/platform.h>
@@ -122,10 +123,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_clear();
write_sequnlock_irq(&xtime_lock);
return 0;
}
@@ -184,7 +182,7 @@ again:
next += CCOUNT_PER_JIFFY;
do_timer (regs); /* Linux handler in kernel/timer.c */
- if ((time_status & STA_UNSYNC) == 0 &&
+ if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
jiffies - wall_jiffies == 1) {
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 3/12] NTP cleanup: Remove unused NTP PPS code
2005-07-16 2:57 ` [RFC][PATCH - 2/12] NTP cleanup: Move arches to new ntp interfaces john stultz
@ 2005-07-16 2:58 ` john stultz
2005-07-16 2:59 ` [RFC][PATCH - 4/12] NTP cleanup: Breakup ntp_adjtimex() john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 2:58 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
Since the NTP PPS code required an out of tree patch which I don't
believe there is a 2.6 version of, this patch removes the unused PPS
logic in the kernel.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part3_B4.patch
============================================
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -46,26 +46,9 @@ void time_interpolator_update(long delta
#define time_interpolator_update(x)
#endif
-
-static long pps_offset; /* pps time offset (us) */
-static long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
-
-static long pps_freq; /* frequency offset (scaled ppm) */
-static long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
-
-static long pps_valid = PPS_VALID; /* pps signal watchdog counter */
-
-static int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
-
-static long pps_jitcnt; /* jitter limit exceeded */
-static long pps_calcnt; /* calibration intervals */
-static long pps_errcnt; /* calibration errors */
-static long pps_stbcnt; /* stability limit exceeded */
-
/* Don't completely fail for HZ > 500. */
int tickadj = 500/HZ ? : 1; /* microsecs */
-
/*
* phase-lock loop variables
*/
@@ -235,21 +218,7 @@ void second_overflow(void)
time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
}
- /*
- * Compute the frequency estimate and additional phase
- * adjustment due to frequency error for the next
- * second. When the PPS signal is engaged, gnaw on the
- * watchdog counter and update the frequency computed by
- * the pll and the PPS signal.
- */
- pps_valid++;
- if (pps_valid == PPS_VALID) { /* PPS signal lost */
- pps_jitter = MAXTIME;
- pps_stabil = MAXFREQ;
- time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
- STA_PPSWANDER | STA_PPSERROR);
- }
- ltemp = time_freq + pps_freq;
+ ltemp = time_freq;
if (ltemp < 0)
time_adj -= -ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
else
@@ -307,10 +276,6 @@ int ntp_adjtimex(struct timex *txc)
/* Save for later - semantics of adjtime is to return old value */
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 */
-#endif
-
/* If there are input parameters, then process them */
if (txc->modes) {
if (txc->modes & ADJ_STATUS) /* only set allowed bits */
@@ -322,7 +287,7 @@ int ntp_adjtimex(struct timex *txc)
result = -EINVAL;
goto leave;
}
- time_freq = txc->freq - pps_freq;
+ time_freq = txc->freq;
}
if (txc->modes & ADJ_MAXERROR) {
@@ -356,11 +321,8 @@ int ntp_adjtimex(struct timex *txc)
/* adjtime() is independent from ntp_adjtime() */
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))
- == (STA_PPSTIME | STA_PPSSIGNAL) ?
- pps_offset : txc->offset;
+ } else if (time_status & STA_PLL) {
+ ltemp = txc->offset;
/*
* Scale the phase adjustment and
@@ -415,7 +377,7 @@ int ntp_adjtimex(struct timex *txc)
time_freq = time_tolerance;
else if (time_freq < -time_tolerance)
time_freq = -time_tolerance;
- } /* STA_PLL || STA_PPSTIME */
+ } /* STA_PLL */
} /* txc->modes & ADJ_OFFSET */
if (txc->modes & ADJ_TICK) {
@@ -425,17 +387,8 @@ int ntp_adjtimex(struct timex *txc)
} /* txc->modes */
leave:
- if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
- || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
- && (time_status & STA_PPSSIGNAL) == 0)
- /* p. 24, (b) */
- || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
- == (STA_PPSTIME|STA_PPSJITTER))
- /* p. 24, (c) */
- || ((time_status & STA_PPSFREQ) != 0
- && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
- /* p. 24, (d) */
- result = TIME_ERROR;
+ if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
+ result = TIME_ERROR;
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust;
@@ -445,7 +398,7 @@ leave:
else
txc->offset = time_offset >> SHIFT_UPDATE;
}
- txc->freq = time_freq + pps_freq;
+ txc->freq = time_freq;
txc->maxerror = time_maxerror;
txc->esterror = time_esterror;
txc->status = time_status;
@@ -453,14 +406,17 @@ leave:
txc->precision = time_precision;
txc->tolerance = time_tolerance;
txc->tick = tick_usec;
- txc->ppsfreq = pps_freq;
- txc->jitter = pps_jitter >> PPS_AVG;
- txc->shift = pps_shift;
- txc->stabil = pps_stabil;
- txc->jitcnt = pps_jitcnt;
- txc->calcnt = pps_calcnt;
- txc->errcnt = pps_errcnt;
- txc->stbcnt = pps_stbcnt;
+
+ /* PPS is not implemented, so these are zero */
+ txc->ppsfreq = 0;
+ txc->jitter = 0;
+ txc->shift = 0;
+ txc->stabil = 0;
+ txc->jitcnt = 0;
+ txc->calcnt = 0;
+ txc->errcnt = 0;
+ txc->stbcnt = 0;
+
write_sequnlock_irq(&xtime_lock);
do_gettimeofday(&txc->time);
return result;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 4/12] NTP cleanup: Breakup ntp_adjtimex()
2005-07-16 2:58 ` [RFC][PATCH - 3/12] NTP cleanup: Remove unused NTP PPS code john stultz
@ 2005-07-16 2:59 ` john stultz
2005-07-16 3:00 ` [RFC][PATCH - 5/12] NTP cleanup: Break out leapsecond processing john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 2:59 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch breaks up the complex nesting of code in ntp_adjtimex() by
creating a ntp_hardupdate() function and simplifying some of the logic.
This also follows the documented NTP spec somewhat better.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part4_B4.patch
============================================
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -69,6 +69,9 @@ static long time_reftime;
long time_adjust;
static long time_next_adjust;
+/* Required to safely shift negative values */
+#define shiftR(x,s) (x < 0) ? (-((-x) >> (s))) : ((x) >> (s))
+
int ntp_advance(void)
{
long time_adjust_step, delta_nsec;
@@ -244,12 +247,79 @@ void second_overflow(void)
#endif
}
+/**
+ * ntp_hardupdate - Calculates the offset and freq values
+ * offset: current offset
+ * tv: timeval holding the current time
+ *
+ * Private function, called only by ntp_adjtimex
+ *
+ * This function is called when an offset adjustment is requested.
+ * It calculates the offset adjustment and manipulates the
+ * frequency adjustement accordingly.
+ */
+static int ntp_hardupdate(long offset, struct timespec tv)
+{
+ int ret;
+ long current_offset, interval;
+
+ ret = 0;
+ if (!(time_status & STA_PLL))
+ return ret;
+
+ current_offset = offset;
+ /* Make sure offset is bounded by MAXPHASE */
+ current_offset = min(current_offset, MAXPHASE);
+ current_offset = max(current_offset, -MAXPHASE);
+ time_offset = current_offset << SHIFT_UPDATE;
+
+ if (time_status & STA_FREQHOLD || time_reftime == 0)
+ time_reftime = tv.tv_sec;
+
+ /* calculate seconds since last call to hardupdate */
+ interval = tv.tv_sec - time_reftime;
+ time_reftime = tv.tv_sec;
+
+ /*
+ * Select whether the frequency is to be controlled
+ * and in which mode (PLL or FLL). Clamp to the operating
+ * range. Ugly multiply/divide should be replaced someday.
+ */
+ if ((time_status & STA_FLL) && (interval >= MINSEC)) {
+ long offset_ppm;
+
+ offset_ppm = time_offset / interval;
+ offset_ppm <<= (SHIFT_USEC - SHIFT_UPDATE);
+
+ time_freq += shiftR(offset_ppm, SHIFT_KH);
+
+ } else if ((time_status & STA_PLL) && (interval < MAXSEC)) {
+ long damping, offset_ppm;
+
+ offset_ppm = offset * interval;
+
+ damping = (2 * time_constant) + SHIFT_KF - SHIFT_USEC;
+
+ time_freq += shiftR(offset_ppm, damping);
+
+ } else { /* calibration interval out of bounds (p. 12) */
+ ret = TIME_ERROR;
+ }
+
+ /* bound time_freq */
+ time_freq = min(time_freq, time_tolerance);
+ time_freq = max(time_freq, -time_tolerance);
+
+ return ret;
+}
+
+
/* adjtimex mainly allows reading (and writing, if superuser) of
* kernel time-keeping variables. used by xntpd.
*/
int ntp_adjtimex(struct timex *txc)
{
- long ltemp, mtemp, save_adjust;
+ long save_adjust;
int result;
/* Now we validate the data before disabling interrupts */
@@ -321,63 +391,9 @@ int ntp_adjtimex(struct timex *txc)
/* adjtime() is independent from ntp_adjtime() */
if ((time_next_adjust = txc->offset) == 0)
time_adjust = 0;
- } else if (time_status & STA_PLL) {
- ltemp = txc->offset;
-
- /*
- * Scale the phase adjustment and
- * clamp to the operating range.
- */
- if (ltemp > MAXPHASE)
- time_offset = MAXPHASE << SHIFT_UPDATE;
- else if (ltemp < -MAXPHASE)
- time_offset = -(MAXPHASE
- << SHIFT_UPDATE);
- else
- time_offset = ltemp << SHIFT_UPDATE;
-
- /*
- * Select whether the frequency is to be controlled
- * and in which mode (PLL or FLL). Clamp to the operating
- * range. Ugly multiply/divide should be replaced someday.
- */
-
- if (time_status & STA_FREQHOLD || time_reftime == 0)
- time_reftime = xtime.tv_sec;
-
- mtemp = xtime.tv_sec - time_reftime;
- time_reftime = xtime.tv_sec;
-
- if (time_status & STA_FLL) {
- if (mtemp >= MINSEC) {
- ltemp = (time_offset / mtemp) << (SHIFT_USEC -
- SHIFT_UPDATE);
- if (ltemp < 0)
- time_freq -= -ltemp >> SHIFT_KH;
- else
- time_freq += ltemp >> SHIFT_KH;
- } else /* calibration interval too short (p. 12) */
- result = TIME_ERROR;
- } else { /* PLL mode */
- if (mtemp < MAXSEC) {
- ltemp *= mtemp;
- if (ltemp < 0)
- time_freq -= -ltemp >> (time_constant +
- time_constant +
- SHIFT_KF - SHIFT_USEC);
- else
- time_freq += ltemp >> (time_constant +
- time_constant +
- SHIFT_KF - SHIFT_USEC);
- } else /* calibration interval too long (p. 12) */
- result = TIME_ERROR;
- }
-
- if (time_freq > time_tolerance)
- time_freq = time_tolerance;
- else if (time_freq < -time_tolerance)
- time_freq = -time_tolerance;
- } /* STA_PLL */
+ else if (ntp_hardupdate(txc->offset, xtime))
+ result = TIME_ERROR;
+ }
} /* txc->modes & ADJ_OFFSET */
if (txc->modes & ADJ_TICK) {
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 5/12] NTP cleanup: Break out leapsecond processing
2005-07-16 2:59 ` [RFC][PATCH - 4/12] NTP cleanup: Breakup ntp_adjtimex() john stultz
@ 2005-07-16 3:00 ` john stultz
2005-07-16 3:02 ` [RFC][PATCH - 6/12] NTP cleanup: Clean up ntp_adjtimex() arguement checking john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:00 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch breaks the leapsecond processing logic into its own
function. By making the NTP code avoid making any direct changes to
time, instead allowing the time code to use NTP to decide when to change
time, we better isolate the NTP subsystem.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part5_B4.patch
============================================
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
--- a/include/linux/ntp.h
+++ b/include/linux/ntp.h
@@ -13,6 +13,7 @@
int ntp_advance(void);
int ntp_adjtimex(struct timex*);
void second_overflow(void);
+int ntp_leapsecond(struct timespec now);
void ntp_clear(void);
int ntp_synced(void);
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -40,12 +40,6 @@
#include <linux/jiffies.h>
#include <linux/errno.h>
-#ifdef CONFIG_TIME_INTERPOLATION
-void time_interpolator_update(long delta_nsec);
-#else
-#define time_interpolator_update(x)
-#endif
-
/* Don't completely fail for HZ > 500. */
int tickadj = 500/HZ ? : 1; /* microsecs */
@@ -69,6 +63,8 @@ static long time_reftime;
long time_adjust;
static long time_next_adjust;
+#define SEC_PER_DAY 86400
+
/* Required to safely shift negative values */
#define shiftR(x,s) (x < 0) ? (-((-x) >> (s))) : ((x) >> (s))
@@ -142,59 +138,6 @@ void second_overflow(void)
}
/*
- * Leap second processing. If in leap-insert state at
- * the end of the day, the system clock is set back one
- * second; if in leap-delete state, the system clock is
- * set ahead one second. The microtime() routine or
- * external clock driver will insure that reported time
- * is always monotonic. The ugly divides should be
- * replaced.
- */
- switch (time_state) {
-
- case TIME_OK:
- if (time_status & STA_INS)
- time_state = TIME_INS;
- else if (time_status & STA_DEL)
- time_state = TIME_DEL;
- break;
-
- case TIME_INS:
- if (xtime.tv_sec % 86400 == 0) {
- xtime.tv_sec--;
- wall_to_monotonic.tv_sec++;
- /* The timer interpolator will make time change gradually instead
- * of an immediate jump by one second.
- */
- time_interpolator_update(-NSEC_PER_SEC);
- time_state = TIME_OOP;
- clock_was_set();
- printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
- }
- break;
-
- case TIME_DEL:
- if ((xtime.tv_sec + 1) % 86400 == 0) {
- xtime.tv_sec++;
- wall_to_monotonic.tv_sec--;
- /* Use of time interpolator for a gradual change of time */
- time_interpolator_update(NSEC_PER_SEC);
- time_state = TIME_WAIT;
- clock_was_set();
- printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
- }
- break;
-
- case TIME_OOP:
- time_state = TIME_WAIT;
- break;
-
- case TIME_WAIT:
- if (!(time_status & (STA_INS | STA_DEL)))
- time_state = TIME_OK;
- }
-
- /*
* Compute the phase adjustment for the next second. In
* PLL mode, the offset is reduced by a fixed factor
* times the time constant. In FLL mode the offset is
@@ -438,6 +381,70 @@ leave:
return result;
}
+
+/**
+ * ntp_leapsecond - NTP leapsecond processing code.
+ * now: the current time
+ *
+ * Returns the number of seconds (-1, 0, or 1) that
+ * should be added to the current time to properly
+ * adjust for leapseconds.
+ */
+int ntp_leapsecond(struct timespec now)
+{
+ /*
+ * Leap second processing. If in leap-insert state at
+ * the end of the day, the system clock is set back one
+ * second; if in leap-delete state, the system clock is
+ * set ahead one second.
+ */
+ static time_t leaptime = 0;
+
+ switch (time_state) {
+ case TIME_OK:
+ if (time_status & STA_INS)
+ time_state = TIME_INS;
+ else if (time_status & STA_DEL)
+ time_state = TIME_DEL;
+
+ /* calculate end of today (23:59:59)*/
+ leaptime = now.tv_sec + SEC_PER_DAY -
+ (now.tv_sec % SEC_PER_DAY) - 1;
+ break;
+
+ case TIME_INS:
+ /* Once we are at (or past) leaptime, insert the second */
+ if (now.tv_sec >= leaptime) {
+ time_state = TIME_OOP;
+ printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
+ return -1;
+ }
+ break;
+
+ case TIME_DEL:
+ /* Once we are at (or past) leaptime, delete the second */
+ if (now.tv_sec >= leaptime) {
+ time_state = TIME_WAIT;
+ printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
+ return 1;
+ }
+ break;
+
+ case TIME_OOP:
+ /* Wait for the end of the leap second*/
+ if (now.tv_sec > (leaptime + 1))
+ time_state = TIME_WAIT;
+ break;
+
+ case TIME_WAIT:
+ if (!(time_status & (STA_INS | STA_DEL)))
+ time_state = TIME_OK;
+ }
+
+ return 0;
+}
+
+
/**
* ntp_clear - Clears the NTP state machine.
*
diff --git a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -42,7 +42,7 @@
#include <asm/io.h>
#ifdef CONFIG_TIME_INTERPOLATION
-void time_interpolator_update(long delta_nsec);
+static void time_interpolator_update(long delta_nsec);
#else
#define time_interpolator_update(x)
#endif
@@ -624,9 +624,19 @@ static void update_wall_time(unsigned lo
ticks--;
update_wall_time_one_tick();
if (xtime.tv_nsec >= 1000000000) {
+ int leapsecond;
xtime.tv_nsec -= 1000000000;
xtime.tv_sec++;
second_overflow();
+
+ /* apply leapsecond if appropriate */
+ leapsecond = ntp_leapsecond(xtime);
+ if (leapsecond) {
+ xtime.tv_sec += leapsecond;
+ wall_to_monotonic.tv_sec -= leapsecond;
+ time_interpolator_update(leapsecond * NSEC_PER_SEC);
+ clock_was_set();
+ }
}
} while (ticks);
}
@@ -1272,7 +1282,7 @@ unsigned long time_interpolator_get_offs
#define INTERPOLATOR_ADJUST 65536
#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
-void time_interpolator_update(long delta_nsec)
+static void time_interpolator_update(long delta_nsec)
{
u64 counter;
unsigned long offset;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 6/12] NTP cleanup: Clean up ntp_adjtimex() arguement checking
2005-07-16 3:00 ` [RFC][PATCH - 5/12] NTP cleanup: Break out leapsecond processing john stultz
@ 2005-07-16 3:02 ` john stultz
2005-07-16 3:04 ` [RFC][PATCH - 7/12] NTP cleanup: Cleanup signed shifting logic john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:02 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
Currently ntp_adjtimex() checks the validity of a few arguments values
then takes the xtime_lock then checks the validity of more arguments
while it parses them. This separates the logic so we check the validity
of all arguments before aquiring the xtime lock. This greatly improves
the readability of the code.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part6_B4.patch
============================================
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -267,21 +267,44 @@ int ntp_adjtimex(struct timex *txc)
/* Now we validate the data before disabling interrupts */
- if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
- /* singleshot must not be used with any other mode bits */
- if (txc->modes != ADJ_OFFSET_SINGLESHOT)
- return -EINVAL;
-
- if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
- /* adjustment Offset limited to +- .512 seconds */
- if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
- return -EINVAL;
-
- /* if the quartz is off by more than 10% something is VERY wrong ! */
- if (txc->modes & ADJ_TICK)
- if (txc->tick < 900000/USER_HZ ||
- txc->tick > 1100000/USER_HZ)
- return -EINVAL;
+ /* frequency adjustment limited to +/- MAXFREQ */
+ if ((txc->modes & ADJ_FREQUENCY)
+ && (abs(txc->freq) > MAXFREQ))
+ return -EINVAL;
+
+ /* maxerror adjustment limited to NTP_PHASE_LIMIT */
+ if ((txc->modes & ADJ_MAXERROR)
+ && (txc->maxerror < 0
+ || txc->maxerror >= NTP_PHASE_LIMIT))
+ return -EINVAL;
+
+ /* esterror adjustment limited to NTP_PHASE_LIMIT */
+ if ((txc->modes & ADJ_ESTERROR)
+ && (txc->esterror < 0
+ || txc->esterror >= NTP_PHASE_LIMIT))
+ return -EINVAL;
+
+ /* constant adjustment must be positive */
+ if ((txc->modes & ADJ_TIMECONST)
+ && (txc->constant < 0)) /* NTP v4 uses values > 6 */
+ return -EINVAL;
+
+ /* Single shot mode can only be used by itself */
+ if (((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+ && (txc->modes != ADJ_OFFSET_SINGLESHOT))
+ return -EINVAL;
+
+ /* offset adjustment limited to +/- MAXPHASE */
+ if ((txc->modes != ADJ_OFFSET_SINGLESHOT)
+ && (txc->modes & ADJ_OFFSET)
+ && (abs(txc->offset)>= MAXPHASE))
+ return -EINVAL;
+
+ /* tick adjustment limited to 10% */
+ if ((txc->modes & ADJ_TICK)
+ && ((txc->tick < 900000/USER_HZ)
+ ||(txc->tick > 11000000/USER_HZ)))
+ return -EINVAL;
write_seqlock_irq(&xtime_lock);
result = time_state; /* mostly `TIME_OK' */
@@ -290,65 +313,42 @@ int ntp_adjtimex(struct timex *txc)
save_adjust = time_next_adjust ? time_next_adjust : time_adjust;
/* If there are input parameters, then process them */
- if (txc->modes) {
- if (txc->modes & ADJ_STATUS) /* only set allowed bits */
- time_status = (txc->status & ~STA_RONLY) |
- (time_status & STA_RONLY);
-
- if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */
- if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
- result = -EINVAL;
- goto leave;
- }
- time_freq = txc->freq;
- }
-
- if (txc->modes & ADJ_MAXERROR) {
- if (txc->maxerror < 0
- || txc->maxerror >= NTP_PHASE_LIMIT) {
- result = -EINVAL;
- goto leave;
- }
- time_maxerror = txc->maxerror;
- }
-
- if (txc->modes & ADJ_ESTERROR) {
- if (txc->esterror < 0
- || txc->esterror >= NTP_PHASE_LIMIT) {
- result = -EINVAL;
- goto leave;
- }
- time_esterror = txc->esterror;
- }
- if (txc->modes & ADJ_TIMECONST) { /* p. 24 */
- if (txc->constant < 0) { /* NTP v4 uses values > 6 */
- result = -EINVAL;
- goto leave;
- }
- time_constant = txc->constant;
- }
+ if (txc->modes & ADJ_STATUS) /* only set allowed bits */
+ time_status = (txc->status & ~STA_RONLY) |
+ (time_status & STA_RONLY);
+
+ if (txc->modes & ADJ_FREQUENCY)
+ time_freq = txc->freq;
+
+ if (txc->modes & ADJ_MAXERROR)
+ time_maxerror = txc->maxerror;
+
+ if (txc->modes & ADJ_ESTERROR)
+ time_esterror = txc->esterror;
+
+ if (txc->modes & ADJ_TIMECONST)
+ time_constant = txc->constant;
+
+ if (txc->modes & ADJ_OFFSET) {
+ if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
+ /* adjtime() is independent from ntp_adjtime() */
+ if ((time_next_adjust = txc->offset) == 0)
+ time_adjust = 0;
+ } else if (ntp_hardupdate(txc->offset, xtime))
+ result = TIME_ERROR;
+ }
- if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
- if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
- /* adjtime() is independent from ntp_adjtime() */
- if ((time_next_adjust = txc->offset) == 0)
- time_adjust = 0;
- else if (ntp_hardupdate(txc->offset, xtime))
- result = TIME_ERROR;
- }
- } /* txc->modes & ADJ_OFFSET */
-
- if (txc->modes & ADJ_TICK) {
- tick_usec = txc->tick;
- tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
- }
- } /* txc->modes */
-leave:
+ if (txc->modes & ADJ_TICK) {
+ tick_usec = txc->tick;
+ tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
+ }
if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
result = TIME_ERROR;
+ /* write kernel state to user timex values*/
+
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust;
else {
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 7/12] NTP cleanup: Cleanup signed shifting logic
2005-07-16 3:02 ` [RFC][PATCH - 6/12] NTP cleanup: Clean up ntp_adjtimex() arguement checking john stultz
@ 2005-07-16 3:04 ` john stultz
2005-07-16 3:05 ` [RFC][PATCH - 8/12] NTP cleanup: Integrate second_overflow() logic john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:04 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
Signed shifting must be done carefully, and the ntp code has quite a
number of conditionals to do the signed shifting. This patch makes use
of the local shiftR() macro introduced in a previous patch to simplify a
bit of logic.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part7_B4.patch
============================================
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -165,28 +165,19 @@ void second_overflow(void)
}
ltemp = time_freq;
- if (ltemp < 0)
- time_adj -= -ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
- else
- time_adj += ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+ time_adj += shiftR(ltemp, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
#if HZ == 100
/* Compensate for (HZ==100) != (1 << SHIFT_HZ).
* Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
*/
- if (time_adj < 0)
- time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
- else
- time_adj += (time_adj >> 2) + (time_adj >> 5);
+ time_adj += shiftR(time_adj,2) + shiftR(time_adj,5);
#endif
#if HZ == 1000
/* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
* Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
*/
- if (time_adj < 0)
- time_adj -= (-time_adj >> 6) + (-time_adj >> 7);
- else
- time_adj += (time_adj >> 6) + (time_adj >> 7);
+ time_adj += shiftR(time_adj,6) + shiftR(time_adj,7);
#endif
}
@@ -352,10 +343,7 @@ int ntp_adjtimex(struct timex *txc)
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust;
else {
- if (time_offset < 0)
- txc->offset = -(-time_offset >> SHIFT_UPDATE);
- else
- txc->offset = time_offset >> SHIFT_UPDATE;
+ txc->offset = shiftR(time_offset, SHIFT_UPDATE);
}
txc->freq = time_freq;
txc->maxerror = time_maxerror;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 8/12] NTP cleanup: Integrate second_overflow() logic
2005-07-16 3:04 ` [RFC][PATCH - 7/12] NTP cleanup: Cleanup signed shifting logic john stultz
@ 2005-07-16 3:05 ` john stultz
2005-07-16 3:06 ` [RFC][PATCH - 9/12] NTP cleanup: Improve NTP variable names john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:05 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch removes the second_overflow() logic integrating it into the
ntp_advance() function. This provides a single interface to advance the
internal NTP state machine.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part8_B4.patch
============================================
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
--- a/include/linux/ntp.h
+++ b/include/linux/ntp.h
@@ -10,9 +10,8 @@
#include <linux/timex.h>
/* NTP state machine interfaces */
-int ntp_advance(void);
+int ntp_advance(unsigned long interval_nsec);
int ntp_adjtimex(struct timex*);
-void second_overflow(void);
int ntp_leapsecond(struct timespec now);
void ntp_clear(void);
int ntp_synced(void);
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -30,6 +30,11 @@
* http://www.eecis.udel.edu/~mills/database/rfc/rfc1589.txt
* http://www.eecis.udel.edu/~mills/database/reports/kern/kernb.pdf
*
+* The tricky bits of code to handle the accurate clock support
+* were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+* They were originally developed for SUN and DEC kernels.
+* All the kudos should go to Dave for this stuff.
+*
* NOTE: To simplify the code, we do not implement any of
* the PPS code, as the code that uses it never was merged.
* -johnstul@us.ibm.com
@@ -68,10 +73,69 @@ static long time_next_adjust;
/* Required to safely shift negative values */
#define shiftR(x,s) (x < 0) ? (-((-x) >> (s))) : ((x) >> (s))
-int ntp_advance(void)
+int ntp_advance(unsigned long interval_nsec)
{
+ static unsigned long interval_sum = 0;
long time_adjust_step, delta_nsec;
+
+ /* Some components of the NTP state machine are advanced
+ * in full second increments (this is a hold-over from
+ * the old second_overflow() code)
+ *
+ * XXX - I'd prefer to smoothly apply this math at each
+ * call to ntp_advance() rather then each second.
+ */
+ interval_sum += interval_nsec;
+ while (interval_sum > NSEC_PER_SEC) {
+ long next_adj;
+ interval_sum -= NSEC_PER_SEC;
+
+ /* Bump the maxerror field */
+ time_maxerror += time_tolerance >> SHIFT_USEC;
+ if ( time_maxerror > NTP_PHASE_LIMIT ) {
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_status |= STA_UNSYNC;
+ }
+
+ /*
+ * Compute the phase adjustment for the next second. In
+ * PLL mode, the offset is reduced by a fixed factor
+ * times the time constant. In FLL mode the offset is
+ * used directly. In either mode, the maximum phase
+ * adjustment for each second is clamped so as to spread
+ * the adjustment over not more than the number of
+ * seconds between updates.
+ */
+ next_adj = time_offset;
+ if (!(time_status & STA_FLL))
+ next_adj = shiftR(next_adj, SHIFT_KG + time_constant);
+ next_adj = min(next_adj, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
+ next_adj = max(next_adj, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
+ time_offset -= next_adj;
+
+ time_adj = next_adj << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+
+ time_adj += shiftR(time_freq, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
+
+#if HZ == 100
+ /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
+ * Add 25% and 3.125% to get 128.125;
+ * => only 0.125% error (p. 14)
+ */
+ time_adj += shiftR(time_adj,2) + shiftR(time_adj,5);
+#endif
+#if HZ == 1000
+ /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
+ * Add 1.5625% and 0.78125% to get 1023.4375;
+ * => only 0.05% error (p. 14)
+ */
+ time_adj += shiftR(time_adj,6) + shiftR(time_adj,7);
+#endif
+
+ }
+
+
if ( (time_adjust_step = time_adjust) != 0 ) {
/* We are doing an adjtime thing.
*
@@ -116,71 +180,6 @@ int ntp_advance(void)
return delta_nsec;
}
-
-/*
- * this routine handles the overflow of the microsecond field
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- *
- */
-void second_overflow(void)
-{
- long ltemp;
-
- /* Bump the maxerror field */
- time_maxerror += time_tolerance >> SHIFT_USEC;
- if ( time_maxerror > NTP_PHASE_LIMIT ) {
- time_maxerror = NTP_PHASE_LIMIT;
- time_status |= STA_UNSYNC;
- }
-
- /*
- * Compute the phase adjustment for the next second. In
- * PLL mode, the offset is reduced by a fixed factor
- * times the time constant. In FLL mode the offset is
- * used directly. In either mode, the maximum phase
- * adjustment for each second is clamped so as to spread
- * the adjustment over not more than the number of
- * seconds between updates.
- */
- if (time_offset < 0) {
- ltemp = -time_offset;
- if (!(time_status & STA_FLL))
- ltemp >>= SHIFT_KG + time_constant;
- if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
- ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
- time_offset += ltemp;
- time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- } else {
- ltemp = time_offset;
- if (!(time_status & STA_FLL))
- ltemp >>= SHIFT_KG + time_constant;
- if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
- ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
- time_offset -= ltemp;
- time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- }
-
- ltemp = time_freq;
- time_adj += shiftR(ltemp, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
-
-#if HZ == 100
- /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
- * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
- */
- time_adj += shiftR(time_adj,2) + shiftR(time_adj,5);
-#endif
-#if HZ == 1000
- /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
- * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
- */
- time_adj += shiftR(time_adj,6) + shiftR(time_adj,7);
-#endif
-}
-
/**
* ntp_hardupdate - Calculates the offset and freq values
* offset: current offset
diff --git a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -604,7 +604,7 @@ static void update_wall_time_one_tick(vo
{
long delta_nsec;
- delta_nsec = tick_nsec + ntp_advance();
+ delta_nsec = tick_nsec + ntp_advance(tick_nsec);
xtime.tv_nsec += delta_nsec;
time_interpolator_update(delta_nsec);
@@ -627,7 +627,6 @@ static void update_wall_time(unsigned lo
int leapsecond;
xtime.tv_nsec -= 1000000000;
xtime.tv_sec++;
- second_overflow();
/* apply leapsecond if appropriate */
leapsecond = ntp_leapsecond(xtime);
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 9/12] NTP cleanup: Improve NTP variable names
2005-07-16 3:05 ` [RFC][PATCH - 8/12] NTP cleanup: Integrate second_overflow() logic john stultz
@ 2005-07-16 3:06 ` john stultz
2005-07-16 3:06 ` [RFC][PATCH - 10/12] NTP cleanup: Use ntp_lock instead of xtime_lock john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:06 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch changes the NTP variable names from time_* to ntp_* further
clarifying their use.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part9_B4.patch
============================================
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -68,11 +68,11 @@ void do_gettimeofday(struct timeval *tv)
}
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)
+ if (unlikely(ntp_adjtime_offset < 0) && usec > tickadj)
usec = tickadj;
sec = xtime.tv_sec;
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -166,11 +166,11 @@ void do_gettimeofday(struct timeval *tv)
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
usec = min(usec, max_ntp_tick);
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -142,11 +142,11 @@ void do_gettimeofday(struct timeval *tv)
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
usec = min(usec, max_ntp_tick);
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -122,11 +122,11 @@ void do_gettimeofday(struct timeval *tv)
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
usec = min(usec, max_ntp_tick);
if (lost)
usec += lost * max_ntp_tick;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -171,11 +171,11 @@ void do_gettimeofday(struct timeval *tv)
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
usec = min(usec, max_ntp_tick);
if (lost)
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -355,7 +355,7 @@ int timer_interrupt(struct pt_regs * reg
timer_sync_xtime(lpaca->next_jiffy_update_tb);
timer_check_rtc();
write_sequnlock(&xtime_lock);
- if ( adjusting_time && (time_adjust == 0) )
+ if ( adjusting_time && (ntp_adjtime_offset == 0) )
ppc_adjtimex();
}
lpaca->next_jiffy_update_tb += tb_ticks_per_jiffy;
@@ -582,7 +582,7 @@ void __init time_init(void)
systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
systemcfg->tb_to_xs = tb_to_xs;
- time_freq = 0;
+ ntp_freq = 0;
xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec;
@@ -599,7 +599,7 @@ void __init time_init(void)
* to microseconds to keep do_gettimeofday synchronized
* with ntpd.
*
- * Use the time_adjust, time_freq and time_offset computed by adjtimex to
+ * Use the ntp_adjtime_offset, ntp_freq and ntp_offset computed by adjtimex to
* adjust the frequency.
*/
@@ -617,32 +617,32 @@ void ppc_adjtimex(void)
long singleshot_ppm = 0;
/* Compute parts per million frequency adjustment to accomplish the time adjustment
- implied by time_offset to be applied over the elapsed time indicated by time_constant.
- Use SHIFT_USEC to get it into the same units as time_freq. */
- if ( time_offset < 0 ) {
- ltemp = -time_offset;
+ implied by ntp_offset to be applied over the elapsed time indicated by ntp_constant.
+ Use SHIFT_USEC to get it into the same units as ntp_freq. */
+ if ( ntp_offset < 0 ) {
+ ltemp = -ntp_offset;
ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + time_constant;
+ ltemp >>= SHIFT_KG + ntp_constant;
ltemp = -ltemp;
}
else {
- ltemp = time_offset;
+ ltemp = ntp_offset;
ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + time_constant;
+ ltemp >>= SHIFT_KG + ntp_constant;
}
/* If there is a single shot time adjustment in progress */
- if ( time_adjust ) {
+ if ( ntp_adjtime_offset ) {
#ifdef DEBUG_PPC_ADJTIMEX
printk("ppc_adjtimex: ");
if ( adjusting_time == 0 )
printk("starting ");
- printk("single shot time_adjust = %ld\n", time_adjust);
+ printk("single shot ntp_adjtime_offset = %ld\n", ntp_adjtime_offset);
#endif
adjusting_time = 1;
- /* Compute parts per million frequency adjustment to match time_adjust */
+ /* Compute parts per million frequency adjustment to match ntp_adjtime_offset */
singleshot_ppm = tickadj * HZ;
/*
* The adjustment should be tickadj*HZ to match the code in
@@ -650,21 +650,21 @@ void ppc_adjtimex(void)
* large. 3/4 of tickadj*HZ seems about right
*/
singleshot_ppm -= singleshot_ppm / 4;
- /* Use SHIFT_USEC to get it into the same units as time_freq */
+ /* Use SHIFT_USEC to get it into the same units as ntp_freq */
singleshot_ppm <<= SHIFT_USEC;
- if ( time_adjust < 0 )
+ if ( ntp_adjtime_offset < 0 )
singleshot_ppm = -singleshot_ppm;
}
else {
#ifdef DEBUG_PPC_ADJTIMEX
if ( adjusting_time )
- printk("ppc_adjtimex: ending single shot time_adjust\n");
+ printk("ppc_adjtimex: ending single shot ntp_adjtime_offset\n");
#endif
adjusting_time = 0;
}
/* Add up all of the frequency adjustments */
- delta_freq = time_freq + ltemp + singleshot_ppm;
+ delta_freq = ntp_freq + ltemp + singleshot_ppm;
/* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */
den = 1000000 * (1 << (SHIFT_USEC - 8));
@@ -678,7 +678,7 @@ void ppc_adjtimex(void)
}
#ifdef DEBUG_PPC_ADJTIMEX
- printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
+ printk("ppc_adjtimex: ltemp = %ld, ntp_freq = %ld, singleshot_ppm = %ld\n", ltemp, ntp_freq, singleshot_ppm);
printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
#endif
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -783,11 +783,11 @@ static void pci_do_gettimeofday(struct t
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
usec = min(usec, max_ntp_tick);
if (lost)
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -492,11 +492,11 @@ void do_gettimeofday(struct timeval *tv)
lost = jiffies - wall_jiffies;
/*
- * If time_adjust is negative then NTP is slowing the clock
+ * If ntp_adjtime_offset 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)) {
+ if (unlikely(ntp_adjtime_offset < 0)) {
usec = min(usec, max_ntp_tick);
if (lost)
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
--- a/include/linux/ntp.h
+++ b/include/linux/ntp.h
@@ -20,9 +20,9 @@ int ntp_synced(void);
* these variables cannot be made static just yet
*/
extern int tickadj;
-extern long time_offset;
-extern long time_freq;
-extern long time_adjust;
-extern long time_constant;
+extern long ntp_offset;
+extern long ntp_freq;
+extern long ntp_adjtime_offset;
+extern long ntp_constant;
#endif
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -47,26 +47,28 @@
/* Don't completely fail for HZ > 500. */
int tickadj = 500/HZ ? : 1; /* microsecs */
-
-/*
- * phase-lock loop variables
- */
-/* TIME_ERROR prevents overwriting the CMOS clock */
-static int time_state = TIME_OK; /* clock synchronization status */
-static int time_status = STA_UNSYNC; /* clock status bits */
-long time_offset; /* time adjustment (us) */
-long time_constant = 2; /* pll time constant */
-static long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
-static long time_precision = 1; /* clock precision (us) */
-static long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
-static long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
-static long time_phase; /* phase offset (scaled us) */
-long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
- /* frequency offset (scaled ppm) */
+static long time_phase; /* phase offset (scaled us) */
static long time_adj; /* tick adjust (scaled 1 / HZ) */
-static long time_reftime; /* time at last adjustment (s) */
-long time_adjust;
-static long time_next_adjust;
+
+/* Chapter 5: Kernel Variables [RFC 1589 pg. 28] */
+/* 5.1 Interface Variables */
+static int ntp_status = STA_UNSYNC; /* status */
+long ntp_offset; /* usec */
+long ntp_constant = 2; /* ntp magic? */
+static long ntp_maxerror = NTP_PHASE_LIMIT; /* usec */
+static long ntp_esterror = NTP_PHASE_LIMIT; /* usec */
+static const long ntp_tolerance = MAXFREQ; /* shifted ppm */
+static const long ntp_precision = 1; /* constant */
+
+/* 5.2 Phase-Lock Loop Variables */
+long ntp_freq; /* shifted ppm */
+static long ntp_reftime; /* sec */
+
+/* Extra values */
+static int ntp_state = TIME_OK; /* leapsecond state */
+long ntp_adjtime_offset;
+static long ntp_next_adjtime_offset;
+
#define SEC_PER_DAY 86400
@@ -92,10 +94,10 @@ int ntp_advance(unsigned long interval_n
interval_sum -= NSEC_PER_SEC;
/* Bump the maxerror field */
- time_maxerror += time_tolerance >> SHIFT_USEC;
- if ( time_maxerror > NTP_PHASE_LIMIT ) {
- time_maxerror = NTP_PHASE_LIMIT;
- time_status |= STA_UNSYNC;
+ ntp_maxerror += shiftR(ntp_tolerance, SHIFT_USEC);
+ if (ntp_maxerror > NTP_PHASE_LIMIT) {
+ ntp_maxerror = NTP_PHASE_LIMIT;
+ ntp_status |= STA_UNSYNC;
}
/*
@@ -107,16 +109,16 @@ int ntp_advance(unsigned long interval_n
* the adjustment over not more than the number of
* seconds between updates.
*/
- next_adj = time_offset;
- if (!(time_status & STA_FLL))
- next_adj = shiftR(next_adj, SHIFT_KG + time_constant);
+ next_adj = ntp_offset;
+ if (!(ntp_status & STA_FLL))
+ next_adj = shiftR(next_adj, SHIFT_KG + ntp_constant);
next_adj = min(next_adj, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
next_adj = max(next_adj, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
- time_offset -= next_adj;
+ ntp_offset -= next_adj;
time_adj = next_adj << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- time_adj += shiftR(time_freq, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
+ time_adj += shiftR(ntp_freq, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
#if HZ == 100
/* Compensate for (HZ==100) != (1 << SHIFT_HZ).
@@ -136,23 +138,23 @@ int ntp_advance(unsigned long interval_n
}
- if ( (time_adjust_step = time_adjust) != 0 ) {
+ if ( (time_adjust_step = ntp_adjtime_offset) != 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
+ * Note that a positive ntp_adjtime_offset means we want the clock
* to run faster.
*
* Limit the amount of the step to be in the range
* -tickadj .. +tickadj
*/
- if (time_adjust > tickadj)
+ if (ntp_adjtime_offset > tickadj)
time_adjust_step = tickadj;
- else if (time_adjust < -tickadj)
+ else if (ntp_adjtime_offset < -tickadj)
time_adjust_step = -tickadj;
/* Reduce by this step the amount of time left */
- time_adjust -= time_adjust_step;
+ ntp_adjtime_offset -= time_adjust_step;
}
delta_nsec = time_adjust_step * 1000;
@@ -172,9 +174,9 @@ int ntp_advance(unsigned long interval_n
}
/* Changes by adjtime() do not take effect till next tick. */
- if (time_next_adjust != 0) {
- time_adjust = time_next_adjust;
- time_next_adjust = 0;
+ if (ntp_next_adjtime_offset != 0) {
+ ntp_adjtime_offset = ntp_next_adjtime_offset;
+ ntp_next_adjtime_offset = 0;
}
return delta_nsec;
@@ -197,51 +199,51 @@ static int ntp_hardupdate(long offset, s
long current_offset, interval;
ret = 0;
- if (!(time_status & STA_PLL))
+ if (!(ntp_status & STA_PLL))
return ret;
current_offset = offset;
/* Make sure offset is bounded by MAXPHASE */
current_offset = min(current_offset, MAXPHASE);
current_offset = max(current_offset, -MAXPHASE);
- time_offset = current_offset << SHIFT_UPDATE;
+ ntp_offset = current_offset << SHIFT_UPDATE;
- if (time_status & STA_FREQHOLD || time_reftime == 0)
- time_reftime = tv.tv_sec;
+ if (ntp_status & STA_FREQHOLD || ntp_reftime == 0)
+ ntp_reftime = tv.tv_sec;
/* calculate seconds since last call to hardupdate */
- interval = tv.tv_sec - time_reftime;
- time_reftime = tv.tv_sec;
+ interval = tv.tv_sec - ntp_reftime;
+ ntp_reftime = tv.tv_sec;
/*
* Select whether the frequency is to be controlled
* and in which mode (PLL or FLL). Clamp to the operating
* range. Ugly multiply/divide should be replaced someday.
*/
- if ((time_status & STA_FLL) && (interval >= MINSEC)) {
+ if ((ntp_status & STA_FLL) && (interval >= MINSEC)) {
long offset_ppm;
- offset_ppm = time_offset / interval;
+ offset_ppm = ntp_offset / interval;
offset_ppm <<= (SHIFT_USEC - SHIFT_UPDATE);
- time_freq += shiftR(offset_ppm, SHIFT_KH);
+ ntp_freq += shiftR(offset_ppm, SHIFT_KH);
- } else if ((time_status & STA_PLL) && (interval < MAXSEC)) {
+ } else if ((ntp_status & STA_PLL) && (interval < MAXSEC)) {
long damping, offset_ppm;
offset_ppm = offset * interval;
- damping = (2 * time_constant) + SHIFT_KF - SHIFT_USEC;
+ damping = (2 * ntp_constant) + SHIFT_KF - SHIFT_USEC;
- time_freq += shiftR(offset_ppm, damping);
+ ntp_freq += shiftR(offset_ppm, damping);
} else { /* calibration interval out of bounds (p. 12) */
ret = TIME_ERROR;
}
- /* bound time_freq */
- time_freq = min(time_freq, time_tolerance);
- time_freq = max(time_freq, -time_tolerance);
+ /* bound ntp_freq */
+ ntp_freq = min(ntp_freq, ntp_tolerance);
+ ntp_freq = max(ntp_freq, -ntp_tolerance);
return ret;
}
@@ -297,34 +299,34 @@ int ntp_adjtimex(struct timex *txc)
return -EINVAL;
write_seqlock_irq(&xtime_lock);
- result = time_state; /* mostly `TIME_OK' */
+ result = ntp_state; /* mostly `TIME_OK' */
/* Save for later - semantics of adjtime is to return old value */
- save_adjust = time_next_adjust ? time_next_adjust : time_adjust;
+ save_adjust = ntp_next_adjtime_offset ? ntp_next_adjtime_offset : ntp_adjtime_offset;
/* If there are input parameters, then process them */
if (txc->modes & ADJ_STATUS) /* only set allowed bits */
- time_status = (txc->status & ~STA_RONLY) |
- (time_status & STA_RONLY);
+ ntp_status = (txc->status & ~STA_RONLY) |
+ (ntp_status & STA_RONLY);
if (txc->modes & ADJ_FREQUENCY)
- time_freq = txc->freq;
+ ntp_freq = txc->freq;
if (txc->modes & ADJ_MAXERROR)
- time_maxerror = txc->maxerror;
+ ntp_maxerror = txc->maxerror;
if (txc->modes & ADJ_ESTERROR)
- time_esterror = txc->esterror;
+ ntp_esterror = txc->esterror;
if (txc->modes & ADJ_TIMECONST)
- time_constant = txc->constant;
+ ntp_constant = txc->constant;
if (txc->modes & ADJ_OFFSET) {
if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
/* adjtime() is independent from ntp_adjtime() */
- if ((time_next_adjust = txc->offset) == 0)
- time_adjust = 0;
+ if ((ntp_next_adjtime_offset = txc->offset) == 0)
+ ntp_adjtime_offset = 0;
} else if (ntp_hardupdate(txc->offset, xtime))
result = TIME_ERROR;
}
@@ -334,23 +336,22 @@ int ntp_adjtimex(struct timex *txc)
tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
}
- if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
+ if ((ntp_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
result = TIME_ERROR;
/* write kernel state to user timex values*/
-
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust;
- else {
- txc->offset = shiftR(time_offset, SHIFT_UPDATE);
- }
- txc->freq = time_freq;
- txc->maxerror = time_maxerror;
- txc->esterror = time_esterror;
- txc->status = time_status;
- txc->constant = time_constant;
- txc->precision = time_precision;
- txc->tolerance = time_tolerance;
+ else
+ txc->offset = shiftR(ntp_offset, SHIFT_UPDATE);
+
+ txc->freq = ntp_freq;
+ txc->maxerror = ntp_maxerror;
+ txc->esterror = ntp_esterror;
+ txc->status = ntp_status;
+ txc->constant = ntp_constant;
+ txc->precision = ntp_precision;
+ txc->tolerance = ntp_tolerance;
txc->tick = tick_usec;
/* PPS is not implemented, so these are zero */
@@ -387,12 +388,12 @@ int ntp_leapsecond(struct timespec now)
*/
static time_t leaptime = 0;
- switch (time_state) {
+ switch (ntp_state) {
case TIME_OK:
- if (time_status & STA_INS)
- time_state = TIME_INS;
- else if (time_status & STA_DEL)
- time_state = TIME_DEL;
+ if (ntp_status & STA_INS)
+ ntp_state = TIME_INS;
+ else if (ntp_status & STA_DEL)
+ ntp_state = TIME_DEL;
/* calculate end of today (23:59:59)*/
leaptime = now.tv_sec + SEC_PER_DAY -
@@ -402,7 +403,7 @@ int ntp_leapsecond(struct timespec now)
case TIME_INS:
/* Once we are at (or past) leaptime, insert the second */
if (now.tv_sec >= leaptime) {
- time_state = TIME_OOP;
+ ntp_state = TIME_OOP;
printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
return -1;
}
@@ -411,7 +412,7 @@ int ntp_leapsecond(struct timespec now)
case TIME_DEL:
/* Once we are at (or past) leaptime, delete the second */
if (now.tv_sec >= leaptime) {
- time_state = TIME_WAIT;
+ ntp_state = TIME_WAIT;
printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
return 1;
}
@@ -420,12 +421,12 @@ int ntp_leapsecond(struct timespec now)
case TIME_OOP:
/* Wait for the end of the leap second*/
if (now.tv_sec > (leaptime + 1))
- time_state = TIME_WAIT;
+ ntp_state = TIME_WAIT;
break;
case TIME_WAIT:
- if (!(time_status & (STA_INS | STA_DEL)))
- time_state = TIME_OK;
+ if (!(ntp_status & (STA_INS | STA_DEL)))
+ ntp_state = TIME_OK;
}
return 0;
@@ -439,10 +440,10 @@ int ntp_leapsecond(struct timespec now)
*/
void ntp_clear(void)
{
- time_adjust = 0; /* stop active adjtime() */
- time_status |= STA_UNSYNC;
- time_maxerror = NTP_PHASE_LIMIT;
- time_esterror = NTP_PHASE_LIMIT;
+ ntp_next_adjtime_offset = 0; /* stop active adjtime() */
+ ntp_status |= STA_UNSYNC;
+ ntp_maxerror = NTP_PHASE_LIMIT;
+ ntp_esterror = NTP_PHASE_LIMIT;
}
/**
@@ -451,6 +452,6 @@ void ntp_clear(void)
*/
int ntp_synced(void)
{
- return !(time_status & STA_UNSYNC);
+ return !(ntp_status & STA_UNSYNC);
}
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 10/12] NTP cleanup: Use ntp_lock instead of xtime_lock
2005-07-16 3:06 ` [RFC][PATCH - 9/12] NTP cleanup: Improve NTP variable names john stultz
@ 2005-07-16 3:06 ` john stultz
2005-07-16 3:07 ` [RFC][PATCH - 11/12] NTP cleanup: Introduce PPM adjustment variables john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:06 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch introduces the ntp_lock which replaces the xtime_lock for
serialization in the NTP subsystem. This further isolates the NTP
subsystem from the time subsystem.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part10_B4.patch
============================================
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -69,6 +69,8 @@ static int ntp_state = TIME_OK;
long ntp_adjtime_offset;
static long ntp_next_adjtime_offset;
+/* lock for the above variables */
+static seqlock_t ntp_lock = SEQLOCK_UNLOCKED;
#define SEC_PER_DAY 86400
@@ -79,7 +81,9 @@ int ntp_advance(unsigned long interval_n
{
static unsigned long interval_sum = 0;
long time_adjust_step, delta_nsec;
+ unsigned long flags;
+ write_seqlock_irqsave(&ntp_lock, flags);
/* Some components of the NTP state machine are advanced
* in full second increments (this is a hold-over from
@@ -178,6 +182,7 @@ int ntp_advance(unsigned long interval_n
ntp_adjtime_offset = ntp_next_adjtime_offset;
ntp_next_adjtime_offset = 0;
}
+ write_sequnlock_irqrestore(&ntp_lock, flags);
return delta_nsec;
}
@@ -187,13 +192,13 @@ int ntp_advance(unsigned long interval_n
* offset: current offset
* tv: timeval holding the current time
*
- * Private function, called only by ntp_adjtimex
+ * Private function, called only by ntp_adjtimex while holding ntp_lock
*
* This function is called when an offset adjustment is requested.
* It calculates the offset adjustment and manipulates the
* frequency adjustement accordingly.
*/
-static int ntp_hardupdate(long offset, struct timespec tv)
+static int ntp_hardupdate(long offset, struct timeval tv)
{
int ret;
long current_offset, interval;
@@ -256,6 +261,7 @@ int ntp_adjtimex(struct timex *txc)
{
long save_adjust;
int result;
+ unsigned long flags;
/* Now we validate the data before disabling interrupts */
@@ -298,7 +304,8 @@ int ntp_adjtimex(struct timex *txc)
||(txc->tick > 11000000/USER_HZ)))
return -EINVAL;
- write_seqlock_irq(&xtime_lock);
+ write_seqlock_irqsave(&ntp_lock, flags);
+
result = ntp_state; /* mostly `TIME_OK' */
/* Save for later - semantics of adjtime is to return old value */
@@ -327,7 +334,7 @@ int ntp_adjtimex(struct timex *txc)
/* adjtime() is independent from ntp_adjtime() */
if ((ntp_next_adjtime_offset = txc->offset) == 0)
ntp_adjtime_offset = 0;
- } else if (ntp_hardupdate(txc->offset, xtime))
+ } else if (ntp_hardupdate(txc->offset, txc->time))
result = TIME_ERROR;
}
@@ -364,8 +371,8 @@ int ntp_adjtimex(struct timex *txc)
txc->errcnt = 0;
txc->stbcnt = 0;
- write_sequnlock_irq(&xtime_lock);
- do_gettimeofday(&txc->time);
+ write_sequnlock_irqrestore(&ntp_lock, flags);
+
return result;
}
@@ -387,6 +394,8 @@ int ntp_leapsecond(struct timespec now)
* set ahead one second.
*/
static time_t leaptime = 0;
+ unsigned long flags;
+ write_seqlock_irqsave(&ntp_lock, flags);
switch (ntp_state) {
case TIME_OK:
@@ -429,6 +438,7 @@ int ntp_leapsecond(struct timespec now)
ntp_state = TIME_OK;
}
+ write_sequnlock_irqrestore(&ntp_lock, flags);
return 0;
}
@@ -436,14 +446,18 @@ int ntp_leapsecond(struct timespec now)
/**
* ntp_clear - Clears the NTP state machine.
*
- * Must be called while holding a write on the xtime_lock
*/
void ntp_clear(void)
{
+ unsigned long flags;
+ write_seqlock_irqsave(&ntp_lock, flags);
+
ntp_next_adjtime_offset = 0; /* stop active adjtime() */
ntp_status |= STA_UNSYNC;
ntp_maxerror = NTP_PHASE_LIMIT;
ntp_esterror = NTP_PHASE_LIMIT;
+
+ write_sequnlock_irqrestore(&ntp_lock, flags);
}
/**
diff --git a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -222,6 +222,11 @@ int do_adjtimex(struct timex *txc)
if (txc->modes && !capable(CAP_SYS_TIME))
return -EPERM;
+ /* Note: We set tx->time first,
+ * because ntp_adjtimex uses it
+ */
+ do_gettimeofday(&txc->time);
+
result = ntp_adjtimex(txc);
notify_arch_cmos_timer();
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 11/12] NTP cleanup: Introduce PPM adjustment variables
2005-07-16 3:06 ` [RFC][PATCH - 10/12] NTP cleanup: Use ntp_lock instead of xtime_lock john stultz
@ 2005-07-16 3:07 ` john stultz
2005-07-16 3:09 ` [RFC][PATCH - 12/12] NTP cleanup: use ppm instead of unit adj returned by ntp_advance john stultz
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-16 3:07 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch introduces variables to keep track of the different NTP
adjustment values in PPM units. It also introduces the
ntp_get_adjustment() interface which returns shifted PPM units. The
patch also changes the ppc64 ppc_adjtimex() function to use
ntp_get_adjustment().
This will likely need careful review from the ppc64 folks. There are
some subtle differences between what ntp_get_adjustment() returns and
what ppc_adjtimex() calculates.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part11_B4.patch
============================================
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -106,8 +106,6 @@ extern struct timezone sys_tz;
void ppc_adjtimex(void);
-static unsigned adjusting_time = 0;
-
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
@@ -355,8 +353,7 @@ int timer_interrupt(struct pt_regs * reg
timer_sync_xtime(lpaca->next_jiffy_update_tb);
timer_check_rtc();
write_sequnlock(&xtime_lock);
- if ( adjusting_time && (ntp_adjtime_offset == 0) )
- ppc_adjtimex();
+ ppc_adjtimex();
}
lpaca->next_jiffy_update_tb += tb_ticks_per_jiffy;
}
@@ -582,7 +579,7 @@ void __init time_init(void)
systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
systemcfg->tb_to_xs = tb_to_xs;
- ntp_freq = 0;
+ ntp_clear();
xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec;
@@ -599,7 +596,7 @@ void __init time_init(void)
* to microseconds to keep do_gettimeofday synchronized
* with ntpd.
*
- * Use the ntp_adjtime_offset, ntp_freq and ntp_offset computed by adjtimex to
+ * Use the ntp_get_adjustment computed by adjtimex to
* adjust the frequency.
*/
@@ -609,62 +606,14 @@ void ppc_adjtimex(void)
{
unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec;
unsigned long tb_ticks_per_sec_delta;
- long delta_freq, ltemp;
+ long delta_freq;
struct div_result divres;
unsigned long flags;
struct gettimeofday_vars * temp_varp;
unsigned temp_idx;
- long singleshot_ppm = 0;
- /* Compute parts per million frequency adjustment to accomplish the time adjustment
- implied by ntp_offset to be applied over the elapsed time indicated by ntp_constant.
- Use SHIFT_USEC to get it into the same units as ntp_freq. */
- if ( ntp_offset < 0 ) {
- ltemp = -ntp_offset;
- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + ntp_constant;
- ltemp = -ltemp;
- }
- else {
- ltemp = ntp_offset;
- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
- ltemp >>= SHIFT_KG + ntp_constant;
- }
-
- /* If there is a single shot time adjustment in progress */
- if ( ntp_adjtime_offset ) {
-#ifdef DEBUG_PPC_ADJTIMEX
- printk("ppc_adjtimex: ");
- if ( adjusting_time == 0 )
- printk("starting ");
- printk("single shot ntp_adjtime_offset = %ld\n", ntp_adjtime_offset);
-#endif
-
- adjusting_time = 1;
-
- /* Compute parts per million frequency adjustment to match ntp_adjtime_offset */
- singleshot_ppm = tickadj * HZ;
- /*
- * The adjustment should be tickadj*HZ to match the code in
- * linux/kernel/timer.c, but experiments show that this is too
- * large. 3/4 of tickadj*HZ seems about right
- */
- singleshot_ppm -= singleshot_ppm / 4;
- /* Use SHIFT_USEC to get it into the same units as ntp_freq */
- singleshot_ppm <<= SHIFT_USEC;
- if ( ntp_adjtime_offset < 0 )
- singleshot_ppm = -singleshot_ppm;
- }
- else {
-#ifdef DEBUG_PPC_ADJTIMEX
- if ( adjusting_time )
- printk("ppc_adjtimex: ending single shot ntp_adjtime_offset\n");
-#endif
- adjusting_time = 0;
- }
-
/* Add up all of the frequency adjustments */
- delta_freq = ntp_freq + ltemp + singleshot_ppm;
+ delta_freq = ntp_get_adjustment();
/* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */
den = 1000000 * (1 << (SHIFT_USEC - 8));
@@ -678,7 +627,7 @@ void ppc_adjtimex(void)
}
#ifdef DEBUG_PPC_ADJTIMEX
- printk("ppc_adjtimex: ltemp = %ld, ntp_freq = %ld, singleshot_ppm = %ld\n", ltemp, ntp_freq, singleshot_ppm);
+ printk("ppc_adjtimex: delta_freq = %ld\n", delta_freq);
printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
#endif
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
--- a/include/linux/ntp.h
+++ b/include/linux/ntp.h
@@ -15,14 +15,10 @@ int ntp_adjtimex(struct timex*);
int ntp_leapsecond(struct timespec now);
void ntp_clear(void);
int ntp_synced(void);
+long ntp_get_adjustment(void);
-/* Due to ppc64 having its own NTP code,
- * these variables cannot be made static just yet
- */
+/* these variables cannot be made static just yet */
extern int tickadj;
-extern long ntp_offset;
-extern long ntp_freq;
extern long ntp_adjtime_offset;
-extern long ntp_constant;
#endif
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -41,6 +41,7 @@
*
*********************************************************************/
+#include <linux/kernel.h>
#include <linux/ntp.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
@@ -53,15 +54,15 @@ static long time_adj;
/* Chapter 5: Kernel Variables [RFC 1589 pg. 28] */
/* 5.1 Interface Variables */
static int ntp_status = STA_UNSYNC; /* status */
-long ntp_offset; /* usec */
-long ntp_constant = 2; /* ntp magic? */
+static long ntp_offset; /* usec */
+static long ntp_constant = 2; /* ntp magic? */
static long ntp_maxerror = NTP_PHASE_LIMIT; /* usec */
static long ntp_esterror = NTP_PHASE_LIMIT; /* usec */
static const long ntp_tolerance = MAXFREQ; /* shifted ppm */
static const long ntp_precision = 1; /* constant */
/* 5.2 Phase-Lock Loop Variables */
-long ntp_freq; /* shifted ppm */
+static long ntp_freq; /* shifted ppm */
static long ntp_reftime; /* sec */
/* Extra values */
@@ -69,9 +70,16 @@ static int ntp_state = TIME_OK;
long ntp_adjtime_offset;
static long ntp_next_adjtime_offset;
+static long singleshot_adj; /* +/- MAX_SINGLESHOT_ADJ (ppm)*/
+static long tick_adj; /* txc->tick adjustment (ppm) */
+static long offset_adj; /* offset adjustment (ppm) */
+
+static long shifted_ppm_sum; /* ppm<<SHIFT_USEC sum of total freq adj */
+
/* lock for the above variables */
static seqlock_t ntp_lock = SEQLOCK_UNLOCKED;
+#define MAX_SINGLESHOT_ADJ 500 /* (ppm) */
#define SEC_PER_DAY 86400
/* Required to safely shift negative values */
@@ -82,6 +90,7 @@ int ntp_advance(unsigned long interval_n
static unsigned long interval_sum = 0;
long time_adjust_step, delta_nsec;
unsigned long flags;
+ static long ss_adj = 0;
write_seqlock_irqsave(&ntp_lock, flags);
@@ -119,11 +128,11 @@ int ntp_advance(unsigned long interval_n
next_adj = min(next_adj, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
next_adj = max(next_adj, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
ntp_offset -= next_adj;
+ offset_adj = shiftR(next_adj, SHIFT_UPDATE); /* ppm */
- time_adj = next_adj << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+ time_adj = next_adj << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
time_adj += shiftR(ntp_freq, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
-
#if HZ == 100
/* Compensate for (HZ==100) != (1 << SHIFT_HZ).
* Add 25% and 3.125% to get 128.125;
@@ -138,9 +147,17 @@ int ntp_advance(unsigned long interval_n
*/
time_adj += shiftR(time_adj,6) + shiftR(time_adj,7);
#endif
-
+ /* Set ss_adj for the next second */
+ ss_adj = min_t(unsigned long, singleshot_adj, MAX_SINGLESHOT_ADJ);
+ singleshot_adj -= ss_adj;
}
+ /* calculate total shifted ppm adjustment for the next interval */
+ shifted_ppm_sum = tick_adj<<SHIFT_USEC;
+ shifted_ppm_sum += offset_adj << SHIFT_USEC;
+ shifted_ppm_sum += ntp_freq; /* already shifted by SHIFT_USEC */
+ shifted_ppm_sum += ss_adj << SHIFT_USEC;
+
if ( (time_adjust_step = ntp_adjtime_offset) != 0 ) {
/* We are doing an adjtime thing.
@@ -334,11 +351,17 @@ int ntp_adjtimex(struct timex *txc)
/* adjtime() is independent from ntp_adjtime() */
if ((ntp_next_adjtime_offset = txc->offset) == 0)
ntp_adjtime_offset = 0;
+ singleshot_adj = txc->offset;
} else if (ntp_hardupdate(txc->offset, txc->time))
result = TIME_ERROR;
}
if (txc->modes & ADJ_TICK) {
+ /* first calculate usec/user_tick offset */
+ tick_adj = ((USEC_PER_SEC + USER_HZ/2)/USER_HZ) - txc->tick;
+ /* multiply by user_hz to get usec/sec => ppm */
+ tick_adj *= USER_HZ;
+
tick_usec = txc->tick;
tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
}
@@ -456,6 +479,9 @@ void ntp_clear(void)
ntp_status |= STA_UNSYNC;
ntp_maxerror = NTP_PHASE_LIMIT;
ntp_esterror = NTP_PHASE_LIMIT;
+ singleshot_adj = 0;
+ tick_adj = 0;
+ offset_adj =0;
write_sequnlock_irqrestore(&ntp_lock, flags);
}
@@ -469,3 +495,12 @@ int ntp_synced(void)
return !(ntp_status & STA_UNSYNC);
}
+
+/**
+ * ntp_get_adjustment - Returns Shifted PPM adjustment
+ *
+ */
+long ntp_get_adjustment(void)
+{
+ return shifted_ppm_sum;
+}
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC][PATCH - 12/12] NTP cleanup: use ppm instead of unit adj returned by ntp_advance
2005-07-16 3:07 ` [RFC][PATCH - 11/12] NTP cleanup: Introduce PPM adjustment variables john stultz
@ 2005-07-16 3:09 ` john stultz
0 siblings, 0 replies; 19+ messages in thread
From: john stultz @ 2005-07-16 3:09 UTC (permalink / raw)
To: lkml
Cc: George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan, Roman Zippel
All,
This patch stops ntp_advance() from returning unit adjustments (ie:
nanoseconds). Instead the update_wall_time() function uses the ppm
adjustment from get_ntp_adjustment() which is then converted into a
nanosecond adjustment value.
Any comments or feedback would be greatly appreciated.
thanks
-john
linux-2.6.13-rc3_timeofday-ntp-part12_B4.patch
============================================
diff --git a/include/linux/ntp.h b/include/linux/ntp.h
--- a/include/linux/ntp.h
+++ b/include/linux/ntp.h
@@ -9,8 +9,11 @@
#include <linux/time.h>
#include <linux/timex.h>
+/* Required to safely shift negative values */
+#define shiftR(x,s) (x < 0) ? (-((-x) >> (s))) : ((x) >> (s))
+
/* NTP state machine interfaces */
-int ntp_advance(unsigned long interval_nsec);
+void ntp_advance(unsigned long interval_nsec);
int ntp_adjtimex(struct timex*);
int ntp_leapsecond(struct timespec now);
void ntp_clear(void);
diff --git a/kernel/ntp.c b/kernel/ntp.c
--- a/kernel/ntp.c
+++ b/kernel/ntp.c
@@ -3,7 +3,9 @@
*
* NTP state machine and time scaling code.
*
-* Code moved from kernel/time.c and kernel/timer.c
+* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
+*
+* Code moved and rewritten from kernel/time.c and kernel/timer.c
* Please see those files for original copyrights.
*
* This program is free software; you can redistribute it and/or modify
@@ -48,8 +50,6 @@
/* Don't completely fail for HZ > 500. */
int tickadj = 500/HZ ? : 1; /* microsecs */
-static long time_phase; /* phase offset (scaled us) */
-static long time_adj; /* tick adjust (scaled 1 / HZ) */
/* Chapter 5: Kernel Variables [RFC 1589 pg. 28] */
/* 5.1 Interface Variables */
@@ -82,13 +82,9 @@ static seqlock_t ntp_lock = SEQLOCK_UNLO
#define MAX_SINGLESHOT_ADJ 500 /* (ppm) */
#define SEC_PER_DAY 86400
-/* Required to safely shift negative values */
-#define shiftR(x,s) (x < 0) ? (-((-x) >> (s))) : ((x) >> (s))
-
-int ntp_advance(unsigned long interval_nsec)
+void ntp_advance(unsigned long interval_nsec)
{
static unsigned long interval_sum = 0;
- long time_adjust_step, delta_nsec;
unsigned long flags;
static long ss_adj = 0;
@@ -130,23 +126,6 @@ int ntp_advance(unsigned long interval_n
ntp_offset -= next_adj;
offset_adj = shiftR(next_adj, SHIFT_UPDATE); /* ppm */
-
- time_adj = next_adj << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
- time_adj += shiftR(ntp_freq, (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
-#if HZ == 100
- /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
- * Add 25% and 3.125% to get 128.125;
- * => only 0.125% error (p. 14)
- */
- time_adj += shiftR(time_adj,2) + shiftR(time_adj,5);
-#endif
-#if HZ == 1000
- /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
- * Add 1.5625% and 0.78125% to get 1023.4375;
- * => only 0.05% error (p. 14)
- */
- time_adj += shiftR(time_adj,6) + shiftR(time_adj,7);
-#endif
/* Set ss_adj for the next second */
ss_adj = min_t(unsigned long, singleshot_adj, MAX_SINGLESHOT_ADJ);
singleshot_adj -= ss_adj;
@@ -158,42 +137,6 @@ int ntp_advance(unsigned long interval_n
shifted_ppm_sum += ntp_freq; /* already shifted by SHIFT_USEC */
shifted_ppm_sum += ss_adj << SHIFT_USEC;
-
- if ( (time_adjust_step = ntp_adjtime_offset) != 0 ) {
- /* We are doing an adjtime thing.
- *
- * Prepare time_adjust_step to be within bounds.
- * Note that a positive ntp_adjtime_offset means we want the clock
- * to run faster.
- *
- * Limit the amount of the step to be in the range
- * -tickadj .. +tickadj
- */
- if (ntp_adjtime_offset > tickadj)
- time_adjust_step = tickadj;
- else if (ntp_adjtime_offset < -tickadj)
- time_adjust_step = -tickadj;
-
- /* Reduce by this step the amount of time left */
- ntp_adjtime_offset -= time_adjust_step;
- }
- delta_nsec = time_adjust_step * 1000;
-
- /*
- * Advance the phase, once it gets to one microsecond, then
- * advance the tick more.
- */
- time_phase += time_adj;
- if (time_phase <= -FINENSEC) {
- long ltemp = -time_phase >> (SHIFT_SCALE - 10);
- time_phase += ltemp << (SHIFT_SCALE - 10);
- delta_nsec -= ltemp;
- } else if (time_phase >= FINENSEC) {
- long ltemp = time_phase >> (SHIFT_SCALE - 10);
- time_phase -= ltemp << (SHIFT_SCALE - 10);
- delta_nsec += ltemp;
- }
-
/* Changes by adjtime() do not take effect till next tick. */
if (ntp_next_adjtime_offset != 0) {
ntp_adjtime_offset = ntp_next_adjtime_offset;
@@ -201,7 +144,6 @@ int ntp_advance(unsigned long interval_n
}
write_sequnlock_irqrestore(&ntp_lock, flags);
- return delta_nsec;
}
/**
diff --git a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -598,17 +598,23 @@ struct timespec wall_to_monotonic __attr
EXPORT_SYMBOL(xtime);
-
/* in the NTP reference this is called "hardclock()" */
static void update_wall_time_one_tick(void)
{
- long delta_nsec;
+ long delta_nsec, ppm;
+ unsigned long interval_nsec;
+
+ interval_nsec = tick_nsec;
+ ppm = ntp_get_adjustment();
- delta_nsec = tick_nsec + ntp_advance(tick_nsec);
+ delta_nsec = interval_nsec;
+ delta_nsec += shiftR((interval_nsec * ppm),SHIFT_USEC)/1000000;
xtime.tv_nsec += delta_nsec;
- time_interpolator_update(delta_nsec);
+ ntp_advance(interval_nsec);
+
+ time_interpolator_update(delta_nsec);
}
/*
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC - 0/12] NTP cleanup work (v. B4)
2005-07-16 2:55 [RFC - 0/12] NTP cleanup work (v. B4) john stultz
2005-07-16 2:57 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c john stultz
@ 2005-07-17 18:00 ` Roman Zippel
2005-07-20 16:26 ` john stultz
1 sibling, 1 reply; 19+ messages in thread
From: Roman Zippel @ 2005-07-17 18:00 UTC (permalink / raw)
To: john stultz
Cc: lkml, George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan
Hi,
On Fri, 15 Jul 2005, john stultz wrote:
> In my attempts to rework the timeofday subsystem, it was suggested I
> try to avoid mixing cleanups with functional changes. In response to the
> suggestion I've tried to break out the majority of the NTP cleanups I've
> been working out of my larger patch and try to feed it in piece meal.
>
> The goal of this patch set is to isolate the in kernel NTP state machine
> in the hope of simplifying the current timeofday code.
I don't really like, where you taken it with ntp_advance(). With these
patches you put half the ntp state machine in there and execute it at
every single tick.
>From the previous patches I can guess where you want to go with this, but
I think it's the wrong direction. The code is currently as is for a
reason, it's optimized for tick based system and I don't see a reason to
change this for tick based system.
If you want to change this for cycle based system, you have to give more
control to the arch/timer source, which simply call a different set of
functions and the ntp core system basically just acts as a library to the
timer source.
Tick based timer sources continue to update xtime and cycle based system
will modify the cycle multiplier (e.g. what ppc64 does). Don't force
everything to use the same set of functions, you'll make it only more
complex. Larger ntp state updates don't have to be done more than once a
second and leave the details of how the clock is updated to the clock
source (just provide some library functions it can use).
bye, Roman
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c
2005-07-16 2:57 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c john stultz
2005-07-16 2:57 ` [RFC][PATCH - 2/12] NTP cleanup: Move arches to new ntp interfaces john stultz
@ 2005-07-18 11:42 ` Pavel Machek
2005-07-20 20:44 ` john stultz
1 sibling, 1 reply; 19+ messages in thread
From: Pavel Machek @ 2005-07-18 11:42 UTC (permalink / raw)
To: john stultz; +Cc: kernel list
Hi!
> This patch moves the generic NTP code from time.c and timer.c into
> ntp.c. It makes most of the NTP variables static providing more
> understandable interfaces like ntp_synced() and ntp_clear().
>
> Since some of the newly made static variables are used in arch generic
> code, this patch alone will not compile. Thus this patch requires part 2
> of the series which fixes the arch specific uses of the newly static
> variables.
>
> Any comments or feedback would be greatly appreciated.
>
> thanks
> -john
>
> diff --git a/kernel/ntp.c b/kernel/ntp.c
> new file mode 100644
> --- /dev/null
> +++ b/kernel/ntp.c
> @@ -0,0 +1,490 @@
> +/********************************************************************
> +* linux/kernel/ntp.c
> +*
> +* NTP state machine and time scaling code.
> +*
> +* Code moved from kernel/time.c and kernel/timer.c
> +* Please see those files for original copyrights.
> +*
> +* This program is free software; you can redistribute it and/or modify
> +* it under the terms of the GNU General Public License as published by
> +* the Free Software Foundation; either version 2 of the License, or
> +* (at your option) any later version.
> +*
> +* This program is distributed in the hope that it will be useful,
> +* but WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +* GNU General Public License for more details.
> +*
> +* You should have received a copy of the GNU General Public License
> +* along with this program; if not, write to the Free Software
> +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> +*
> +* Notes:
> +*
> +* Hopefully you should never have to understand or touch
> +* any of the code below. but don't let that keep you from trying!
~~~ should be "," ?
> +* This code is loosely based on David Mills' RFC 1589 and its
> +* updates. Please see the following for more details:
> +* http://www.eecis.udel.edu/~mills/database/rfc/rfc1589.txt
> +* http://www.eecis.udel.edu/~mills/database/reports/kern/kernb.pdf
> +*
> +* NOTE: To simplify the code, we do not implement any of
> +* the PPS code, as the code that uses it never was merged.
> +* -johnstul@us.ibm.com
> +*
> +*********************************************************************/
> +
> +#include <linux/ntp.h>
> +#include <linux/jiffies.h>
> +#include <linux/errno.h>
> +
> +#ifdef CONFIG_TIME_INTERPOLATION
> +void time_interpolator_update(long delta_nsec);
> +#else
> +#define time_interpolator_update(x)
do {} while (0) is safer...
> + result = time_state; /* mostly `TIME_OK' */
> +
> + /* Save for later - semantics of adjtime is to return old value */
> + 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 */
> +#endif
Please remove deleted code completely.
> +/**
> + * ntp_synced - Returns 1 if the NTP status is not UNSYNC
> + *
> + */
> +int ntp_synced(void)
> +{
> + return !(time_status & STA_UNSYNC);
> +}
Should this be inline in header somewhere?
Pavel
--
teflon -- maybe it is a trademark, but it should not be.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC - 0/12] NTP cleanup work (v. B4)
2005-07-17 18:00 ` [RFC - 0/12] NTP cleanup work (v. B4) Roman Zippel
@ 2005-07-20 16:26 ` john stultz
2005-07-21 10:39 ` Roman Zippel
0 siblings, 1 reply; 19+ messages in thread
From: john stultz @ 2005-07-20 16:26 UTC (permalink / raw)
To: Roman Zippel
Cc: lkml, George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan
On Sun, 2005-07-17 at 20:00 +0200, Roman Zippel wrote:
> On Fri, 15 Jul 2005, john stultz wrote:
>
> > In my attempts to rework the timeofday subsystem, it was suggested I
> > try to avoid mixing cleanups with functional changes. In response to the
> > suggestion I've tried to break out the majority of the NTP cleanups I've
> > been working out of my larger patch and try to feed it in piece meal.
> >
> > The goal of this patch set is to isolate the in kernel NTP state machine
> > in the hope of simplifying the current timeofday code.
>
> I don't really like, where you taken it with ntp_advance(). With these
> patches you put half the ntp state machine in there and execute it at
> every single tick.
Hmm. While second_overflow() has been integrated into ntp_advance, we
are not actually running that code every tick. Instead we keep an
internal interval counter that runs the equivalent second_overflow()
code only once a second. Maybe I'm not understanding specifically which
you're talking about?
> From the previous patches I can guess where you want to go with this, but
> I think it's the wrong direction. The code is currently as is for a
> reason, it's optimized for tick based system and I don't see a reason to
> change this for tick based system.
Well, with the exception of the last two patches, these changes should
just be cleanups. If you notice a change in behavior in the first 10
patches, please let me know.
> If you want to change this for cycle based system, you have to give more
> control to the arch/timer source, which simply call a different set of
> functions and the ntp core system basically just acts as a library to the
> timer source.
> Tick based timer sources continue to update xtime and cycle based system
> will modify the cycle multiplier (e.g. what ppc64 does). Don't force
> everything to use the same set of functions, you'll make it only more
> complex.
In a sense that's what I'm trying to provide, the NTP state machine will
provide the adjustment that you can either apply completely at tick time
or continually w/ a timesource.
I really don't think the NTP changes I've mailed is very complex.
Please, be specific and point to something you think is an issue and
I'll do my best to fix it.
> Larger ntp state updates don't have to be done more than once a
> second and leave the details of how the clock is updated to the clock
> source (just provide some library functions it can use).
Again, I'm not be doing larger NTP state machine changes every tick.
Thanks again for the feedback, I really do appreciate the review.
thanks
-john
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c
2005-07-18 11:42 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c Pavel Machek
@ 2005-07-20 20:44 ` john stultz
0 siblings, 0 replies; 19+ messages in thread
From: john stultz @ 2005-07-20 20:44 UTC (permalink / raw)
To: Pavel Machek; +Cc: kernel list
On Mon, 2005-07-18 at 13:42 +0200, Pavel Machek wrote:
> Hi!
> > Any comments or feedback would be greatly appreciated.
> > +#ifdef CONFIG_TIME_INTERPOLATION
> > +void time_interpolator_update(long delta_nsec);
> > +#else
> > +#define time_interpolator_update(x)
>
> do {} while (0) is safer...
Applied.
> > + result = time_state; /* mostly `TIME_OK' */
> > +
> > + /* Save for later - semantics of adjtime is to return old value */
> > + 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 */
> > +#endif
>
> Please remove deleted code completely.
Done in a later patch, but good point, I'll kill it in the first one.
Thanks for the review and feedback!
-john
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC - 0/12] NTP cleanup work (v. B4)
2005-07-20 16:26 ` john stultz
@ 2005-07-21 10:39 ` Roman Zippel
2005-07-26 1:03 ` john stultz
0 siblings, 1 reply; 19+ messages in thread
From: Roman Zippel @ 2005-07-21 10:39 UTC (permalink / raw)
To: john stultz
Cc: lkml, George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan
Hi,
On Wed, 20 Jul 2005, john stultz wrote:
> I really don't think the NTP changes I've mailed is very complex.
> Please, be specific and point to something you think is an issue and
> I'll do my best to fix it.
Maybe I should explain, in what direction I would take it.
Let's first only take tick based updates, one property I don't want to see
go away (and which you remove in the last patch), is to basically update
xtime at every tick by (tick_nsec+time_adj) (and maybe fold time_adjust
into time_adj), no multiply/divide just adds/shifts. Every second (or
maybe even less frequently) we update time_adj, where we even might
integrate a better to way to add previous errors due to SHIFT_HZ.
To add support for continous time sources, the generic ntp code would just
provide [tick,frequency,offset] values and the time source converts it
into its internal values. A tick based source calculates [tick_nsec,
time_adj] and a continous source calculates the [offset,multiplier]. These
values should be recalculated as infrequently as possible and not every
single tick as you do with ppc_adjtimex. This also means a continous
source updates xtime basically by calling gettimeofday (what ppc64 already
almost does) and doesn't use update_wall_time() at all.
Maybe I'm missing something, but I don't see a reason to forcibly merge
both ways to update the clock, keep them seperate and let the generic ntp
code provide the basic parameters which the time source uses to update the
clock. The important thing is to precalculate as much as possible, so that
the runtime overhead is as low as possible and these precalculations
differ between time sources, so what your patches basically do is to
remove all of these precalculations and I can't convince myself to see
this as a good thing.
BTW do you have any user space test code for this? This might be useful to
verify that the changes are really correct and a prototype might be a good
way to demonstrate the kernel changes.
bye, Roman
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC - 0/12] NTP cleanup work (v. B4)
2005-07-21 10:39 ` Roman Zippel
@ 2005-07-26 1:03 ` john stultz
0 siblings, 0 replies; 19+ messages in thread
From: john stultz @ 2005-07-26 1:03 UTC (permalink / raw)
To: Roman Zippel
Cc: lkml, George Anzinger, frank, Anton Blanchard, benh,
Nishanth Aravamudan
On Thu, 2005-07-21 at 12:39 +0200, Roman Zippel wrote:
> Hi,
>
> On Wed, 20 Jul 2005, john stultz wrote:
>
> > I really don't think the NTP changes I've mailed is very complex.
> > Please, be specific and point to something you think is an issue and
> > I'll do my best to fix it.
>
> Maybe I should explain, in what direction I would take it.
> Let's first only take tick based updates, one property I don't want to see
> go away (and which you remove in the last patch), is to basically update
> xtime at every tick by (tick_nsec+time_adj) (and maybe fold time_adjust
> into time_adj), no multiply/divide just adds/shifts. Every second (or
> maybe even less frequently) we update time_adj, where we even might
> integrate a better to way to add previous errors due to SHIFT_HZ.
Hmm. Ok, would something like ntp_static_interval_adjustment() or
whatnot be a decent interface to provide a fixed single tick adjustment
as precalculated by the NTP state machine? Similar to what I have in
patch 10, but via a separate interface?
> To add support for continous time sources, the generic ntp code would just
> provide [tick,frequency,offset] values and the time source converts it
> into its internal values. A tick based source calculates [tick_nsec,
> time_adj] and a continous source calculates the [offset,multiplier]. These
> values should be recalculated as infrequently as possible and not every
> single tick as you do with ppc_adjtimex. This also means a continous
> source updates xtime basically by calling gettimeofday (what ppc64 already
> almost does) and doesn't use update_wall_time() at all.
Yep, that sounds doable. Although yes, the ppc_adjtimex is more
overhead, I went with the worse implementation to scratch out my idea
adn see if the ppc folks might scream and suggest the proper way.
> Maybe I'm missing something, but I don't see a reason to forcibly merge
> both ways to update the clock, keep them seperate and let the generic ntp
> code provide the basic parameters which the time source uses to update the
> clock. The important thing is to precalculate as much as possible, so that
> the runtime overhead is as low as possible and these precalculations
> differ between time sources, so what your patches basically do is to
> remove all of these precalculations and I can't convince myself to see
> this as a good thing.
I don't know if that's the case. I am precalculating things, but maybe
we're misunderstanding each other. Regardless, yes, for the tick based
systems that can't go continuous I can preserve the existing behavior
(if not possibly improve it some).
> BTW do you have any user space test code for this? This might be useful to
> verify that the changes are really correct and a prototype might be a good
> way to demonstrate the kernel changes.
I do not right now, after seeing Rusty's talk at OLS this sounds like
quite a nice idea. I was thinking of a simple simulator that has two
files: the first a list of hardware time values and and the second a
list of operations (gettimeofday, timer_interrupt, adjtimex). We can
then generate time sequences and action sequences and run them through
the simulator of both the current and old implementations.
Not that this is completely trivial to do, but it did seem like a good
idea. I'll see what I can do.
thanks
-john
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2005-07-26 1:03 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-16 2:55 [RFC - 0/12] NTP cleanup work (v. B4) john stultz
2005-07-16 2:57 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c john stultz
2005-07-16 2:57 ` [RFC][PATCH - 2/12] NTP cleanup: Move arches to new ntp interfaces john stultz
2005-07-16 2:58 ` [RFC][PATCH - 3/12] NTP cleanup: Remove unused NTP PPS code john stultz
2005-07-16 2:59 ` [RFC][PATCH - 4/12] NTP cleanup: Breakup ntp_adjtimex() john stultz
2005-07-16 3:00 ` [RFC][PATCH - 5/12] NTP cleanup: Break out leapsecond processing john stultz
2005-07-16 3:02 ` [RFC][PATCH - 6/12] NTP cleanup: Clean up ntp_adjtimex() arguement checking john stultz
2005-07-16 3:04 ` [RFC][PATCH - 7/12] NTP cleanup: Cleanup signed shifting logic john stultz
2005-07-16 3:05 ` [RFC][PATCH - 8/12] NTP cleanup: Integrate second_overflow() logic john stultz
2005-07-16 3:06 ` [RFC][PATCH - 9/12] NTP cleanup: Improve NTP variable names john stultz
2005-07-16 3:06 ` [RFC][PATCH - 10/12] NTP cleanup: Use ntp_lock instead of xtime_lock john stultz
2005-07-16 3:07 ` [RFC][PATCH - 11/12] NTP cleanup: Introduce PPM adjustment variables john stultz
2005-07-16 3:09 ` [RFC][PATCH - 12/12] NTP cleanup: use ppm instead of unit adj returned by ntp_advance john stultz
2005-07-18 11:42 ` [RFC][PATCH - 1/12] NTP cleanup: Move NTP code into ntp.c Pavel Machek
2005-07-20 20:44 ` john stultz
2005-07-17 18:00 ` [RFC - 0/12] NTP cleanup work (v. B4) Roman Zippel
2005-07-20 16:26 ` john stultz
2005-07-21 10:39 ` Roman Zippel
2005-07-26 1:03 ` john stultz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox