From: Kurt Garloff Subject: Allow to combine --adjust and --hctosys Reference: bnc441106 Waiting for a clock tick twice when calling --adjust and --hctosys is wasteful. Having to do it once is bad enough. This patch allows combining the two options. [Patch 1/5] Index: util-linux-ng-2.14.1/hwclock/hwclock.c =================================================================== --- util-linux-ng-2.14.1.orig/hwclock/hwclock.c +++ util-linux-ng-2.14.1/hwclock/hwclock.c @@ -490,13 +490,18 @@ set_hardware_clock(const time_t newtime, } +static int +set_system_clock(const bool hclock_valid, const time_t newtime, + const bool testing, const int usec); + static void set_hardware_clock_exact(const time_t sethwtime, const struct timeval refsystime, const bool universal, - const bool testing) { + const bool testing, + const bool hctosys) { /*---------------------------------------------------------------------------- Set the Hardware Clock to the time "sethwtime", in local time zone or UTC, according to "universal". @@ -539,8 +544,10 @@ set_hardware_clock_exact(const time_t se if (tdiff < 0) goto time_resync; /* probably time was reset */ } while (time_diff(nowsystime, refsystime) - 0.5 < newhwtime - sethwtime); + if (hctosys) + set_system_clock(TRUE, newhwtime, testing, 500000); set_hardware_clock(newhwtime, universal, testing); } @@ -671,9 +678,9 @@ interpret_date_string(const char *date_o static int set_system_clock(const bool hclock_valid, const time_t newtime, - const bool testing) { + const bool testing, const int usec) { /*---------------------------------------------------------------------------- Set the System Clock to time 'newtime'. Also set the kernel time zone value to the value indicated by the @@ -699,9 +706,9 @@ set_system_clock(const bool hclock_valid int minuteswest; int rc; tv.tv_sec = newtime; - tv.tv_usec = 0; + tv.tv_usec = usec; broken = localtime(&newtime); #ifdef HAVE_TM_GMTOFF minuteswest = -broken->tm_gmtoff/60; /* GNU extension */ @@ -935,9 +942,10 @@ save_adjtime(const struct adjtime adjtim static void do_adjustment(struct adjtime *adjtime_p, const bool hclock_valid, const time_t hclocktime, const struct timeval read_time, - const bool universal, const bool testing) { + const bool universal, const bool testing, + const bool hctosys) { /*--------------------------------------------------------------------------- Do the adjustment requested, by 1) setting the Hardware Clock (if necessary), and 2) updating the last-adjusted time in the adjtime structure. @@ -990,9 +998,9 @@ do_adjustment(struct adjtime *adjtime_p, &adjustment, &retro); if (adjustment > 0 || adjustment < -1) { set_hardware_clock_exact(hclocktime + adjustment, time_inc(read_time, -retro), - universal, testing); + universal, testing, hctosys); adjtime_p->last_adj_time = hclocktime + adjustment; adjtime_p->not_adjusted = 0; adjtime_p->dirty = TRUE; } else @@ -1046,8 +1054,9 @@ manipulate_clock(const bool show, const struct adjtime adjtime; /* Contents of the adjtime file, or what they should be. */ int rc; /* local return code */ bool no_auth; /* User lacks necessary authorization to access the clock */ + int usec = 0; no_auth = ur->get_permissions(); if (no_auth) return EX_NOPERM; @@ -1097,15 +1106,15 @@ manipulate_clock(const bool show, const display_time(hclock_valid, hclocktime, time_diff(read_time, startup_time)); } else if (set) { set_hardware_clock_exact(set_time, startup_time, - universal, testing); + universal, testing, FALSE); if (!noadjfile) adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime, time_diff(read_time, startup_time)); } else if (adjust) { do_adjustment(&adjtime, hclock_valid, hclocktime, - read_time, universal, testing); + read_time, universal, testing, hctosys); } else if (systohc) { struct timeval nowtime, reftime; /* We can only set_hardware_clock_exact to a whole seconds time, so we set it with reference to the most recent @@ -1115,14 +1124,14 @@ manipulate_clock(const bool show, const reftime.tv_sec = nowtime.tv_sec; reftime.tv_usec = 0; set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, - universal, testing); + universal, testing, FALSE); if (!noadjfile) adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, hclocktime, (double) read_time.tv_usec / 1E6); } else if (hctosys) { - rc = set_system_clock(hclock_valid, hclocktime, testing); + rc = set_system_clock(hclock_valid, hclocktime, testing, usec); if (rc) { printf(_("Unable to set system clock.\n")); return rc; } @@ -1442,9 +1451,16 @@ main(int argc, char **argv) { "You supplied %d.\n"), MYNAME, argc); } - if (show + set + systohc + hctosys + adjust + getepoch + setepoch > 1){ + if (show + set + systohc + hctosys + getepoch + setepoch > 1){ + fprintf(stderr, _("You have specified multiple functions.\n" + "You can only perform one function " + "at a time.\n")); + hwclock_exit(EX_USAGE); + } + + if (show + set + systohc + adjust + getepoch + setepoch > 1){ fprintf(stderr, _("You have specified multiple functions.\n" "You can only perform one function " "at a time.\n")); hwclock_exit(EX_USAGE); Index: util-linux-ng-2.14.1/hwclock/hwclock.8 =================================================================== --- util-linux-ng-2.14.1.orig/hwclock/hwclock.8 +++ util-linux-ng-2.14.1/hwclock/hwclock.8 @@ -86,8 +86,12 @@ Set the Hardware Clock to the current Sy .B \-\-adjust Add or subtract time from the Hardware Clock to account for systematic drift since the last time the clock was set or adjusted. See discussion below. +.B \-\-adjust +can be used together with +.B \-\-hctosys +to speed up the boot process by 1s. .TP .B \-\-getepoch Print the kernel's Hardware Clock epoch value to standard output. This is the number of years into AD to which a zero year value in the