]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Introduce offset correction rate
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 5 Sep 2011 13:45:32 +0000 (15:45 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 15 Nov 2011 11:27:44 +0000 (12:27 +0100)
We want to correct the offset quickly, but we also want to keep the
frequency error caused by the correction itself low.

Define correction rate as the area of the region bounded by the graph of
offset corrected in time. Set the rate so that the time needed to correct
an offset equal to the current sourcestats stddev will be equal to the
update interval (assuming linear adjustment). The offset and the
time needed to make the correction are inversely proportional.

This is only a suggestion and it's up to the system driver how the
adjustment will be executed.

13 files changed:
acquire.c
cmdmon.c
local.c
local.h
localp.h
reference.c
reference.h
rtc_linux.c
sources.c
sys_linux.c
sys_netbsd.c
sys_solaris.c
sys_sunos.c

index 6b38fe399af718157b72979fb5d1db9b9df27bdf..250dca28772cc5e1d90fbcbaa105a42b74b94936 100644 (file)
--- a/acquire.c
+++ b/acquire.c
@@ -708,7 +708,7 @@ process_measurements(void)
       LOG(LOGS_INFO, LOGF_Acquire, "System's initial offset : %.6f seconds %s of true (slew)",
           fabs(estimated_offset),
           (estimated_offset >= 0) ? "fast" : "slow");
-      LCL_AccumulateOffset(estimated_offset);
+      LCL_AccumulateOffset(estimated_offset, 0.0);
     }
 
   } else {
index 0baf86dae08007967696317305aeb2fab3e42b51..7810fefdc18e6d999cae2ea5dd2968130cf2413f 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -1354,7 +1354,7 @@ handle_doffset(CMD_Request *rx_message, CMD_Reply *tx_message)
   usec = (long)(ntohl(rx_message->data.doffset.usec));
   doffset = (double) sec + 1.0e-6 * (double) usec;
   LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta offset of %.6f seconds", doffset);
-  LCL_AccumulateOffset(doffset);
+  LCL_AccumulateOffset(doffset, 0.0);
   tx_message->status = htons(STT_SUCCESS);
 }
 
diff --git a/local.c b/local.c
index 12fecf4363a0edf67c70b7b5970f0dfc757793eb..b300cc6df0f29b0b9c275413d798e6747675bd95 100644 (file)
--- a/local.c
+++ b/local.c
@@ -443,7 +443,7 @@ LCL_AccumulateDeltaFrequency(double dfreq)
 /* ================================================== */
 
 void
-LCL_AccumulateOffset(double offset)
+LCL_AccumulateOffset(double offset, double corr_rate)
 {
   ChangeListEntry *ptr;
   struct timeval raw, cooked;
@@ -454,7 +454,7 @@ LCL_AccumulateOffset(double offset)
   LCL_ReadRawTime(&raw);
   LCL_CookTime(&raw, &cooked, NULL);
 
-  (*drv_accrue_offset)(offset);
+  (*drv_accrue_offset)(offset, corr_rate);
 
   /* Dispatch to all handlers */
   for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
@@ -505,7 +505,7 @@ LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
 /* ================================================== */
 
 void
-LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
+LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate)
 {
   ChangeListEntry *ptr;
   struct timeval raw, cooked;
@@ -532,7 +532,7 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
   current_freq_ppm = (*drv_set_freq)(current_freq_ppm);
   dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm);
 
-  (*drv_accrue_offset)(doffset);
+  (*drv_accrue_offset)(doffset, corr_rate);
 
   /* Dispatch to all handlers */
   for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
@@ -598,7 +598,7 @@ LCL_MakeStep(double threshold)
     return 0;
 
   /* Cancel remaining slew and make the step */
-  LCL_AccumulateOffset(correction);
+  LCL_AccumulateOffset(correction, 0.0);
   LCL_ApplyStepOffset(-correction);
 
   LOG(LOGS_WARN, LOGF_Local, "System clock was stepped by %.3f seconds", correction);
diff --git a/local.h b/local.h
index 40c085363e4b31b0d284a621eb7090eb3b215b89..eea70722f7ba94c1ca00cd612dce5e425dd7d3c8 100644 (file)
--- a/local.h
+++ b/local.h
@@ -138,9 +138,10 @@ extern void LCL_AccumulateDeltaFrequency(double dfreq);
 /* Routine to apply an offset (in seconds) to the local clock.  The
    argument should be positive to move the clock backwards (i.e. the
    local clock is currently fast of true time), or negative to move it
-   forwards (i.e. it is currently slow of true time). */
+   forwards (i.e. it is currently slow of true time).  Provided is also
+   a suggested correction rate (correction time * offset). */
 
-extern void LCL_AccumulateOffset(double offset);
+extern void LCL_AccumulateOffset(double offset, double corr_rate);
 
 /* Routine to apply an immediate offset by doing a sudden step if
    possible. (Intended for use after an initial estimate of offset has
@@ -158,7 +159,7 @@ extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cook
 
 /* Perform the combination of modifying the frequency and applying
    a slew, in one easy step */
-extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
+extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset, double corr_rate);
 
 /* Routine to read the system precision as a log to base 2 value. */
 extern int LCL_GetSysPrecisionAsLog(void);
index a473d16f217e2eb3a4db4515ad6c07dd6711e7ed..ce92f1c733bd1d4804f9af88fea10e5dd76d84fa 100644 (file)
--- a/localp.h
+++ b/localp.h
@@ -41,8 +41,9 @@ typedef double (*lcl_ReadFrequencyDriver)(void);
 typedef double (*lcl_SetFrequencyDriver)(double freq_ppm);
 
 /* System driver to accrue an offset. A positive argument means slew
-   the clock forwards. */
-typedef void (*lcl_AccrueOffsetDriver)(double offset);
+   the clock forwards.  The suggested correction rate of time to correct the
+   offset is given in 'corr_rate'. */
+typedef void (*lcl_AccrueOffsetDriver)(double offset, double corr_rate);
 
 /* System driver to apply a step offset. A positive argument means step
    the clock forwards. */
index 6181002dae0dea9cd827834e8a4a3d3c566a69db..c2c316e017154338bb22806dc52f80cfb21b2a23 100644 (file)
@@ -541,6 +541,7 @@ REF_SetReference(int stratum,
                  IPAddr *ref_ip,
                  struct timeval *ref_time,
                  double offset,
+                 double offset_sd,
                  double frequency,
                  double skew,
                  double root_delay,
@@ -556,6 +557,7 @@ REF_SetReference(int stratum,
   double abs_freq_ppm;
   double update_interval;
   double elapsed;
+  double correction_rate;
   struct timeval now;
 
   assert(initialised);
@@ -611,6 +613,20 @@ REF_SetReference(int stratum,
   }
   last_ref_update = now;
 
+  /* We want to correct the offset quickly, but we also want to keep the
+     frequency error caused by the correction itself low.
+
+     Define correction rate as the area of the region bounded by the graph of
+     offset corrected in time. Set the rate so that the time needed to correct
+     an offset equal to the current sourcestats stddev will be equal to the
+     update interval (assuming linear adjustment). The offset and the
+     time needed to make the correction are inversely proportional.
+
+     This is only a suggestion and it's up to the system driver how the
+     adjustment will be executed. */
+
+  correction_rate = 0.5 * offset_sd * update_interval;
+
   /* Eliminate updates that are based on totally unreliable frequency
      information */
 
@@ -645,7 +661,7 @@ REF_SetReference(int stratum,
     our_residual_freq = new_freq - our_frequency;
 
     maybe_log_offset(our_offset);
-    LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset);
+    LCL_AccumulateFrequencyAndOffset(our_frequency, our_offset, correction_rate);
     
   } else {
 
@@ -653,7 +669,7 @@ REF_SetReference(int stratum,
     LOG(LOGS_INFO, LOGF_Reference, "Skew %f too large to track, offset=%f", skew, our_offset);
 #endif
     maybe_log_offset(our_offset);
-    LCL_AccumulateOffset(our_offset);
+    LCL_AccumulateOffset(our_offset, correction_rate);
 
     our_residual_freq = frequency;
   }
@@ -714,7 +730,7 @@ REF_SetManualReference
   our_residual_freq = 0.0;
 
   maybe_log_offset(offset);
-  LCL_AccumulateFrequencyAndOffset(frequency, offset);
+  LCL_AccumulateFrequencyAndOffset(frequency, offset, 0.0);
   maybe_make_step();
 
   abs_freq_ppm = LCL_ReadAbsoluteFrequency();
index 2b66f6ab734abd8266573572aacf01466db50e53..2d6de9f276f5101dff07cb2bb35f0212a6bd4ca0 100644 (file)
@@ -109,6 +109,7 @@ extern void REF_SetReference
  IPAddr *ref_ip,
  struct timeval *ref_time,
  double offset,
+ double offset_sd,
  double frequency,
  double skew,
  double root_delay,
index 3ee8b66f8e9c5befa3cad154c77689268464e435..aa172e14d3c90e1b272db9b5bf34c5425df0516a 100644 (file)
@@ -664,7 +664,7 @@ handle_initial_trim(void)
     sys_error_now = rtc_error_now - coef_seconds_fast;
           
     LOG(LOGS_INFO, LOGF_RtcLinux, "System trim from RTC = %f", sys_error_now);
-    LCL_AccumulateOffset(sys_error_now);
+    LCL_AccumulateOffset(sys_error_now, 0.0);
   } else {
     LOG(LOGS_WARN, LOGF_RtcLinux, "No valid file coefficients, cannot trim system time");
   }
index 6ebd62040f524a109941d151f9af44e2747e2847..bfe7e3c2b72cc58e9533693164ca3c6d2c4a79bd 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -857,6 +857,7 @@ SRC_SelectSource(uint32_t match_refid)
                            sources[selected_source_index]->ip_addr,
                            &ref_time,
                            src_offset,
+                           src_offset_sd,
                            src_frequency,
                            src_skew,
                            src_root_delay,
index ffc917ed52a8e2e20a9ea7299fc0abb75ff2d371..c0512bdb11573c9ece8bcda6597b34bd0ffd4f0c 100644 (file)
@@ -592,7 +592,7 @@ abort_slew(void)
    time) */
 
 static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
 {
   /* Add the new offset to the register */
   offset_register += offset;
index 863f572c8b292252d0445b71e4cd34592108d778..c9a29b33ea7f037ef07597228e6fe3182bd14264 100644 (file)
@@ -199,7 +199,7 @@ stop_adjust(void)
    slew backwards */
 
 static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
 {
   stop_adjust();
   offset_register += offset;
index db40091eb240eab5788c3b7813fa3b3226a888aa..54d2bde84b347daf8d5271c996b3e1cf597a54e4 100644 (file)
@@ -212,7 +212,7 @@ stop_adjust(void)
    slew backwards */
 
 static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
 {
   stop_adjust();
   offset_register += offset;
index 5178c5aabf7a9031cb6cbd1013c7bab3f3567dc2..3ac67a0725e6389a6ab03c6b6cede87f9ad05fc0 100644 (file)
@@ -216,7 +216,7 @@ stop_adjust(void)
    slew backwards */
 
 static void
-accrue_offset(double offset)
+accrue_offset(double offset, double corr_rate)
 {
   stop_adjust();
   offset_register += offset;