File hwclock-nowait.diff of Package util-linux

From: Kurt Garloff <garloff@suse.de>
Subject: New options --nowait and --preadjust for a fast call of hwclock
References: bnc441106

Delaying the boot process by ~1.5s by calling hwclock --adjust; hwclock --hctosys
is not nice.
Instead introduce an option --nowait that allows to not wait for a clock tick, 
resulting in the system time being up to 1s behind the best guess from a call
without that option.
Also introduce the option --preadjust to read adjfile and do the necessary 
corrections before setting the system time. However, don't touch adjfile.
Can result in the system to time being behind the best guess up to yet 
another s.

[Patch 3/4]

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
@@ -1035,9 +1035,9 @@ manipulate_clock(const bool show, const 
                  const bool set, const time_t set_time,
                  const bool hctosys, const bool systohc,
                  const struct timeval startup_time,
                  const bool utc, const bool local_opt,
-		 const bool testing) {
+		 const bool testing, const bool nowait, const bool preadjust) {
 /*---------------------------------------------------------------------------
   Do all the normal work of hwclock - read, set clock, etc.
 
   Issue output to stdout and error message to stderr where appropriate.
@@ -1052,9 +1052,9 @@ manipulate_clock(const bool show, const 
     no_auth = ur->get_permissions();
     if (no_auth)
 	  return EX_NOPERM;
 
-    if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt))) {
+    if (!noadjfile && (nowait || adjust || set || systohc || (!utc && !local_opt))) {
       rc = read_adjtime(&adjtime);
       if (rc)
 	      return rc;
     } else {
@@ -1071,11 +1071,13 @@ manipulate_clock(const bool show, const 
 	adjtime.local_utc = universal ? UTC : LOCAL;
 	adjtime.dirty = TRUE;
       }
 
-      rc = synchronize_to_clock_tick();  /* this takes up to 1 second */
-      if (rc)
-	      return rc;
+      if (!nowait) {
+        rc = synchronize_to_clock_tick();  /* this takes up to 1 second */
+        if (rc)
+	  return rc;
+      }
 
       {
         struct timeval read_time;
           /* The time at which we read the Hardware Clock */
@@ -1093,8 +1095,24 @@ manipulate_clock(const bool show, const 
 
         gettimeofday(&read_time, NULL);
         read_hardware_clock(universal, &hclock_valid, &hclocktime);
 
+	if ((show || hctosys) && preadjust && !noadjfile) {
+	  int adjustment;	/* seconds to add to hclocktime */
+	  double retro;		/* fractions to add to hclocktime */
+	  calculate_adjustment(adjtime.drift_factor,
+			       adjtime.last_adj_time,
+			       adjtime.not_adjusted,
+			       hclocktime,
+			       &adjustment, &retro);
+	  hclocktime += adjustment;
+	  /* We can safely ignore retro here as it's a positive value,
+	   * thus by ignoring it we at worst set the time a bit more
+	   * backwards than we would ideally, which is safe, as a subsequent
+	   * exact setting will only cause a jump forward which is harmless.
+	   * We could do: usleep((1-retro)*1000000); hclocktime += 1; */
+	}
+
         if (show) {
           display_time(hclock_valid, hclocktime,
                        time_diff(read_time, startup_time));
         } else if (set) {
@@ -1234,8 +1252,10 @@ usage( const char *fmt, ... ) {
     "  --noadjfile    do not access /etc/adjtime. Requires the use of\n"
     "                 either --utc or --localtime\n"
     "  --adjfile=path specifies the path to the adjust file (default is\n"
     "                 /etc/adjtime)\n"
+    "  --nowait       don't wait for a clock tick; results in up to 1s error\n"
+    "  --preadjust    apply rough adjfile correction without updating it\n"
     ),RTC_DEV);
 #ifdef __alpha__
   fprintf(usageto, _(
     "  --jensen, --arc, --srm, --funky-toy\n"
@@ -1291,8 +1311,10 @@ static const struct option longopts[] = 
 	{ "date", 1, 0, 136 },
 	{ "epoch", 1, 0, 137 },
 	{ "rtc", 1, 0, 'f' },
 	{ "adjfile", 1, 0, 138 },
+	{ "nowait", 0, 0, 139 },
+	{ "preadjust", 0, 0, 140 },
 	{ NULL, 0, 0, 0 }
 };
 
 /*
@@ -1317,9 +1339,9 @@ main(int argc, char **argv) {
 
 	/* Variables set by various options; show may also be set later */
 	/* The options debug, badyear and epoch_option are global */
 	bool show, set, systohc, hctosys, adjust, getepoch, setepoch;
-	bool utc, testing, local_opt, noadjfile, directisa;
+	bool utc, testing, local_opt, noadjfile, nowait, directisa, preadjust;
 	bool ARCconsole, Jensen, SRM, funky_toy;
 	char *date_opt;
 
 	/* Remember what time we were invoked */
@@ -1346,11 +1368,12 @@ main(int argc, char **argv) {
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 
 	/* Set option defaults */
-	show = set = systohc = hctosys = adjust = noadjfile = FALSE;
+	show = set = systohc = hctosys = adjust = noadjfile = nowait = FALSE;
 	getepoch = setepoch = utc = local_opt = testing = debug = FALSE;
 	ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
+	preadjust = FALSE;
 	date_opt = NULL;
 
 	while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
 	       != -1) {
@@ -1419,8 +1442,14 @@ main(int argc, char **argv) {
 			break;
 		case 138:
 			adj_file_name = optarg;		/* --adjfile */
 			break;
+		case 139:
+			nowait = TRUE;			/* --nowait */
+			break;
+		case 140:
+			preadjust = TRUE;		/* --preadjust */
+			break;
 		case 'f':
 			rtc_dev_name = optarg;		/* --rtc */
 			break;
 		case 'v':				/* --version */
@@ -1477,8 +1506,20 @@ main(int argc, char **argv) {
 				  "are mutually exclusive.  You specified "
 				  "both.\n"), MYNAME);
 		hwclock_exit(EX_USAGE);
 	}
+
+	if (nowait && systohc) {
+		fprintf(stderr, _("%s: You can not use --nowait with "
+				  "--systohc.\n"), MYNAME);
+		hwclock_exit(EX_USAGE);
+	}
+	if (preadjust && (noadjfile || systohc || adjust)) {
+		fprintf(stderr, _("%s: You can not use --preadjust with "
+				  "--systohc or --noadjfile or --adjust.\n"), MYNAME);
+		hwclock_exit(EX_USAGE);
+	}
+
 	if (!adj_file_name)
 		adj_file_name = ADJPATH;
 
 	if (noadjfile && !(utc || local_opt)) {
@@ -1553,9 +1594,9 @@ main(int argc, char **argv) {
 
 	raise_priority();
 	rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
 				hctosys, systohc, startup_time, utc,
-				local_opt, testing);
+				local_opt, testing, nowait, preadjust);
 	hwclock_exit(rc);
 	return rc;	/* Not reached */
 }
 
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
@@ -23,8 +23,10 @@ other options:
 .B "[\-u|\-\-utc]  \-\-localtime  \-\-noadjfile \-\-directisa"
 .B "\-\-test [\-D|\-\-debug]"
 .B "\-\-rtc=filename"
 .B "\-\-adjfile=filename"
+.B "\-\-nowait"
+.B "\-\-preadjust"
 .PP
 and arcane options for DEC Alpha:
 .PP
 .B "[\-A|\-\-arc] [\-J|\-\-jensen] [\-S|\-\-srm] [\-F|\-\-funky-toy]"
@@ -187,8 +189,33 @@ must be specified when using this option
 .B \-\-adjfile=filename
 overrides the default /etc/adjtime.
 
 .TP
+.B \-\-nowait
+causes hwclock not to wait for the next hwclock tick, thus allowing hwclock
+to perform its job quickly rather than waiting for ~1s. The price is that
+the set system time may be up to 1s behind the best guess that would result
+from not using this option. This option makes only sense with
+.B \-\-hctosys
+(
+.B \-s
+). This option is often combined
+.B \-\-preadjust
+and then followed by asynchronous calls with
+.B \-\-adjust
+and
+.B \-\-hctosys
+
+.TP
+.B \-\-preadjust
+causes hwclock to use the drift information from adjfile when transferring
+the hwclock time to the system time. Unlike
+.B \-\-adjust
+it will not update the adjfile nor change the hwclock. The calculation does
+discard sub-second corrections and may result in a time that's up to 1s behind
+the real value.
+
+.TP
 .B \-\-rtc=filename
 overrides the default /dev file name, which is
 .IR /dev/rtc
 on many platforms but may be
openSUSE Build Service is sponsored by