]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_linux: add support for PTP_SYS_OFFSET_EXTENDED ioctl
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 27 Nov 2018 12:46:37 +0000 (13:46 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 27 Nov 2018 13:56:17 +0000 (14:56 +0100)
A new ioctl will probably be added in Linux 4.21. It should enable a
significantly more accurate measurement of the offset between PHC and
system clock.

sys_linux.c

index bd94c77978f197acb69f0668ba1cad5b8cdd9bfe..7688d513425239ad3024f5db3164b6b8aed902a3 100644 (file)
@@ -544,6 +544,9 @@ SYS_Linux_EnableSystemCallFilter(int level)
 #ifdef PTP_PIN_SETFUNC
     PTP_PIN_SETFUNC,
 #endif
+#ifdef PTP_SYS_OFFSET_EXTENDED
+    PTP_SYS_OFFSET_EXTENDED,
+#endif
 #ifdef PTP_SYS_OFFSET_PRECISE
     PTP_SYS_OFFSET_PRECISE,
 #endif
@@ -778,6 +781,42 @@ get_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
 
 /* ================================================== */
 
+static int
+get_extended_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
+                        struct timespec *sys_ts, double *err)
+{
+#ifdef PTP_SYS_OFFSET_EXTENDED
+  struct timespec ts[PHC_READINGS][3];
+  struct ptp_sys_offset_extended sys_off;
+  int i;
+
+  /* Silence valgrind */
+  memset(&sys_off, 0, sizeof (sys_off));
+
+  sys_off.n_samples = PHC_READINGS;
+
+  if (ioctl(phc_fd, PTP_SYS_OFFSET_EXTENDED, &sys_off)) {
+    DEBUG_LOG("ioctl(%s) failed : %s", "PTP_SYS_OFFSET_EXTENDED", strerror(errno));
+    return 0;
+  }
+
+  for (i = 0; i < PHC_READINGS; i++) {
+    ts[i][0].tv_sec = sys_off.ts[i][0].sec;
+    ts[i][0].tv_nsec = sys_off.ts[i][0].nsec;
+    ts[i][1].tv_sec = sys_off.ts[i][1].sec;
+    ts[i][1].tv_nsec = sys_off.ts[i][1].nsec;
+    ts[i][2].tv_sec = sys_off.ts[i][2].sec;
+    ts[i][2].tv_nsec = sys_off.ts[i][2].nsec;
+  }
+
+  return process_phc_readings(ts, PHC_READINGS, precision, phc_ts, sys_ts, err);
+#else
+  return 0;
+#endif
+}
+
+/* ================================================== */
+
 static int
 get_precise_phc_sample(int phc_fd, double precision, struct timespec *phc_ts,
                       struct timespec *sys_ts, double *err)
@@ -849,6 +888,10 @@ SYS_Linux_GetPHCSample(int fd, int nocrossts, double precision, int *reading_mod
       get_precise_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
     *reading_mode = 2;
     return 1;
+  } else if ((*reading_mode == 3 || !*reading_mode) &&
+      get_extended_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
+    *reading_mode = 3;
+    return 1;
   } else if ((*reading_mode == 1 || !*reading_mode) &&
       get_phc_sample(fd, precision, phc_ts, sys_ts, err)) {
     *reading_mode = 1;