From df4f1a664700626f0b949a0cae87a3a735be46db Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 18 Jul 2018 13:59:15 +0200 Subject: hwclock: add --delay * add command line option --delay * read RTC type from /sys/class/rtc/rtc/name * default to 0.5 (500ms) for rtc_cmos or when RTC type is impossible determine; otherwise delay is 0. Signed-off-by: Karel Zak --- sys-utils/hwclock.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 6 deletions(-) (limited to 'sys-utils/hwclock.c') diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c index b83e71004..d9acbaf7d 100644 --- a/sys-utils/hwclock.c +++ b/sys-utils/hwclock.c @@ -78,6 +78,8 @@ #include "timeutils.h" #include "env.h" #include "xalloc.h" +#include "path.h" +#include "strutils.h" #ifdef HAVE_LIBAUDIT #include @@ -409,6 +411,47 @@ set_hardware_clock(const struct hwclock_control *ctl, const time_t newtime) ur->set_hardware_clock(ctl, &new_broken_time); } +static double +get_hardware_delay(const struct hwclock_control *ctl) +{ + const char *devpath, *rtcname; + char name[128 + 1]; + struct path_cxt *pc; + int rc; + + devpath = ur->get_device_path(); + if (!devpath) + goto unknown; + + rtcname = strrchr(devpath, '/'); + if (!rtcname || !*(rtcname + 1)) + goto unknown; + rtcname++; + + pc = ul_new_path("/sys/class/rtc/%s", rtcname); + if (!pc) + goto unknown; + rc = ul_path_scanf(pc, "name", "%128[^\n ]", &name); + ul_unref_path(pc); + + if (rc != 1 || !*name) + goto unknown; + + if (ctl->verbose) + printf(_("RTC type: '%s'\n"), name); + + /* MC146818A-compatible (x86) */ + if (strcmp(name, "rtc_cmos") == 0) + return 0.5; + + /* Another HW */ + return 0; +unknown: + /* Let's be backwardly compatible */ + return 0.5; +} + + /* * Set the Hardware Clock to the time "sethwtime", in local time zone or * UTC, according to "universal". @@ -418,7 +461,8 @@ set_hardware_clock(const struct hwclock_control *ctl, const time_t newtime) * example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5 and * the current system time is 12:10:06.0: Wait .5 seconds (to make exactly 2 * seconds since "refsystime") and then set the Hardware Clock to 14:03:07, - * thus getting a precise and retroactive setting of the clock. + * thus getting a precise and retroactive setting of the clock. The .5 delay is + * default on x86, see --delay and get_hardware_delay(). * * (Don't be confused by the fact that the system clock and the Hardware * Clock differ by two hours in the above example. That's just to remind you @@ -480,15 +524,26 @@ set_hardware_clock_exact(const struct hwclock_control *ctl, time_t newhwtime = sethwtime; double target_time_tolerance_secs = 0.001; /* initial value */ double tolerance_incr_secs = 0.001; /* initial value */ - const double RTC_SET_DELAY_SECS = 0.5; /* 500 ms */ - const struct timeval RTC_SET_DELAY_TV = { 0, RTC_SET_DELAY_SECS * 1E6 }; + double delay; + struct timeval rtc_set_delay_tv; struct timeval targetsystime; struct timeval nowsystime; struct timeval prevsystime = refsystime; double deltavstarget; - timeradd(&refsystime, &RTC_SET_DELAY_TV, &targetsystime); + if (ctl->rtc_delay != -1.0) /* --delay specified */ + delay = ctl->rtc_delay; + else + delay = get_hardware_delay(ctl); + + if (ctl->verbose) + printf(_("Using delay: %.6f seconds\n"), delay); + + rtc_set_delay_tv.tv_sec = 0; + rtc_set_delay_tv.tv_usec = delay * 1E6; + + timeradd(&refsystime, &rtc_set_delay_tv, &targetsystime); while (1) { double ticksize; @@ -549,7 +604,7 @@ set_hardware_clock_exact(const struct hwclock_control *ctl, newhwtime = sethwtime + (int)(time_diff(nowsystime, refsystime) - - RTC_SET_DELAY_SECS /* don't count this */ + - delay /* don't count this */ + 0.5 /* for rounding */); if (ctl->verbose) printf(_("%ld.%06ld is close enough to %ld.%06ld (%.6f < %.6f)\n" @@ -1082,6 +1137,7 @@ usage(void) printf(_( " --directisa use the ISA bus instead of %1$s access\n"), _PATH_RTC_DEV); puts(_(" --date