summaryrefslogtreecommitdiff
path: root/ntpd/ntp_loopfilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_loopfilter.c')
-rw-r--r--ntpd/ntp_loopfilter.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c
index 01772bd1ffe9..b7a742bbd183 100644
--- a/ntpd/ntp_loopfilter.c
+++ b/ntpd/ntp_loopfilter.c
@@ -15,6 +15,7 @@
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include "timexsup.h"
#include <limits.h>
#include <stdio.h>
@@ -167,6 +168,9 @@ u_char sys_poll; /* time constant/poll (log2 s) */
int tc_counter; /* jiggle counter */
double last_offset; /* last offset (s) */
+u_int tc_twinlo; /* TC step down not before this time */
+u_int tc_twinhi; /* TC step up not before this time */
+
/*
* Huff-n'-puff filter variables
*/
@@ -761,30 +765,21 @@ local_clock(
if (ext_enable) {
ntv.modes = MOD_STATUS;
} else {
-#ifdef STA_NANO
- ntv.modes = MOD_BITS | MOD_NANO;
-#else /* STA_NANO */
ntv.modes = MOD_BITS;
-#endif /* STA_NANO */
- if (clock_offset < 0)
- dtemp = -.5;
- else
- dtemp = .5;
+ ntv.offset = var_long_from_dbl(
+ clock_offset, &ntv.modes);
#ifdef STA_NANO
- ntv.offset = (int32)(clock_offset * 1e9 +
- dtemp);
ntv.constant = sys_poll;
#else /* STA_NANO */
- ntv.offset = (int32)(clock_offset * 1e6 +
- dtemp);
ntv.constant = sys_poll - 4;
#endif /* STA_NANO */
if (ntv.constant < 0)
ntv.constant = 0;
- ntv.esterror = (u_int32)(clock_jitter * 1e6);
- ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
- sys_rootdisp) * 1e6);
+ ntv.esterror = usec_long_from_dbl(
+ clock_jitter);
+ ntv.maxerror = usec_long_from_dbl(
+ sys_rootdelay / 2 + sys_rootdisp);
ntv.status = STA_PLL;
/*
@@ -823,22 +818,15 @@ local_clock(
ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, hardpps_enable, 0, __LINE__ - 1);
}
pll_status = ntv.status;
-#ifdef STA_NANO
- clock_offset = ntv.offset / 1e9;
-#else /* STA_NANO */
- clock_offset = ntv.offset / 1e6;
-#endif /* STA_NANO */
+ clock_offset = dbl_from_var_long(ntv.offset, ntv.status);
clock_frequency = FREQTOD(ntv.freq);
/*
* If the kernel PPS is lit, monitor its performance.
*/
if (ntv.status & STA_PPSTIME) {
-#ifdef STA_NANO
- clock_jitter = ntv.jitter / 1e9;
-#else /* STA_NANO */
- clock_jitter = ntv.jitter / 1e6;
-#endif /* STA_NANO */
+ clock_jitter = dbl_from_var_long(
+ ntv.jitter, ntv.status);
}
#if defined(STA_NANO) && NTP_API == 4
@@ -888,34 +876,52 @@ local_clock(
* increased, otherwise it is decreased. A bit of hysteresis
* helps calm the dance. Works best using burst mode. Don't
* fiddle with the poll during the startup clamp period.
+ * [Bug 3615] also observe time gates to avoid eager stepping
*/
if (freq_cnt > 0) {
tc_counter = 0;
+ tc_twinlo = current_time;
+ tc_twinhi = current_time;
} else if (fabs(clock_offset) < CLOCK_PGATE * clock_jitter) {
tc_counter += sys_poll;
if (tc_counter > CLOCK_LIMIT) {
tc_counter = CLOCK_LIMIT;
- if (sys_poll < peer->maxpoll) {
- tc_counter = 0;
- sys_poll++;
- }
+ if (sys_poll < peer->maxpoll)
+ sys_poll += (current_time >= tc_twinhi);
}
} else {
tc_counter -= sys_poll << 1;
if (tc_counter < -CLOCK_LIMIT) {
tc_counter = -CLOCK_LIMIT;
- if (sys_poll > peer->minpoll) {
- tc_counter = 0;
- sys_poll--;
- }
+ if (sys_poll > peer->minpoll)
+ sys_poll -= (current_time >= tc_twinlo);
}
}
/*
* If the time constant has changed, update the poll variables.
+ *
+ * [bug 3615] also set new time gates
+ * The time limit for stepping down will be half the TC interval
+ * or 60 secs from now, whatever is bigger, and the step up time
+ * limit will be half the TC interval after the step down limit.
+ *
+ * The 'sys_poll' value affects the servo loop gain, and
+ * overshooting sys_poll slows it down unnecessarily. Stepping
+ * down too fast also has bad effects.
+ *
+ * The 'tc_counter' dance itself is something that *should*
+ * happen *once* every (1 << sys_poll) seconds, I think, but
+ * that's not how it works right now, and adding time guards
+ * seems the least intrusive way to handle this.
*/
- if (osys_poll != sys_poll)
- poll_update(peer, sys_poll);
+ if (osys_poll != sys_poll) {
+ u_int deadband = 1u << (sys_poll - 1);
+ tc_counter = 0;
+ tc_twinlo = current_time + max(deadband, 60);
+ tc_twinhi = tc_twinlo + deadband;
+ poll_update(peer, sys_poll, 0);
+ }
/*
* Yibbidy, yibbbidy, yibbidy; that'h all folks.