]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1981] Initial offset convergence applies frequency correction 2x
authorDave Hart <hart@ntp.org>
Mon, 19 Sep 2011 18:09:12 +0000 (18:09 +0000)
committerDave Hart <hart@ntp.org>
Mon, 19 Sep 2011 18:09:12 +0000 (18:09 +0000)
  with kernel discipline.
[Bug 2008] Initial offset convergence degraded with 500 PPM adjtime().

bk: 4e778548igd1M9_obMYst6Y230H0dQ

ChangeLog
libntp/systime.c
ntpd/ntp_loopfilter.c

index 3ed459824d95e241d8c988733a7e24e476872ca5..2aa951266e4fcd96594dfa25b6e1fe91acba5b5d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+* [Bug 1981] Initial offset convergence applies frequency correction 2x
+  with kernel discipline.
+* [Bug 2008] Initial offset convergence degraded with 500 PPM adjtime().
 (4.2.7p213) 2011/09/08 Released by Harlan Stenn <stenn@ntp.org>
 * [Bug 1999] NMEA does not send PMOTG messages any more.
 (4.2.7p212) 2011/09/07 Released by Harlan Stenn <stenn@ntp.org>
index a862e69b27a34ac5a346087eb12de26709c9ea93..c1bd2bd616843ec8df944f0bd371f57920ec92bc 100644 (file)
@@ -136,6 +136,18 @@ adj_systime(
        long    ticks;
        int     isneg = 0;
 
+       /*
+        * The Windows port adj_systime() depends on being called each
+        * second even when there's no additional correction, to allow
+        * emulation of adjtime() behavior on top of an API that simply
+        * sets the current rate.  This POSIX implementation needs to
+        * ignore invocations with zero correction, otherwise ongoing
+        * EVNT_NSET adjtime() can be aborted by a tiny adjtime()
+        * triggered by sys_residual.
+        */
+       if (0. == now)
+               return;
+
        /*
         * Most Unix adjtime() implementations adjust the system clock
         * in microsecond quanta, but some adjust in 10-ms quanta. We
index b037660312673c105f406a7f55c5c5dd8bbc9a78..715f2c3e419821445dcd96fcfbfb5067d1aaefc7 100644 (file)
@@ -136,9 +136,9 @@ static u_int loop_tai;              /* last TAI offset */
 /*
  * Clock state machine control flags
  */
-int    ntp_enable = 1;         /* clock discipline enabled */
+int    ntp_enable = TRUE;      /* clock discipline enabled */
 int    pll_control;            /* kernel support available */
-int    kern_enable = 1;        /* kernel support enabled */
+int    kern_enable = TRUE;     /* kernel support enabled */
 int    pps_enable;             /* kernel PPS discipline enabled */
 int    ext_enable;             /* external clock enabled */
 int    pps_stratum;            /* pps stratum */
@@ -186,7 +186,7 @@ init_loopfilter(void)
         */
        sys_poll = ntp_minpoll;
        clock_jitter = LOGTOD(sys_precision);
-       freq_cnt = clock_minstep;
+       freq_cnt = (int)clock_minstep;
 }
 
 /*
@@ -220,15 +220,16 @@ local_clock(
         * the open-loop response and then go home.
         */
 #ifdef LOCKCLOCK
-       return (0);
-
-#else /* LOCKCLOCK */
+       {
+#else
        if (!ntp_enable) {
+#endif /* LOCKCLOCK */
                record_loop_stats(fp_offset, drift_comp, clock_jitter,
                    clock_stability, sys_poll);
                return (0);
        }
 
+#ifndef LOCKCLOCK
        /*
         * If the clock is way off, panic is declared. The clock_panic
         * defaults to 1000 s; if set to zero, the panic will never
@@ -682,7 +683,8 @@ adj_host_clock(
        void
        )
 {
-       double  adjustment;
+       double  offset_adj;
+       double  freq_adj;
 
        /*
         * Update the dispersion since the last update. In contrast to
@@ -694,32 +696,55 @@ adj_host_clock(
         */
        sys_rootdisp += clock_phi;
 #ifndef LOCKCLOCK
-       if (state != EVNT_SYNC)
+       if (!ntp_enable || mode_ntpdate)
                return;
-       
-       if (freq_cnt > 0)
+       /*
+        * Determine the phase adjustment. The gain factor (denominator)
+        * increases with poll interval, so is dominated by the FLL
+        * above the Allan intercept. Note the reduced time constant at
+        * startup.
+        */
+       if (state != EVNT_SYNC) {
+               offset_adj = 0.;
+       } else if (freq_cnt > 0) {
+               offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(1));
                freq_cnt--;
+#ifdef KERNEL_PLL
+       } else if (pll_control && kern_enable) {
+               offset_adj = 0.;
+#endif /* KERNEL_PLL */
+       } else {
+               offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
+       }
 
        /*
-        * If clock discipline is disabled or if the kernel is enabled,
-        * get out of Dodge quick.
+        * If the kernel discipline is enabled the frequency correction
+        * drift_comp has already been engaged via ntp_adjtime() in
+        * set_freq().  Otherwise it is a component of the adj_systime()
+        * offset.
         */
-       if (!ntp_enable || mode_ntpdate || (pll_control &&
-           kern_enable && freq_cnt == 0))
-               return;
+#ifdef KERNEL_PLL
+       if (pll_control && kern_enable)
+               freq_adj = 0.;
+       else
+#endif /* KERNEL_PLL */
+               freq_adj = drift_comp;
 
+       /* Bound absolute value of total adjustment to NTP_MAXFREQ. */
+       if (offset_adj + freq_adj > NTP_MAXFREQ)
+               offset_adj = NTP_MAXFREQ - freq_adj;
+       else if (offset_adj + freq_adj < -NTP_MAXFREQ)
+               offset_adj = -NTP_MAXFREQ - freq_adj;
+
+       clock_offset -= offset_adj;
        /*
-        * Implement the phase and frequency adjustments. The gain
-        * factor (denominator) increases with poll interval, so is
-        * dominated by the FLL above the Allan intercept. Note the
-        * reduced time constant at startup.
+        * Windows port adj_systime() must be called each second,
+        * even if the argument is zero, to ease emulation of 
+        * adjtime() using Windows' slew API which controls the rate
+        * but does not automatically stop slewing when an offset
+        * has decayed to zero.
         */
-       if (freq_cnt > 0)
-               adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(1));
-       else
-               adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
-       clock_offset -= adjustment;
-       adj_systime(adjustment + drift_comp);
+       adj_systime(offset_adj + freq_adj);
 #endif /* LOCKCLOCK */
 }
 
@@ -762,9 +787,9 @@ direct_freq(
        double  fp_offset
        )
 {
-       set_freq(fp_offset / (current_time -
-           clock_epoch));
-       return (drift_comp);
+       set_freq(fp_offset / (current_time - clock_epoch));
+
+       return drift_comp;
 }
 
 
@@ -776,39 +801,28 @@ set_freq(
        double  freq            /* frequency update */
        )
 {
-       char    tbuf[80];
+       const char *    loop_desc;
 
        drift_comp = freq;
-
+       loop_desc = "ntpd";
 #ifdef KERNEL_PLL
-       /*
-        * If the kernel is enabled, update the kernel frequency.
-        */
        if (pll_control && kern_enable) {
-               memset(&ntv,  0, sizeof(ntv));
+               loop_desc = "kernel";
+               ZERO(ntv);
                ntv.modes = MOD_FREQUENCY;
                ntv.freq = DTOFREQ(drift_comp);
                ntp_adjtime(&ntv);
-               snprintf(tbuf, sizeof(tbuf), "kernel %.3f PPM",
-                   drift_comp * 1e6);
-               report_event(EVNT_FSET, NULL, tbuf);
-       } else {
-               snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM",
-                   drift_comp * 1e6);
-               report_event(EVNT_FSET, NULL, tbuf);
        }
-#else /* KERNEL_PLL */
-       snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM", drift_comp *
-           1e6);
-       report_event(EVNT_FSET, NULL, tbuf);
 #endif /* KERNEL_PLL */
+       mprintf_event(EVNT_FSET, NULL, "%s %.3f PPM", loop_desc,
+           drift_comp * 1e6);
 }
 
 /*
  * huff-n'-puff filter
  */
 void
-huffpuff()
+huffpuff(void)
 {
        int i;