From: Dave Hart Date: Mon, 19 Sep 2011 18:09:12 +0000 (+0000) Subject: [Bug 1981] Initial offset convergence applies frequency correction 2x X-Git-Tag: NTP_4_2_7P214~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90d56421a3024210e96df72f57dd7fe18b203949;p=thirdparty%2Fntp.git [Bug 1981] Initial offset convergence applies frequency correction 2x with kernel discipline. [Bug 2008] Initial offset convergence degraded with 500 PPM adjtime(). bk: 4e778548igd1M9_obMYst6Y230H0dQ --- diff --git a/ChangeLog b/ChangeLog index 3ed459824..2aa951266 100644 --- 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 * [Bug 1999] NMEA does not send PMOTG messages any more. (4.2.7p212) 2011/09/07 Released by Harlan Stenn diff --git a/libntp/systime.c b/libntp/systime.c index a862e69b2..c1bd2bd61 100644 --- a/libntp/systime.c +++ b/libntp/systime.c @@ -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 diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c index b03766031..715f2c3e4 100644 --- a/ntpd/ntp_loopfilter.c +++ b/ntpd/ntp_loopfilter.c @@ -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;