示例#1
0
void
SYS_Generic_Finalise(void)
{
  struct timespec now;

  /* Must *NOT* leave a slew running - clock could drift way off
     if the daemon is not restarted */

  SCH_RemoveTimeout(slew_timeout_id);
  slew_timeout_id = 0;

  (*drv_set_freq)(clamp_freq(base_freq));

  LCL_ReadRawTime(&now);
  stop_fastslew(&now);
}
示例#2
0
int
RTC_Linux_Trim(void)
{
  struct timeval now;


  /* Remember the slope coefficient - we won't be able to determine a
     good one in a few seconds when we determine the new offset! */
  saved_coef_gain_rate = coef_gain_rate;

  if (fabs(coef_seconds_fast) > 1.0) {

    LOG(LOGS_INFO, LOGF_RtcLinux, "Trimming RTC, error = %.3f seconds", coef_seconds_fast);

    /* Do processing to set clock.  Let R be the value we set the
       RTC to, then in 500ms the RTC ticks (R+1) (see comments in
       arch/i386/kernel/time.c about the behaviour of the real time
       clock chip).  If S is the system time now, the error at the
       next RTC tick is given by E = (R+1) - (S+0.5).  Ideally we
       want |E| <= 0.5, which implies R <= S <= R+1, i.e. R is just
       the rounded down part of S, i.e. the seconds part. */

    LCL_ReadCookedTime(&now, NULL);
    
    set_rtc(now.tv_sec);

    /* All old samples will now look bogus under the new
           regime. */
    n_samples = 0;
    operating_mode = OM_AFTERTRIM;

    /* Estimate the offset in case writertc is called or chronyd
       is terminated during rapid sampling */
    coef_seconds_fast = -now.tv_usec / 1e6 + 0.5;
    coef_ref_time = now.tv_sec;

    /* And start rapid sampling, interrupts on now */
    if (timeout_running) {
      SCH_RemoveTimeout(timeout_id);
      timeout_running = 0;
    }
    switch_interrupts(1);
  }

  return 1;
  
}
示例#3
0
void
RTC_Linux_Finalise(void)
{
  if (timeout_running) {
    SCH_RemoveTimeout(timeout_id);
    timeout_running = 0;
  }

  /* Remove input file handler */
  if (fd >= 0) {
    SCH_RemoveInputFileHandler(fd);
    close(fd);

    /* Save the RTC data */
    (void) RTC_Linux_WriteParameters();

  }
}
示例#4
0
文件: rtc_linux.c 项目: SuperQ/chrony
void
RTC_Linux_Finalise(void)
{
  SCH_RemoveTimeout(timeout_id);
  timeout_id = 0;

  /* Remove input file handler */
  if (fd >= 0) {
    SCH_RemoveInputFileHandler(fd);
    close(fd);

    /* Save the RTC data */
    (void) RTC_Linux_WriteParameters();

  }
  Free(rtc_sec);
  Free(rtc_trim);
  Free(system_times);
}
示例#5
0
void
NSR_ResolveSources(void)
{
  /* Try to resolve unresolved sources now */
  if (unresolved_sources) {
    /* Make sure no resolving is currently running */
    if (!resolving_source) {
      if (resolving_interval) {
        SCH_RemoveTimeout(resolving_id);
        resolving_interval--;
      }
      resolve_sources(NULL);
    }
  } else {
    /* No unresolved sources, we are done */
    if (resolving_end_handler)
      (resolving_end_handler)();
  }
}
示例#6
0
static void
update_slew(void)
{
  struct timespec now, end_of_slew;
  double old_slew_freq, total_freq, corr_freq, duration;

  /* Remove currently running timeout */
  SCH_RemoveTimeout(slew_timeout_id);

  LCL_ReadRawTime(&now);

  /* Adjust the offset register by achieved slew */
  duration = UTI_DiffTimespecsToDouble(&now, &slew_start);
  offset_register -= slew_freq * duration;

  stop_fastslew(&now);

  /* Estimate how long should the next slew take */
  if (fabs(offset_register) < MIN_OFFSET_CORRECTION) {
    duration = MAX_SLEW_TIMEOUT;
  } else {
    duration = correction_rate / fabs(offset_register);
    if (duration < MIN_SLEW_TIMEOUT)
      duration = MIN_SLEW_TIMEOUT;
  }

  /* Get frequency offset needed to slew the offset in the duration
     and clamp it to the allowed maximum */
  corr_freq = offset_register / duration;
  if (corr_freq < -max_corr_freq)
    corr_freq = -max_corr_freq;
  else if (corr_freq > max_corr_freq)
    corr_freq = max_corr_freq;

  /* Let the system driver perform the slew if the requested frequency
     offset is too large for the frequency driver */
  if (drv_accrue_offset && fabs(corr_freq) >= fastslew_max_rate &&
      fabs(offset_register) > fastslew_min_offset) {
    start_fastslew();
    corr_freq = 0.0;
  }

  /* Get the new real frequency and clamp it */
  total_freq = clamp_freq(base_freq + corr_freq * (1.0e6 - base_freq));

  /* Set the new frequency (the actual frequency returned by the call may be
     slightly different from the requested frequency due to rounding) */
  total_freq = (*drv_set_freq)(total_freq);

  /* Compute the new slewing frequency, it's relative to the real frequency to
     make the calculation in offset_convert() cheaper */
  old_slew_freq = slew_freq;
  slew_freq = (total_freq - base_freq) / (1.0e6 - total_freq);

  /* Compute the dispersion introduced by changing frequency and add it
     to all statistics held at higher levels in the system */
  slew_error = fabs((old_slew_freq - slew_freq) * max_freq_change_delay);
  if (slew_error >= MIN_OFFSET_CORRECTION)
    lcl_InvokeDispersionNotifyHandlers(slew_error);

  /* Compute the duration of the slew and clamp it.  If the slewing frequency
     is zero or has wrong sign (e.g. due to rounding in the frequency driver or
     when base_freq is larger than max_freq, or fast slew is active), use the
     maximum timeout and try again on the next update. */
  if (fabs(offset_register) < MIN_OFFSET_CORRECTION ||
      offset_register * slew_freq <= 0.0) {
    duration = MAX_SLEW_TIMEOUT;
  } else {
    duration = offset_register / slew_freq;
    if (duration < MIN_SLEW_TIMEOUT)
      duration = MIN_SLEW_TIMEOUT;
    else if (duration > MAX_SLEW_TIMEOUT)
      duration = MAX_SLEW_TIMEOUT;
  }

  /* Restart timer for the next update */
  UTI_AddDoubleToTimespec(&now, duration, &end_of_slew);
  slew_timeout_id = SCH_AddTimeout(&end_of_slew, handle_end_of_slew, NULL);
  slew_start = now;

  DEBUG_LOG("slew offset=%e corr_rate=%e base_freq=%f total_freq=%f slew_freq=%e duration=%f slew_error=%e",
      offset_register, correction_rate, base_freq, total_freq, slew_freq,
      duration, slew_error);
}