From: Miroslav Lichvar Date: Mon, 11 Aug 2025 14:00:38 +0000 (+0200) Subject: hwclock: don't drop valid samples in HCL_ProcessReadings() X-Git-Tag: 4.8-pre1~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5535384878901c6ce77066a3fbdb7d2ae1aeef12;p=thirdparty%2Fchrony.git hwclock: don't drop valid samples in HCL_ProcessReadings() Modify the HCL_ProcessReadings() function to try to always provide a valid sample. Instead of dropping a sample outside of the expected delay, provide its assumed quality level as a small integer (relative to already accumulated samples), and let the caller decide what quality is acceptable. --- diff --git a/hwclock.c b/hwclock.c index 06515e7b..eea2c774 100644 --- a/hwclock.c +++ b/hwclock.c @@ -163,7 +163,8 @@ HCL_NeedsNewSample(HCL_Instance clock, struct timespec *now) int HCL_ProcessReadings(HCL_Instance clock, int n_readings, struct timespec tss[][3], - struct timespec *hw_ts, struct timespec *local_ts, double *err) + struct timespec *hw_ts, struct timespec *local_ts, double *err, + int *quality) { double delay, raw_delay, min_delay, low_delay, high_delay, e, pred_err; double delay_sum, hw_sum, local_sum, local_prec, freq; @@ -228,11 +229,13 @@ HCL_ProcessReadings(HCL_Instance clock, int n_readings, struct timespec tss[][3] UTI_AddDoubleToTimespec(&tss[0][1], hw_sum / combined, hw_ts); UTI_AddDoubleToTimespec(&tss[0][0], local_sum / combined, local_ts); *err = MAX(delay_sum / combined / 2.0, clock->precision); + *quality = 2; return 1; } - /* Accept the reading with minimum delay if its interval does not contain - the current offset predicted from previous samples */ + /* Indicate acceptable quality of the reading with minimum delay if its + interval does not contain the current offset predicted from previous + samples, or a new sample is needed to get the tracking working */ *hw_ts = tss[min_reading][1]; UTI_AddDoubleToTimespec(&tss[min_reading][0], min_delay / freq / 2.0, local_ts); @@ -242,11 +245,14 @@ HCL_ProcessReadings(HCL_Instance clock, int n_readings, struct timespec tss[][3] LCL_CookTime(local_ts, &ts1, NULL); if (!HCL_CookTime(clock, hw_ts, &ts2, &e) || ((pred_err = UTI_DiffTimespecsToDouble(&ts1, &ts2)) > *err)) { - DEBUG_LOG("Accepted reading err=%e prerr=%e", *err, pred_err); - return 1; + *quality = 1; + } else { + *quality = 0; } - return 0; + DEBUG_LOG("Min-delay reading err=%e prerr=%e ql=%d", *err, pred_err, *quality); + + return 1; } /* ================================================== */ diff --git a/hwclock.h b/hwclock.h index c3415ad6..1484ddaa 100644 --- a/hwclock.h +++ b/hwclock.h @@ -38,10 +38,14 @@ extern void HCL_DestroyInstance(HCL_Instance clock); /* Check if a new sample should be accumulated at this time */ extern int HCL_NeedsNewSample(HCL_Instance clock, struct timespec *now); -/* Process new readings of the HW clock in form of (sys, hw, sys) triplets and - produce a sample which can be accumulated */ +/* Process new readings of the HW clock in the form of (sys, hw, sys) triplets + and produce a sample which can be accumulated by HCL_AccumulateSample(). + Indicate the quality of the sample relative to already processed samples as + a value of 0, 1, or 2, where a sample of quality 0 should normally be + dropped. */ extern int HCL_ProcessReadings(HCL_Instance clock, int n_readings, struct timespec tss[][3], - struct timespec *hw_ts, struct timespec *local_ts, double *err); + struct timespec *hw_ts, struct timespec *local_ts, double *err, + int *quality); /* Accumulate a new sample */ extern void HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts, diff --git a/ntp_io_linux.c b/ntp_io_linux.c index 9b53d7bf..23f427a5 100644 --- a/ntp_io_linux.c +++ b/ntp_io_linux.c @@ -519,7 +519,7 @@ poll_phc(struct Interface *iface, struct timespec *now) struct timespec sample_phc_ts, sample_sys_ts, sample_local_ts; struct timespec phc_readings[PHC_READINGS][3]; double phc_err, local_err, interval; - int n_readings; + int n_readings, quality; if (!HCL_NeedsNewSample(iface->clock, now)) return; @@ -543,7 +543,8 @@ poll_phc(struct Interface *iface, struct timespec *now) return; if (!HCL_ProcessReadings(iface->clock, n_readings, phc_readings, - &sample_phc_ts, &sample_sys_ts, &phc_err)) + &sample_phc_ts, &sample_sys_ts, &phc_err, &quality) || + quality <= 0) return; LCL_CookTime(&sample_sys_ts, &sample_local_ts, &local_err); diff --git a/refclock_phc.c b/refclock_phc.c index 08da75f3..fe79c839 100644 --- a/refclock_phc.c +++ b/refclock_phc.c @@ -198,7 +198,7 @@ static int phc_poll(RCL_Instance instance) struct timespec phc_ts, sys_ts, local_ts, readings[PHC_READINGS][3]; struct phc_instance *phc; double phc_err, local_err; - int n_readings; + int n_readings, quality; phc = (struct phc_instance *)RCL_GetDriverData(instance); @@ -210,15 +210,20 @@ static int phc_poll(RCL_Instance instance) if (!phc->extpps) RCL_UpdateReachability(instance); - if (!HCL_ProcessReadings(phc->clock, n_readings, readings, &phc_ts, &sys_ts, &phc_err)) + if (!HCL_ProcessReadings(phc->clock, n_readings, readings, + &phc_ts, &sys_ts, &phc_err, &quality)) return 0; LCL_CookTime(&sys_ts, &local_ts, &local_err); - HCL_AccumulateSample(phc->clock, &phc_ts, &local_ts, phc_err + local_err); + if (quality > 0) + HCL_AccumulateSample(phc->clock, &phc_ts, &local_ts, phc_err + local_err); if (phc->extpps) return 0; + if (quality <= 0) + return 0; + DEBUG_LOG("PHC offset: %+.9f err: %.9f", UTI_DiffTimespecsToDouble(&phc_ts, &sys_ts), phc_err); diff --git a/test/unit/hwclock.c b/test/unit/hwclock.c index 79c08790..d2b94143 100644 --- a/test/unit/hwclock.c +++ b/test/unit/hwclock.c @@ -32,9 +32,9 @@ test_unit(void) { struct timespec start_hw_ts, start_local_ts, hw_ts, local_ts, ts; struct timespec readings[MAX_READINGS][3]; + int i, j, k, l, new_sample, n_readings, count, quality; HCL_Instance clock; double freq, jitter, interval, dj, err, sum; - int i, j, k, l, new_sample, n_readings, count; LCL_Initialise(); TST_RegisterDummyDrivers(); @@ -84,11 +84,13 @@ test_unit(void) UTI_ZeroTimespec(&hw_ts); UTI_ZeroTimespec(&local_ts); - if (HCL_ProcessReadings(clock, n_readings, readings, &hw_ts, &local_ts, &err)) { - HCL_AccumulateSample(clock, &hw_ts, &local_ts, 2.0 * jitter); - new_sample = 1; - } else { - new_sample = 0; + new_sample = 0; + if (HCL_ProcessReadings(clock, n_readings, readings, &hw_ts, &local_ts, &err, &quality)) { + TEST_CHECK(quality >= 0 && quality <= 2); + if (quality > 0) { + HCL_AccumulateSample(clock, &hw_ts, &local_ts, 2.0 * jitter); + new_sample = 1; + } } }