[PATCH 9/10] NTP: convert to the NTP4 model

From: Roman Zippel
Date: Wed Dec 21 2005 - 18:27:25 EST



This converts the kernel ntp model into a model which matches the
nanokernel reference implementations. The previous patches already
increased the resolution and precision of the computations, so that this
conversion becomes quite simple.



Signed-off-by: Roman Zippel <zippel@xxxxxxxxxxxxxx>

---

include/linux/timex.h | 12 +++++-------
kernel/time.c | 40 ++++++++++++++++------------------------
kernel/timer.c | 12 ++----------
3 files changed, 23 insertions(+), 41 deletions(-)

Index: linux-2.6-mm/include/linux/timex.h
===================================================================
--- linux-2.6-mm.orig/include/linux/timex.h 2005-12-21 12:12:22.000000000 +0100
+++ linux-2.6-mm/include/linux/timex.h 2005-12-21 12:12:26.000000000 +0100
@@ -71,10 +71,9 @@
* zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
* respectively.
*/
-#define SHIFT_KG 6 /* phase factor (shift) */
-#define SHIFT_KF 16 /* PLL frequency factor (shift) */
-#define SHIFT_KH 2 /* FLL frequency factor (shift) */
-#define MAXTC 6 /* maximum time constant (shift) */
+#define SHIFT_PLL 4 /* PLL frequency factor (shift) */
+#define SHIFT_FLL 2 /* FLL frequency factor (shift) */
+#define MAXTC 10 /* maximum time constant (shift) */

/*
* The SHIFT_SCALE define establishes the decimal point of the time_phase
@@ -91,7 +90,6 @@
* FINENSEC is 1 ns in SHIFT_UPDATE units of the time_phase variable.
*/
#define SHIFT_SCALE 22 /* phase scale (shift) */
-#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
#define SHIFT_USEC 16 /* frequency offset scale (shift) */
#define SHIFT_NSEC 12 /* kernel frequency offset scale */
#define FINENSEC (1L << SHIFT_SCALE) /* ~1 ns in phase units */
@@ -99,8 +97,8 @@
#define MAXPHASE 500000000L /* max phase error (ns) */
#define MAXFREQ (500000L << SHIFT_NSEC) /* max frequency error (ns/s) */
#define MAXFREQ_USER (500L << SHIFT_USEC) /* max frequency error (ppm) */
-#define MINSEC 16L /* min interval between updates (s) */
-#define MAXSEC 1200L /* max interval between updates (s) */
+#define MINSEC 256 /* min interval between updates (s) */
+#define MAXSEC 2048 /* max interval between updates (s) */
#define NTP_PHASE_LIMIT ((MAXPHASE / 1000) << 5) /* beyond max. dispersion */

/*
Index: linux-2.6-mm/kernel/time.c
===================================================================
--- linux-2.6-mm.orig/kernel/time.c 2005-12-21 12:12:22.000000000 +0100
+++ linux-2.6-mm/kernel/time.c 2005-12-21 12:12:26.000000000 +0100
@@ -212,7 +212,7 @@ void __attribute__ ((weak)) notify_arch_
int do_adjtimex(struct timex *txc)
{
long ltemp, mtemp, save_adjust;
- s64 freq_adj;
+ s64 freq_adj, temp64;
int result;

/* In order to modify anything, you gotta be super-user! */
@@ -284,7 +284,7 @@ int do_adjtimex(struct timex *txc)
result = -EINVAL;
goto leave;
}
- time_constant = txc->constant;
+ time_constant = min(txc->constant + 4, (long)MAXTC);
}

if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
@@ -316,28 +316,20 @@ int do_adjtimex(struct timex *txc)
time_reftime = xtime.tv_sec;
mtemp = xtime.tv_sec - time_reftime;
time_reftime = xtime.tv_sec;
- freq_adj = 0;
- if (time_status & STA_FLL) {
- if (mtemp >= MINSEC) {
- if (time_offset < 0) {
- freq_adj = (s64)-time_offset << SHIFT_USEC;
- do_div(freq_adj, mtemp);
- freq_adj = -(freq_adj >> SHIFT_KH);
- } else {
- freq_adj = (s64)time_offset << SHIFT_USEC;
- do_div(freq_adj, mtemp);
- freq_adj = freq_adj >> SHIFT_KH;
- }
- } else /* calibration interval too short (p. 12) */
- result = TIME_ERROR;
- } else { /* PLL mode */
- if (mtemp < MAXSEC) {
- freq_adj = (s64)ltemp * mtemp;
- freq_adj = shift_right(freq_adj,(time_constant +
- time_constant +
- SHIFT_KF - SHIFT_USEC));
- } else /* calibration interval too long (p. 12) */
- result = TIME_ERROR;
+
+ freq_adj = (s64)time_offset * mtemp;
+ freq_adj = shift_right(freq_adj, (time_constant + SHIFT_PLL +
+ 2) * 2 - SHIFT_NSEC);
+ if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
+ if (time_offset < 0) {
+ temp64 = (s64)-time_offset << SHIFT_NSEC;
+ do_div(temp64, mtemp << SHIFT_FLL);
+ freq_adj -= temp64;
+ } else {
+ temp64 = (s64)time_offset << SHIFT_NSEC;
+ do_div(temp64, mtemp << SHIFT_FLL);
+ freq_adj += temp64;
+ }
}
freq_adj += time_freq;
freq_adj = min(freq_adj, (s64)MAXFREQ);
Index: linux-2.6-mm/kernel/timer.c
===================================================================
--- linux-2.6-mm.orig/kernel/timer.c 2005-12-21 12:12:22.000000000 +0100
+++ linux-2.6-mm/kernel/timer.c 2005-12-21 12:12:26.000000000 +0100
@@ -713,11 +713,7 @@ static void second_overflow(void)
* 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 / HZ) << SHIFT_HZ) / MINSEC))
- ltemp = ((MAXPHASE / HZ) << SHIFT_HZ) / MINSEC;
+ ltemp = -time_offset >> (SHIFT_PLL + time_constant);
time_offset += ltemp;
tick_nsec_curr -= ltemp >> SHIFT_HZ;
time_adj_curr -= (ltemp << (SHIFT_SCALE - SHIFT_HZ)) & (FINENSEC - 1);
@@ -726,11 +722,7 @@ static void second_overflow(void)
time_adj_curr += FINENSEC;
}
} else {
- ltemp = time_offset;
- if (!(time_status & STA_FLL))
- ltemp >>= SHIFT_KG + time_constant;
- if (ltemp > (((MAXPHASE / HZ) << SHIFT_HZ) / MINSEC))
- ltemp = ((MAXPHASE / HZ) << SHIFT_HZ) / MINSEC;
+ ltemp = time_offset >> (SHIFT_PLL + time_constant);
time_offset -= ltemp;
tick_nsec_curr += ltemp >> SHIFT_HZ;
time_adj_curr += (ltemp << (SHIFT_SCALE - SHIFT_HZ)) & (FINENSEC - 1);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/