File hwclock-cpufriendly.diff of Package util-linux
From: Kurt Garloff <garloff@suse.de>
Subject: Avoid busy waiting for too long
References: bnc441106
hwclock does up to 1s busy waiting for a hwclock tick, eating precious
CPU cycles.
Instead do a loop with usleeps(0.02s) to get a rough idea on where the
tick is, then only start busy waiting 0.92 s later. This results in
~0.1s CPU time as opposed to 0.5s average before.
(The combination of --adjust followed by --hctosys would unfortunately
have an average of 1.5s before, we're now down to 0.2s CPU time.)
Downside: We take 1s longer to complete in average.
[Patch 2/4]
Index: util-linux-ng-2.14.1/hwclock/rtc.c
===================================================================
--- util-linux-ng-2.14.1.orig/hwclock/rtc.c
+++ util-linux-ng-2.14.1/hwclock/rtc.c
@@ -170,9 +170,9 @@ do_rtc_read_ioctl(int rtc_fd, struct tm
return 0;
}
static int
-busywait_for_rtc_clock_tick(const int rtc_fd) {
+busywait_for_rtc_clock_tick(const int rtc_fd, const int pause) {
/*----------------------------------------------------------------------------
Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
we see it.
-----------------------------------------------------------------------------*/
@@ -180,8 +180,11 @@ busywait_for_rtc_clock_tick(const int rt
/* The time when we were called (and started waiting) */
struct tm nowtime;
int i; /* local loop index */
int rc;
+ int maxctr = 1000000;
+ if (pause)
+ maxctr = 2000000/pause;
if (debug)
printf(_("Waiting in loop for time from %s to change\n"),
rtc_dev_name);
@@ -196,13 +199,16 @@ busywait_for_rtc_clock_tick(const int rt
*/
for (i = 0;
(rc = do_rtc_read_ioctl(rtc_fd, &nowtime)) == 0
&& start_time.tm_sec == nowtime.tm_sec;
- i++)
- if (i >= 1000000) {
+ i++) {
+ if (i >= maxctr) {
fprintf(stderr, _("Timed out waiting for time change.\n"));
return 2;
}
+ if (pause)
+ usleep(pause);
+ }
if (rc)
return 3;
return 0;
@@ -239,9 +245,16 @@ int ret;
*/
if (debug)
printf(_("%s does not have interrupt functions. "),
rtc_dev_name);
- ret = busywait_for_rtc_clock_tick(rtc_fd);
+ /* Poll with sleeps of 20ms */
+ ret = busywait_for_rtc_clock_tick(rtc_fd, 20000);
+ /* Now we're between 0 and ~40ms after the tick, sleep 920ms */
+ usleep(920000);
+ /* Real busy-waiting, but only for max. 80ms, unless we woke up very late.
+ * TODO: We could check for this and do another usleep then, for now
+ * just deal with the almost 1s busy waiting in this unlikely case. */
+ ret = busywait_for_rtc_clock_tick(rtc_fd, 0);
} else if (rc == 0) {
#ifdef Wait_until_update_interrupt
unsigned long dummy;