rtc: factor out RTC_Linux_ReadTime_Now
We have code to read RTC time and handle the error associated with having no UIE interrupt, which we currently use as part of maintaining the correction file. In a later commit, we will need the same functionality for using the RTC as reference clock, so export the function and give it a descriptive name appropriate for a globally visible function.
This commit is contained in:
parent
577cf09bc5
commit
5ce34d07fb
2 changed files with 53 additions and 48 deletions
99
rtc_linux.c
99
rtc_linux.c
|
@ -930,6 +930,28 @@ RTC_Linux_WriteParameters(void)
|
||||||
return(retval);
|
return(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t
|
||||||
|
RTC_Linux_ReadTime_Now(int fd, int utc, struct timespec *old_sys_time)
|
||||||
|
{
|
||||||
|
struct rtc_time rtc_raw, rtc_raw_retry;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
return status >= 0 ? t_from_rtc(&rtc_raw, utc) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Try to set the system clock from the RTC, in the same manner as
|
/* Try to set the system clock from the RTC, in the same manner as
|
||||||
/sbin/hwclock -s would do. We're not as picky about OS version
|
/sbin/hwclock -s would do. We're not as picky about OS version
|
||||||
|
@ -939,8 +961,7 @@ RTC_Linux_WriteParameters(void)
|
||||||
int
|
int
|
||||||
RTC_Linux_TimePreInit(time_t driftfile_time)
|
RTC_Linux_TimePreInit(time_t driftfile_time)
|
||||||
{
|
{
|
||||||
int fd, status;
|
int fd;
|
||||||
struct rtc_time rtc_raw, rtc_raw_retry;
|
|
||||||
time_t rtc_t;
|
time_t rtc_t;
|
||||||
double accumulated_error, sys_offset;
|
double accumulated_error, sys_offset;
|
||||||
struct timespec new_sys_time, old_sys_time;
|
struct timespec new_sys_time, old_sys_time;
|
||||||
|
@ -956,59 +977,41 @@ RTC_Linux_TimePreInit(time_t driftfile_time)
|
||||||
return 0; /* Can't open it, and won't be able to later */
|
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.
|
rtc_t = RTC_Linux_ReadTime_Now(fd, rtc_on_utc, &old_sys_time);
|
||||||
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);
|
close(fd);
|
||||||
|
|
||||||
if (status >= 0) {
|
if (rtc_t != (time_t)(-1)) {
|
||||||
/* Convert to seconds since 1970 */
|
|
||||||
rtc_t = t_from_rtc(&rtc_raw, rtc_on_utc);
|
|
||||||
|
|
||||||
if (rtc_t != (time_t)(-1)) {
|
/* Work out approximatation to correct time (to about the
|
||||||
|
nearest second) */
|
||||||
/* Work out approximatation to correct time (to about the
|
if (valid_coefs_from_file) {
|
||||||
nearest second) */
|
accumulated_error = file_ref_offset +
|
||||||
if (valid_coefs_from_file) {
|
(rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm;
|
||||||
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_nsec = 500000000;
|
|
||||||
|
|
||||||
UTI_AddDoubleToTimespec(&new_sys_time, -accumulated_error, &new_sys_time);
|
|
||||||
|
|
||||||
if (new_sys_time.tv_sec < driftfile_time) {
|
|
||||||
LOG(LOGS_WARN, "RTC time before last driftfile modification (ignored)");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_offset = UTI_DiffTimespecsToDouble(&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, "System time set from RTC");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
accumulated_error = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Correct time */
|
||||||
|
|
||||||
|
new_sys_time.tv_sec = rtc_t;
|
||||||
|
/* Average error in the RTC reading */
|
||||||
|
new_sys_time.tv_nsec = 500000000;
|
||||||
|
|
||||||
|
UTI_AddDoubleToTimespec(&new_sys_time, -accumulated_error, &new_sys_time);
|
||||||
|
|
||||||
|
if (new_sys_time.tv_sec < driftfile_time) {
|
||||||
|
LOG(LOGS_WARN, "RTC time before last driftfile modification (ignored)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sys_offset = UTI_DiffTimespecsToDouble(&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, "System time set from RTC");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,5 +46,7 @@ extern int RTC_Linux_SwitchInterrupt(int fd, int on_off);
|
||||||
extern int RTC_Linux_CheckInterrupt(int fd);
|
extern int RTC_Linux_CheckInterrupt(int fd);
|
||||||
extern time_t RTC_Linux_ReadTime_AfterInterrupt(int fd, int utc,
|
extern time_t RTC_Linux_ReadTime_AfterInterrupt(int fd, int utc,
|
||||||
struct timespec *sys_time_cooked);
|
struct timespec *sys_time_cooked);
|
||||||
|
extern time_t RTC_Linux_ReadTime_Now(int fd, int utc,
|
||||||
|
struct timespec *sys_time_cooked);
|
||||||
|
|
||||||
#endif /* _GOT_RTC_LINUX_H */
|
#endif /* _GOT_RTC_LINUX_H */
|
||||||
|
|
Loading…
Reference in a new issue