예제 #1
0
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);

}
예제 #2
0
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;

}
예제 #3
0
static void
get_offset_correction(struct timespec *raw,
                      double *corr, double *err)
{
  struct timeval remadj;
  double adjustment_remaining;
#ifdef MACOSX
  struct timeval tv = {0, 0};

  if (PRV_AdjustTime(&tv, &remadj) < 0)
    LOG_FATAL("adjtime() failed");

  if (PRV_AdjustTime(&remadj, NULL) < 0)
    LOG_FATAL("adjtime() failed");
#else
  if (PRV_AdjustTime(NULL, &remadj) < 0)
    LOG_FATAL("adjtime() failed");
#endif

  adjustment_remaining = UTI_TimevalToDouble(&remadj);

  *corr = adjustment_remaining;
  if (err) {
    if (*corr != 0.0)
      *err = 1.0e-6 * MAX_ADJTIME_SLEWRATE / ADJTIME_UPDATE_INTERVAL;
    else
      *err = 0.0;
  }
}
예제 #4
0
static void
accrue_offset(double offset, double corr_rate)
{
  struct timeval newadj, oldadj;
  double doldadj;

  UTI_DoubleToTimeval(-offset, &newadj);

  if (PRV_AdjustTime(&newadj, &oldadj) < 0)
    LOG_FATAL("adjtime() failed");

  /* Add the old remaining adjustment if not zero */
  doldadj = UTI_TimevalToDouble(&oldadj);
  if (doldadj != 0.0) {
    UTI_DoubleToTimeval(-offset + doldadj, &newadj);
    if (PRV_AdjustTime(&newadj, NULL) < 0)
      LOG_FATAL("adjtime() failed");
  }
}