[chrony-dev] [PATCH 3/3] Set refclock poll timer based on last poll time, not offset from now

[ Thread Index | Date Index | More chrony.tuxfamily.org/chrony-dev Archives ]


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-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble?  Email listmaster@xxxxxxxxxxxxxxxxxxxx.


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/