]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_linux: use timex driver
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 15 Sep 2015 13:24:28 +0000 (15:24 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 17 Sep 2015 13:52:49 +0000 (15:52 +0200)
Remove functions that are included in the new timex driver. Keep only
functions that have extended functionality, i.e. read and set the
frequency using the timex tick field and apply step offset with
ADJ_SETOFFSET.

Merge the code from wrap_adjtimex.c that is still needed with
sys_linux.c and remove the file.

configure
sys_linux.c
wrap_adjtimex.c [deleted file]
wrap_adjtimex.h [deleted file]

index abdbf2dd40ddc17ddccb267f964e2791304ccf4f..c75f6c92a8157c068d998e6a54868d7514016a4a 100755 (executable)
--- a/configure
+++ b/configure
@@ -394,7 +394,7 @@ case $SYSTEM in
     esac
     ;;
     Linux* )
-        EXTRA_OBJECTS="sys_generic.o sys_linux.o wrap_adjtimex.o"
+        EXTRA_OBJECTS="sys_generic.o sys_linux.o sys_timex.o"
         [ $try_libcap != "0" ] && try_libcap=1
         try_rtc=1
         [ $try_seccomp != "0" ] && try_seccomp=1
index 285dee2bb32ba3f923ada042aca6c5500a7e3e63..f5543319ad847950492c64d15515de2bc95cacc2 100644 (file)
 #endif
 #endif
 
-#include "sys_generic.h"
 #include "sys_linux.h"
+#include "sys_timex.h"
 #include "conf.h"
 #include "logging.h"
-#include "wrap_adjtimex.h"
 
-/* The threshold for adjtimex maxerror when the kernel sets the UNSYNC flag */
-#define UNSYNC_MAXERROR 16.0
+/* Frequency scale to convert from ppm to the timex freq */
+#define FREQ_SCALE (double)(1 << 16)
+
+/* Definitions used if missed in the system headers */
+#ifndef ADJ_SETOFFSET
+#define ADJ_SETOFFSET           0x0100  /* add 'time' to current time */
+#endif
+#ifndef ADJ_NANO
+#define ADJ_NANO                0x2000  /* select nanosecond resolution */
+#endif
 
 /* This is the uncompensated system tick value */
 static int nominal_tick;
@@ -113,11 +120,19 @@ our_round(double x)
 static int
 apply_step_offset(double offset)
 {
-  if (TMX_ApplyStepOffset(-offset) < 0) {
-    DEBUG_LOG(LOGF_SysLinux, "adjtimex() failed");
-    return 0;
+  struct timex txc;
+
+  txc.modes = ADJ_SETOFFSET | ADJ_NANO;
+  txc.time.tv_sec = -offset;
+  txc.time.tv_usec = 1.0e9 * (-offset - txc.time.tv_sec);
+  if (txc.time.tv_usec < 0) {
+    txc.time.tv_sec--;
+    txc.time.tv_usec += 1000000000;
   }
 
+  if (SYS_Timex_Adjust(&txc, 1) < 0)
+    return 0;
+
   return 1;
 }
 
@@ -131,6 +146,7 @@ apply_step_offset(double offset)
 static double
 set_frequency(double freq_ppm)
 {
+  struct timex txc;
   long required_tick;
   double required_freq;
   int required_delta_tick;
@@ -154,14 +170,15 @@ set_frequency(double freq_ppm)
   required_freq = -(freq_ppm - dhz * required_delta_tick);
   required_tick = nominal_tick - required_delta_tick;
 
-  if (TMX_SetFrequency(&required_freq, required_tick) < 0) {
-    LOG_FATAL(LOGF_SysLinux, "adjtimex failed for set_frequency, freq_ppm=%10.4e required_freq=%10.4e required_tick=%ld",
-        freq_ppm, required_freq, required_tick);
-  }
+  txc.modes = ADJ_TICK | ADJ_FREQUENCY;
+  txc.freq = required_freq * FREQ_SCALE;
+  txc.tick = required_tick;
+
+  SYS_Timex_Adjust(&txc, 0);
 
   current_delta_tick = required_delta_tick;
 
-  return dhz * current_delta_tick - required_freq;
+  return dhz * current_delta_tick - txc.freq / FREQ_SCALE;
 }
 
 /* ================================================== */
@@ -170,60 +187,15 @@ set_frequency(double freq_ppm)
 static double
 read_frequency(void)
 {
-  long tick;
-  double freq;
-
-  if (TMX_GetFrequency(&freq, &tick) < 0) {
-    LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
-  }
-
-  current_delta_tick = nominal_tick - tick;
-  
-  return dhz * current_delta_tick - freq;
-}
-
-/* ================================================== */
-
-static void
-set_leap(int leap)
-{
-  int applied;
-
-  applied = 0;
-  if (!leap && TMX_GetLeapApplied(&applied) < 0) {
-    LOG_FATAL(LOGF_SysLinux, "adjtimex() failed in set_leap");
-  }
-
-  if (TMX_SetLeap(leap) < 0) {
-    LOG_FATAL(LOGF_SysLinux, "adjtimex() failed in set_leap");
-  }
+  struct timex txc;
 
-  LOG(LOGS_INFO, LOGF_SysLinux, "System clock status %s leap second",
-     leap ? (leap > 0 ? "set to insert" : "set to delete") :
-            (applied ? "reset after" : "set to not insert/delete"));
-}
+  txc.modes = 0;
 
-/* ================================================== */
-
-static void
-set_sync_status(int synchronised, double est_error, double max_error)
-{
-  if (synchronised) {
-    if (est_error > UNSYNC_MAXERROR)
-      est_error = UNSYNC_MAXERROR;
-    if (max_error >= UNSYNC_MAXERROR) {
-      max_error = UNSYNC_MAXERROR;
-      synchronised = 0;
-    }
-  } else {
-    est_error = max_error = UNSYNC_MAXERROR;
-  }
+  SYS_Timex_Adjust(&txc, 0);
 
-  /* Clear the UNSYNC flag only if rtcsync is enabled */
-  if (!CNF_GetRtcSync())
-    synchronised = 0;
+  current_delta_tick = nominal_tick - txc.tick;
 
-  TMX_SetSync(synchronised, est_error, max_error);
+  return dhz * current_delta_tick - txc.freq / FREQ_SCALE;
 }
 
 /* ================================================== */
@@ -234,10 +206,16 @@ set_sync_status(int synchronised, double est_error, double max_error)
  * a +/- 10% movement of tick away from the nominal value 1e6/USER_HZ. */
 
 static int
-guess_hz(int tick)
+guess_hz(void)
 {
-  int i, tick_lo, tick_hi, ihz;
+  struct timex txc;
+  int i, tick, tick_lo, tick_hi, ihz;
   double tick_nominal;
+
+  txc.modes = 0;
+  SYS_Timex_Adjust(&txc, 0);
+  tick = txc.tick;
+
   /* Pick off the hz=100 case first */
   if (tick >= 9000 && tick <= 11000) {
     return 100;
@@ -255,6 +233,8 @@ guess_hz(int tick)
   }
 
   /* oh dear.  doomed. */
+  LOG_FATAL(LOGF_SysLinux, "Can't determine hz from tick %d", tick);
+
   return 0;
 }
 
@@ -296,21 +276,12 @@ static void
 get_version_specific_details(void)
 {
   int major, minor, patch;
-  long tick;
-  double freq;
   struct utsname uts;
   
   hz = get_hz();
 
-  if (!hz) {
-    if (TMX_GetFrequency(&freq, &tick) < 0)
-      LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
-
-    hz = guess_hz(tick);
-
-    if (!hz)
-      LOG_FATAL(LOGF_SysLinux, "Can't determine hz from tick %ld", tick);
-  }
+  if (!hz)
+    hz = guess_hz();
 
   dhz = (double) hz;
   nominal_tick = (1000000L + (hz/2))/hz; /* Mirror declaration in kernel */
@@ -353,6 +324,48 @@ get_version_specific_details(void)
       hz, nominal_tick, max_tick_bias);
 }
 
+/* ================================================== */
+
+static void
+reset_adjtime_offset(void)
+{
+  struct timex txc;
+
+  /* Reset adjtime() offset */
+  txc.modes = ADJ_OFFSET_SINGLESHOT;
+  txc.offset = 0;
+
+  SYS_Timex_Adjust(&txc, 0);
+}
+
+/* ================================================== */
+
+static int
+test_step_offset(void)
+{
+  struct timex txc;
+
+  /* Zero maxerror and check it's reset to a maximum after ADJ_SETOFFSET.
+     This seems to be the only way how to verify that the kernel really
+     supports the ADJ_SETOFFSET mode as it doesn't return an error on unknown
+     mode. */
+
+  txc.modes = MOD_MAXERROR;
+  txc.maxerror = 0;
+
+  if (SYS_Timex_Adjust(&txc, 1) < 0 || txc.maxerror != 0)
+    return 0;
+
+  txc.modes = ADJ_SETOFFSET | ADJ_NANO;
+  txc.time.tv_sec = 0;
+  txc.time.tv_usec = 0;
+
+  if (SYS_Timex_Adjust(&txc, 1) < 0 || txc.maxerror < 100000)
+    return 0;
+
+  return 1;
+}
+
 /* ================================================== */
 /* Initialisation code for this module */
 
@@ -361,20 +374,17 @@ SYS_Linux_Initialise(void)
 {
   get_version_specific_details();
 
-  if (TMX_ResetOffset() < 0) {
-    LOG_FATAL(LOGF_SysLinux, "adjtimex() failed");
-  }
+  reset_adjtime_offset();
 
-  if (have_setoffset && TMX_TestStepOffset() < 0) {
+  if (have_setoffset && !test_step_offset()) {
     LOG(LOGS_INFO, LOGF_SysLinux, "adjtimex() doesn't support ADJ_SETOFFSET");
     have_setoffset = 0;
   }
 
-  SYS_Generic_CompleteFreqDriver(1.0e6 * max_tick_bias / nominal_tick,
-                                 1.0 / tick_update_hz,
-                                 read_frequency, set_frequency,
-                                 have_setoffset ? apply_step_offset : NULL,
-                                 set_leap, set_sync_status);
+  SYS_Timex_InitialiseWithFunctions(1.0e6 * max_tick_bias / nominal_tick,
+                                    1.0 / tick_update_hz,
+                                    read_frequency, set_frequency,
+                                    have_setoffset ? apply_step_offset : NULL);
 }
 
 /* ================================================== */
@@ -383,7 +393,7 @@ SYS_Linux_Initialise(void)
 void
 SYS_Linux_Finalise(void)
 {
-  SYS_Generic_Finalise();
+  SYS_Timex_Finalise();
 }
 
 /* ================================================== */
diff --git a/wrap_adjtimex.c b/wrap_adjtimex.c
deleted file mode 100644 (file)
index b543718..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
-  chronyd/chronyc - Programs for keeping computer clocks accurate.
-
- **********************************************************************
- * Copyright (C) Richard P. Curnow  1997-2002
- * Copyright (C) Miroslav Lichvar  2011-2012, 2014
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- * 
- **********************************************************************
-
-  =======================================================================
-
-  This is a wrapper around the Linux adjtimex system call.
-
-  */
-
-#include "config.h"
-
-#include "wrap_adjtimex.h"
-
-#include <sys/timex.h>
-
-/* Definitions used if missing in the system headers */
-#ifndef ADJ_TAI
-#define ADJ_TAI                 0x0080  /* set TAI offset */
-#endif
-#ifndef ADJ_SETOFFSET
-#define ADJ_SETOFFSET           0x0100  /* add 'time' to current time */
-#endif
-#ifndef ADJ_NANO
-#define ADJ_NANO                0x2000  /* select nanosecond resolution */
-#endif
-#ifndef ADJ_OFFSET_SS_READ
-#define ADJ_OFFSET_SS_READ      0xa001  /* read-only adjtime */
-#endif
-
-/* Frequency offset scale (shift) */
-#define SHIFT_USEC 16
-
-static int status = 0;
-
-int
-TMX_ResetOffset(void)
-{
-  struct timex txc;
-
-  /* Reset adjtime() offset */
-  txc.modes = ADJ_OFFSET_SINGLESHOT;
-  txc.offset = 0;
-  if (adjtimex(&txc) < 0)
-    return -1;
-
-  /* Reset PLL offset */
-  txc.modes = ADJ_OFFSET | ADJ_STATUS;
-  txc.status = STA_PLL;
-  txc.offset = 0;
-  if (adjtimex(&txc) < 0)
-    return -1;
-
-  /* Set status back */
-  txc.modes = ADJ_STATUS;
-  txc.status = status;
-  if (adjtimex(&txc) < 0)
-    return -1;
-
-  return 0;
-}
-
-int
-TMX_SetFrequency(double *freq, long tick)
-{
-  struct timex txc;
-  
-  txc.modes = ADJ_TICK | ADJ_FREQUENCY;
-
-  txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
-  *freq = txc.freq / (double)(1 << SHIFT_USEC);
-  txc.tick = tick;
-
-  return adjtimex(&txc);
-}
-
-int
-TMX_GetFrequency(double *freq, long *tick)
-{
-  struct timex txc;
-  int result;
-  txc.modes = 0; /* pure read */
-  result = adjtimex(&txc);
-  *freq = txc.freq / (double)(1 << SHIFT_USEC);
-  *tick = txc.tick;
-  return result;
-}
-
-int
-TMX_SetLeap(int leap)
-{
-  struct timex txc;
-
-  status &= ~(STA_INS | STA_DEL);
-
-  if (leap > 0) {
-    status |= STA_INS;
-  } else if (leap < 0) {
-    status |= STA_DEL;
-  }
-  
-  txc.modes = ADJ_STATUS;
-  txc.status = status;
-
-  return adjtimex(&txc);
-}
-
-int
-TMX_GetLeapApplied(int *applied)
-{
-  struct timex txc;
-  int state;
-
-  txc.modes = 0;
-  state = adjtimex(&txc);
-  if (state < 0)
-    return -1;
-
-  *applied = state == TIME_WAIT;
-
-  return 0;
-}
-
-int TMX_SetSync(int sync, double est_error, double max_error)
-{
-  struct timex txc;
-
-  if (sync) {
-    status &= ~STA_UNSYNC;
-  } else {
-    status |= STA_UNSYNC;
-  }
-
-  txc.modes = ADJ_STATUS | ADJ_ESTERROR | ADJ_MAXERROR;
-  txc.status = status;
-  txc.esterror = est_error * 1.0e6;
-  txc.maxerror = max_error * 1.0e6;
-
-  return adjtimex(&txc);
-}
-
-int
-TMX_TestStepOffset(void)
-{
-  struct timex txc;
-
-  /* Zero maxerror and check it's reset to a maximum after ADJ_SETOFFSET.
-     This seems to be the only way how to verify that the kernel really
-     supports the ADJ_SETOFFSET mode as it doesn't return an error on unknown
-     mode. */
-
-  txc.modes = ADJ_MAXERROR;
-  txc.maxerror = 0;
-  if (adjtimex(&txc) < 0 || txc.maxerror != 0)
-    return -1;
-
-  txc.modes = ADJ_SETOFFSET | ADJ_NANO;
-  txc.time.tv_sec = 0;
-  txc.time.tv_usec = 0;
-  if (adjtimex(&txc) < 0 || txc.maxerror < 100000)
-    return -1;
-
-  return 0;
-}
-
-int
-TMX_ApplyStepOffset(double offset)
-{
-  struct timex txc;
-
-  txc.modes = ADJ_SETOFFSET | ADJ_NANO;
-  txc.time.tv_sec = offset;
-  txc.time.tv_usec = 1.0e9 * (offset - txc.time.tv_sec);
-  if (txc.time.tv_usec < 0) {
-    txc.time.tv_sec--;
-    txc.time.tv_usec += 1000000000;
-  }
-
-  return adjtimex(&txc);
-}
diff --git a/wrap_adjtimex.h b/wrap_adjtimex.h
deleted file mode 100644 (file)
index 97d4164..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-  chronyd/chronyc - Programs for keeping computer clocks accurate.
-
- **********************************************************************
- * Copyright (C) Richard P. Curnow  1997-2002
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- * 
- **********************************************************************
-
-  =======================================================================
-
-  The header file for the adjtimex wrapper
-  */
-
-#ifndef GOT_WRAP_ADJTIMEX_H
-#define GOT_WRAP_ADJTIMEX_H
-
-int TMX_ResetOffset(void);
-int TMX_SetFrequency(double *freq, long tick);
-int TMX_GetFrequency(double *freq, long *tick);
-int TMX_SetLeap(int leap);
-int TMX_GetLeapApplied(int *applied);
-int TMX_SetSync(int sync, double est_error, double max_error);
-int TMX_TestStepOffset(void);
-int TMX_ApplyStepOffset(double offset);
-
-#endif  /* GOT_WRAP_ADJTIMEX_H */
-