int MNL_DeleteSample(int index) { int i; struct timeval now; if ((index < 0) || (index >= n_samples)) { return 0; } /* Crunch the samples down onto the one being deleted */ for (i=index; i<(n_samples-1); i++) { samples[i] = samples[i+1]; } n_samples -= 1; /* Now re-estimate. NULLs because we don't want the parameters back in this case. */ LCL_ReadCookedTime(&now, NULL); estimate_and_set_system(&now, 0, 0.0, NULL, NULL, NULL); return 1; }
int MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm) { struct timeval now; double offset, diff; int i; if (enabled) { LCL_ReadCookedTime(&now, NULL); /* Make sure the provided timestamp is sane and the sample is not too close to the last one */ if (!UTI_IsTimeOffsetSane(ts, 0.0)) return 0; if (n_samples) { UTI_DiffTimevalsToDouble(&diff, &now, &samples[n_samples - 1].when); if (diff < MIN_SAMPLE_SEPARATION) return 0; } UTI_DiffTimevalsToDouble(&offset, &now, ts); /* Check if buffer full up */ if (n_samples == MAX_SAMPLES) { /* Shift samples down */ for (i=1; i<n_samples; i++) { samples[i-1] = samples[i]; } --n_samples; } samples[n_samples].when = now; samples[n_samples].offset = offset; samples[n_samples].orig_offset = offset; ++n_samples; estimate_and_set_system(&now, 1, offset, offset_cs, dfreq_ppm, new_afreq_ppm); return 1; } else { return 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; }
static void fallback_time_init(void) { struct timeval now; struct stat buf; char *drift_file; drift_file = CNF_GetDriftFile(); if (!drift_file) return; if (stat(drift_file, &buf)) return; LCL_ReadCookedTime(&now, NULL); if (now.tv_sec < buf.st_mtime) { LCL_ApplyStepOffset(now.tv_sec - buf.st_mtime); LOG(LOGS_INFO, LOGF_Rtc, "System clock set from driftfile %s", drift_file); } }
int MNL_AcceptTimestamp(struct timeval *ts, long *offset_cs, double *dfreq_ppm, double *new_afreq_ppm) { struct timeval now; double offset; int i; if (enabled) { /* Check whether timestamp is within margin of old one */ LCL_ReadCookedTime(&now, NULL); UTI_DiffTimevalsToDouble(&offset, &now, ts); /* Check if buffer full up */ if (n_samples == MAX_SAMPLES) { /* Shift samples down */ for (i=1; i<n_samples; i++) { samples[i-1] = samples[i]; } --n_samples; } samples[n_samples].when = now; samples[n_samples].offset = offset; samples[n_samples].orig_offset = offset; ++n_samples; estimate_and_set_system(&now, 1, offset, offset_cs, dfreq_ppm, new_afreq_ppm); return 1; } else { return 0; } }
int RTC_Linux_TimePreInit(time_t driftfile_time) { int fd, status; struct rtc_time rtc_raw, rtc_raw_retry; struct tm rtc_tm; time_t rtc_t; double accumulated_error, sys_offset; struct timeval new_sys_time, old_sys_time; coefs_file_name = CNF_GetRtcFile(); setup_config(); read_coefs_from_file(); fd = open(CNF_GetRtcDevice(), O_RDONLY); if (fd < 0) { return 0; /* Can't open it, and won't be able to later */ } /* Retry reading the rtc until both read attempts give the same sec value. This way the race condition is prevented that the RTC has updated itself during the first read operation. */ do { status = ioctl(fd, RTC_RD_TIME, &rtc_raw); if (status >= 0) { status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry); } } while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec); /* Read system clock */ LCL_ReadCookedTime(&old_sys_time, NULL); close(fd); if (status >= 0) { /* Convert to seconds since 1970 */ rtc_tm.tm_sec = rtc_raw.tm_sec; rtc_tm.tm_min = rtc_raw.tm_min; rtc_tm.tm_hour = rtc_raw.tm_hour; rtc_tm.tm_mday = rtc_raw.tm_mday; rtc_tm.tm_mon = rtc_raw.tm_mon; rtc_tm.tm_year = rtc_raw.tm_year; rtc_t = t_from_rtc(&rtc_tm); if (rtc_t != (time_t)(-1)) { /* Work out approximatation to correct time (to about the nearest second) */ if (valid_coefs_from_file) { accumulated_error = file_ref_offset + (rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm; } else { accumulated_error = 0.0; } /* Correct time */ new_sys_time.tv_sec = rtc_t; /* Average error in the RTC reading */ new_sys_time.tv_usec = 500000; UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time); if (new_sys_time.tv_sec < driftfile_time) { LOG(LOGS_WARN, LOGF_RtcLinux, "RTC time before last driftfile modification (ignored)"); return 0; } UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time); /* Set system time only if the step is larger than 1 second */ if (fabs(sys_offset) >= 1.0) { if (LCL_ApplyStepOffset(sys_offset)) LOG(LOGS_INFO, LOGF_RtcLinux, "System time set from RTC"); } } else { return 0; } } else { return 0; } return 1; }