]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
hwclock: add parameters for minimum/maximum number of samples
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 8 Aug 2018 11:22:30 +0000 (13:22 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 9 Aug 2018 12:52:08 +0000 (14:52 +0200)
Allocate the arrays which hold the samples dynamically and limit the
number of dropped samples to not fall below the minimum.

hwclock.c
hwclock.h
ntp_io_linux.c
refclock_phc.c
test/unit/hwclock.c

index 007d19d718330a623a84f26becbdc4edb761306a..6122ab2d14ad02844b607c57b5044e12cdd6b402 100644 (file)
--- a/hwclock.c
+++ b/hwclock.c
@@ -36,8 +36,9 @@
 #include "regress.h"
 #include "util.h"
 
-/* Maximum number of samples per clock */
-#define MAX_SAMPLES 16
+/* Minimum and maximum number of samples per clock */
+#define MIN_SAMPLES 2
+#define MAX_SAMPLES 64
 
 /* Maximum acceptable frequency offset of the clock */
 #define MAX_FREQ_OFFSET (2.0 / 3.0)
@@ -49,10 +50,12 @@ struct HCL_Instance_Record {
 
   /* Samples stored as intervals (uncorrected for frequency error)
      relative to local_ref and hw_ref */
-  double x_data[MAX_SAMPLES];
-  double y_data[MAX_SAMPLES];
+  double *x_data;
+  double *y_data;
 
-  /* Number of samples */
+  /* Minimum, maximum and current number of samples */
+  int min_samples;
+  int max_samples;
   int n_samples;
 
   /* Maximum error of the last sample */
@@ -89,13 +92,21 @@ handle_slew(struct timespec *raw, struct timespec *cooked, double dfreq,
 /* ================================================== */
 
 HCL_Instance
-HCL_CreateInstance(double min_separation)
+HCL_CreateInstance(int min_samples, int max_samples, double min_separation)
 {
   HCL_Instance clock;
 
+  min_samples = CLAMP(MIN_SAMPLES, min_samples, MAX_SAMPLES);
+  max_samples = CLAMP(MIN_SAMPLES, max_samples, MAX_SAMPLES);
+  max_samples = MAX(min_samples, max_samples);
+
   clock = MallocNew(struct HCL_Instance_Record);
-  clock->x_data[MAX_SAMPLES - 1] = 0.0;
-  clock->y_data[MAX_SAMPLES - 1] = 0.0;
+  clock->x_data = MallocArray(double, max_samples);
+  clock->y_data = MallocArray(double, max_samples);
+  clock->x_data[max_samples - 1] = 0.0;
+  clock->y_data[max_samples - 1] = 0.0;
+  clock->min_samples = min_samples;
+  clock->max_samples = max_samples;
   clock->n_samples = 0;
   clock->valid_coefs = 0;
   clock->min_separation = min_separation;
@@ -110,6 +121,8 @@ HCL_CreateInstance(double min_separation)
 void HCL_DestroyInstance(HCL_Instance clock)
 {
   LCL_RemoveParameterChangeHandler(handle_slew, clock);
+  Free(clock->y_data);
+  Free(clock->x_data);
   Free(clock);
 }
 
@@ -138,7 +151,7 @@ HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts,
 
   /* Shift old samples */
   if (clock->n_samples) {
-    if (clock->n_samples >= MAX_SAMPLES)
+    if (clock->n_samples >= clock->max_samples)
       clock->n_samples--;
 
     hw_delta = UTI_DiffTimespecsToDouble(hw_ts, &clock->hw_ref);
@@ -149,7 +162,7 @@ HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts,
       DEBUG_LOG("HW clock reset interval=%f", local_delta);
     }
 
-    for (i = MAX_SAMPLES - clock->n_samples; i < MAX_SAMPLES; i++) {
+    for (i = clock->max_samples - clock->n_samples; i < clock->max_samples; i++) {
       clock->y_data[i - 1] = clock->y_data[i] - hw_delta;
       clock->x_data[i - 1] = clock->x_data[i] - local_delta;
     }
@@ -162,8 +175,8 @@ HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts,
 
   /* Get new coefficients */
   clock->valid_coefs =
-    RGR_FindBestRobustRegression(clock->x_data + MAX_SAMPLES - clock->n_samples,
-                                 clock->y_data + MAX_SAMPLES - clock->n_samples,
+    RGR_FindBestRobustRegression(clock->x_data + clock->max_samples - clock->n_samples,
+                                 clock->y_data + clock->max_samples - clock->n_samples,
                                  clock->n_samples, 1.0e-10, &clock->offset, &raw_freq,
                                  &n_runs, &best_start);
 
@@ -175,7 +188,8 @@ HCL_AccumulateSample(HCL_Instance clock, struct timespec *hw_ts,
   clock->frequency = raw_freq / local_freq;
 
   /* Drop unneeded samples */
-  clock->n_samples -= best_start;
+  if (clock->n_samples > clock->min_samples)
+    clock->n_samples -= MIN(best_start, clock->n_samples - clock->min_samples);
 
   /* If the fit doesn't cross the error interval of the last sample,
      or the frequency is not sane, drop all samples and start again */
index f80d09a55d5da9a7ebc3d4e81bc4bf00ffab8eaa..3005bae39744ba7377475263456edd124462016c 100644 (file)
--- a/hwclock.h
+++ b/hwclock.h
@@ -29,7 +29,8 @@
 typedef struct HCL_Instance_Record *HCL_Instance;
 
 /* Create a new HW clock instance */
-extern HCL_Instance HCL_CreateInstance(double min_separation);
+extern HCL_Instance HCL_CreateInstance(int min_samples, int max_samples,
+                                       double min_separation);
 
 /* Destroy a HW clock instance */
 extern void HCL_DestroyInstance(HCL_Instance clock);
index a1f2fb7af6727a1f1ff4000de0f99d1681428307..ad7b6eebf8e546efa700ba0484911ff3e36fab7e 100644 (file)
@@ -236,7 +236,8 @@ add_interface(CNF_HwTsInterface *conf_iface)
   iface->tx_comp = conf_iface->tx_comp;
   iface->rx_comp = conf_iface->rx_comp;
 
-  iface->clock = HCL_CreateInstance(UTI_Log2ToDouble(MAX(conf_iface->minpoll, MIN_PHC_POLL)));
+  iface->clock = HCL_CreateInstance(0, 16, UTI_Log2ToDouble(MAX(conf_iface->minpoll,
+                                                                MIN_PHC_POLL)));
 
   LOG(LOGS_INFO, "Enabled HW timestamping %son %s",
       ts_config.rx_filter == HWTSTAMP_FILTER_NONE ? "(TX only) " : "", iface->name);
index 6aa5eddf1211cacb3a7f444b7ac393d2337c3d4f..03450dbd35faa7e2e51eafbf2dce36b62b1a7b3b 100644 (file)
@@ -80,7 +80,7 @@ static int phc_initialise(RCL_Instance instance)
     s = RCL_GetDriverOption(instance, "channel");
     phc->channel = s ? atoi(s) : 0;
     rising_edge = RCL_GetDriverOption(instance, "clear") ? 0 : 1;
-    phc->clock = HCL_CreateInstance(UTI_Log2ToDouble(RCL_GetDriverPoll(instance)));
+    phc->clock = HCL_CreateInstance(0, 16, UTI_Log2ToDouble(RCL_GetDriverPoll(instance)));
 
     if (!SYS_Linux_SetPHCExtTimestamping(phc->fd, phc->pin, phc->channel,
                                          rising_edge, !rising_edge, 1))
index 1cbd31265e161fd35e5bdd2eb328c5bb95268dd5..e181750b78a7cf65f0382f6f8180d2f53fe8a3f6 100644 (file)
@@ -31,7 +31,7 @@ test_unit(void)
 
   LCL_Initialise();
 
-  clock = HCL_CreateInstance(1.0);
+  clock = HCL_CreateInstance(0, 16, 1.0);
 
   for (i = 0, count = 0, sum = 0.0; i < 2000; i++) {
     UTI_ZeroTimespec(&start_hw_ts);