]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_netbsd: use timex driver
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 15 Sep 2015 13:44:34 +0000 (15:44 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 17 Sep 2015 13:52:49 +0000 (15:52 +0200)
Remove the driver functions based on adjtime() and switch to the new
timex driver, which is based on ntp_adjtime(). This allows chronyd to
control the kernel frequency, adjust the offset with sub-microsecond
accuracy, and set the kernel leap and sync status. A drawback is that
the maximum slew rate is now limited by the 500 ppm maximum frequency
offset, while adjtime() on NetBSD slewed by up to 5000 ppm.

configure
sys_netbsd.c

index c75f6c92a8157c068d998e6a54868d7514016a4a..03b9f130463908e96f3bf9ee1d0530d8fda6cb81 100755 (executable)
--- a/configure
+++ b/configure
@@ -419,8 +419,7 @@ case $SYSTEM in
         echo "Configuring for $SYSTEM (using SunOS driver)"
     ;;
     NetBSD-* )
-        EXTRA_OBJECTS="sys_netbsd.o"
-        EXTRA_LIBS="-lkvm"
+        EXTRA_OBJECTS="sys_generic.o sys_netbsd.o sys_timex.o"
         try_clockctl=1
         add_def NETBSD
         echo "Configuring for $SYSTEM"
index 2d736291b96fbfb18e54b2f50273b959f9d14d2a..7abc562333513b23a02eb3e8f811170977111bc0 100644 (file)
 
 #include "config.h"
 
-#ifdef NETBSD
-
-#include <kvm.h>
-#include <nlist.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <sys/time.h>
-
-#include <stdio.h>
-#include <signal.h>
+#include "sysincl.h"
 
 #include "sys_netbsd.h"
-#include "localp.h"
+#include "sys_timex.h"
 #include "logging.h"
-#include "util.h"
-
-/* ================================================== */
-
-/* This register contains the number of seconds by which the local
-   clock was estimated to be fast of reference time at the epoch when
-   gettimeofday() returned T0 */
-
-static double offset_register;
-
-/* This register contains the epoch to which the offset is referenced */
-
-static struct timeval T0;
-
-/* This register contains the current estimate of the system
-   frequency, in absolute (NOT ppm) */
-
-static double current_freq;
-
-/* This register contains the number of seconds of adjustment that
-   were passed to adjtime last time it was called. */
-
-static double adjustment_requested;
-
-/* Kernel parameters to calculate adjtime error. */
-
-static int kern_tickadj;
-static long kern_bigadj;
-
-/* ================================================== */
-
-static void
-clock_initialise(void)
-{
-  struct timeval newadj, oldadj;
-
-  offset_register = 0.0;
-  adjustment_requested = 0.0;
-  current_freq = 0.0;
-
-  if (gettimeofday(&T0, NULL) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
-  }
-
-  newadj.tv_sec = 0;
-  newadj.tv_usec = 0;
-
-  if (adjtime(&newadj, &oldadj) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
-  }
-
-}
-
-/* ================================================== */
-
-static void
-clock_finalise(void)
-{
-  /* Nothing to do yet */
-
-}
-
-/* ================================================== */
-
-static void
-start_adjust(void)
-{
-  struct timeval newadj, oldadj;
-  struct timeval T1;
-  double elapsed, accrued_error;
-  double adjust_required;
-  struct timeval exact_newadj;
-  long delta, tickdelta;
-  double rounding_error;
-  double old_adjust_remaining;
-
-  /* Determine the amount of error built up since the last adjustment */
-  if (gettimeofday(&T1, NULL) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
-  }
-
-  UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
-  accrued_error = elapsed * current_freq;
-  
-  adjust_required = - (accrued_error + offset_register);
-
-  UTI_DoubleToTimeval(adjust_required, &exact_newadj);
-
-  /* At this point, we need to round the required adjustment the
-     same way the kernel does. */
-
-  delta = exact_newadj.tv_sec * 1000000 + exact_newadj.tv_usec;
-  if (delta > kern_bigadj || delta < -kern_bigadj)
-    tickdelta = 10 * kern_tickadj;
-  else
-    tickdelta = kern_tickadj;
-  if (delta % tickdelta)
-       delta = delta / tickdelta * tickdelta;
-  newadj.tv_sec = 0;
-  newadj.tv_usec = delta;
-  UTI_NormaliseTimeval(&newadj);
-
-  /* Add rounding error back onto offset register. */
-  UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj);
-
-  if (adjtime(&newadj, &oldadj) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
-  }
-
-  UTI_TimevalToDouble(&oldadj, &old_adjust_remaining);
-
-  offset_register = rounding_error - old_adjust_remaining;
-
-  T0 = T1;
-  UTI_TimevalToDouble(&newadj, &adjustment_requested);
-
-}
-
-/* ================================================== */
-
-static void
-stop_adjust(void)
-{
-  struct timeval T1;
-  struct timeval zeroadj, remadj;
-  double adjustment_remaining, adjustment_achieved;
-  double elapsed, elapsed_plus_adjust;
-
-  zeroadj.tv_sec = 0;
-  zeroadj.tv_usec = 0;
-
-  if (adjtime(&zeroadj, &remadj) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
-  }
-
-  if (gettimeofday(&T1, NULL) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
-  }
-  
-  UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0);
-  UTI_TimevalToDouble(&remadj, &adjustment_remaining);
-
-  adjustment_achieved = adjustment_requested - adjustment_remaining;
-  elapsed_plus_adjust = elapsed - adjustment_achieved;
-
-  offset_register += current_freq * elapsed_plus_adjust - adjustment_remaining;
-
-  adjustment_requested = 0.0;
-  T0 = T1;
-
-}
-
-/* ================================================== */
-
-/* Positive offset means system clock is fast of true time, therefore
-   slew backwards */
-
-static void
-accrue_offset(double offset, double corr_rate)
-{
-  stop_adjust();
-  offset_register += offset;
-  start_adjust();
-
-}
-
-/* ================================================== */
-
-/* Positive offset means system clock is fast of true time, therefore
-   step backwards */
-
-static int
-apply_step_offset(double offset)
-{
-  struct timeval old_time, new_time, T1;
-  
-  stop_adjust();
-
-  if (gettimeofday(&old_time, NULL) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed");
-  }
-
-  UTI_AddDoubleToTimeval(&old_time, -offset, &new_time);
-
-  if (settimeofday(&new_time, NULL) < 0) {
-    DEBUG_LOG(LOGF_SysNetBSD, "settimeofday() failed");
-    return 0;
-  }
-
-  UTI_AddDoubleToTimeval(&T0, offset, &T1);
-  T0 = T1;
-
-  start_adjust();
-
-  return 1;
-}
-
-/* ================================================== */
-
-static double
-set_frequency(double new_freq_ppm)
-{
-  stop_adjust();
-  current_freq = new_freq_ppm * 1.0e-6;
-  start_adjust();
-
-  return current_freq * 1.0e6;
-}
-
-/* ================================================== */
-
-static double
-read_frequency(void)
-{
-  return current_freq * 1.0e6;
-}
-
-/* ================================================== */
-
-static void
-get_offset_correction(struct timeval *raw,
-                      double *corr, double *err)
-{
-  stop_adjust();
-  *corr = -offset_register;
-  start_adjust();
-  if (err)
-    *err = 0.0;
-}
 
 /* ================================================== */
 
 void
 SYS_NetBSD_Initialise(void)
 {
-  static struct nlist nl[] = {
-    {"_tickadj"},
-    {"_bigadj"},
-    {NULL}
-  };
-
-  kvm_t *kt;
-
-  kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
-  if (!kt) {
-    LOG_FATAL(LOGF_SysNetBSD, "Cannot open kvm");
-  }
-
-  if (kvm_nlist(kt, nl) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "Cannot read kernel symbols");
-  }
-
-  if (kvm_read(kt, nl[0].n_value, (char *)(&kern_tickadj), sizeof(int)) < 0) {
-    LOG_FATAL(LOGF_SysNetBSD, "Cannot read from _tickadj");
-  }
-
-  if (kvm_read(kt, nl[1].n_value, (char *)(&kern_bigadj), sizeof(long)) < 0) {
-    /* kernel doesn't have the symbol, use one second instead */
-    kern_bigadj = 1000000;
-  }
-
-  kvm_close(kt);
-
-  clock_initialise();
-
-  lcl_RegisterSystemDrivers(read_frequency, set_frequency, 
-                            accrue_offset, apply_step_offset,
-                            get_offset_correction,
-                            NULL /* set_leap */,
-                            NULL /* set_sync_status */);
-
+  SYS_Timex_Initialise();
 }
 
 /* ================================================== */
@@ -319,7 +46,7 @@ SYS_NetBSD_Initialise(void)
 void
 SYS_NetBSD_Finalise(void)
 {
-  clock_finalise();
+  SYS_Timex_Finalise();
 }
 
 /* ================================================== */
@@ -348,5 +75,3 @@ SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
   close(fd);
 }
 #endif
-
-#endif /* NETBSD */