When polling refclocks, the next poll time is currently calculated by adding the desired inter-poll time to the current time. Given refclock polling occurs at the end of the main loop, this results in each poll slipping by, roughly, the time taken for the main loop. While this should be relatively small, this can add up on refclocks with sub-second poll times.
Specifically, on a 1GHz amd64 AMD GX-412TC with a few PHC refclocks being polled, a main loop iteration can take a millisecond or two, depending on the time taken to read the PHC clocks. This easily adds up to poll interval slippage, slipping the update interval and leading to samples which are ignored due to missing their maxlockage setting. To ensure polling happens at the right interval, we simply track when the last poll happened and increment with that as a base rather than the current time. --- refclock.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/refclock.c b/refclock.c index 84f7439..da3da94 100644 --- a/refclock.c +++ b/refclock.c @@ -62,6 +62,7 @@ struct RCL_Instance_Record { int driver_parameter_length; int driver_poll; int driver_polled; + struct timespec next_poll; int poll; int leap_status; int local; @@ -174,6 +175,8 @@ RCL_AddRefclock(RefclockParameters *params) inst->driver_parameter_length = 0; inst->driver_poll = params->driver_poll; inst->poll = params->poll; + inst->next_poll.tv_sec = 0; + inst->next_poll.tv_nsec = 0; inst->driver_polled = 0; inst->leap_status = LEAP_Normal; inst->local = params->local; @@ -762,6 +765,8 @@ poll_timeout(void *arg) { NTP_Sample sample; int poll, stratum; + struct timespec now, sched; + double delay; RCL_Instance inst = (RCL_Instance)arg; @@ -805,7 +810,22 @@ poll_timeout(void *arg) } } - inst->timeout_id = SCH_AddTimeoutByDelay(UTI_Log2ToDouble(poll), poll_timeout, arg); + delay = UTI_Log2ToDouble(poll); + LCL_ReadRawTime(&now); + if (inst->next_poll.tv_nsec == 0 && inst->next_poll.tv_sec == 0) { + UTI_AddDoubleToTimespec(&now, delay, &sched); + } else { + UTI_AddDoubleToTimespec(&inst->next_poll, delay, &sched); + if (UTI_CompareTimespecs(&now, &sched) > 0) { + UTI_AddDoubleToTimespec(&now, delay, &sched); + LOG(LOGS_WARN, "Can't poll fast enough, skipping poll window"); + } + } + inst->next_poll = sched; + if (UTI_CompareTimespecs(&now, &sched) > 0) { + LOG_FATAL("Timeout overflow"); + } + inst->timeout_id = SCH_AddTimeout(&sched, poll_timeout, arg); } static void -- 2.39.1 -- To unsubscribe email chrony-dev-requ...@chrony.tuxfamily.org with "unsubscribe" in the subject. For help email chrony-dev-requ...@chrony.tuxfamily.org with "help" in the subject. Trouble? Email listmas...@chrony.tuxfamily.org.