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); }
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; }
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(); } }
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); }
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)(); } }
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); }