[pkg-ntp-maintainers] ntp: don't wake up every second
Serge E. Hallyn
serge.hallyn at canonical.com
Tue Jan 18 17:41:20 UTC 2011
Hi,
A patch (based on a Fedora patch which was rejected by the ntp upstream)
was submitted against the Ubuntu ntp package, to reduce the number of
wakeups for the sake of power savings. I was wondering whether you
deemed this suitable for the Debian package. I'm afraid I'm not
qualified to comment on the patch's correctness myself, though at least
it does build and run. The debdiff against the Debian sid ntp package
is appended below, and the original patch submission for Ubuntu was at:
https://bugs.launchpad.net/ubuntu/+source/ntp/+bug/697676
The description from the submitter was:
> The current design of ntp makes it generate at least 1 wakeup/second,
> thus disallowing the CPU to enter deeper states of sleep [1].
>
> I propose applying a patch from Fedora which solves this issue. Previous
> attempts at integrating it upstream failed [2], despite the fact that
> the patch is used in Fedora for a long time. Hopefully, with the
> increasing need for energy efficient computing and Ubuntu validating the
> approach, upstream will be more willing to integrate the fix.
thanks,
-serge
diff -Nru ntp-4.2.6.p2+dfsg/debian/changelog ntp-4.2.6.p2+dfsg/debian/changelog
--- ntp-4.2.6.p2+dfsg/debian/changelog 2010-07-13 13:33:53.000000000 -0500
+++ ntp-4.2.6.p2+dfsg/debian/changelog 2011-01-18 09:46:29.000000000 -0600
@@ -1,3 +1,10 @@
+ntp (1:4.2.6.p2+dfsg-1polar1) natty; urgency=low
+
+ * Incorporate patch (by cristiklein at gmail.com and based on a patch in Fedora)
+ to not necessarily wake up every second. (LP: #697676)
+
+ -- Serge Hallyn <serge.hallyn at ubuntu.com> Tue, 18 Jan 2011 09:42:37 -0600
+
ntp (1:4.2.6.p2+dfsg-1) unstable; urgency=low
[ Peter Eisentraut ]
diff -Nru ntp-4.2.6.p2+dfsg/debian/patches/ntpd-sleep.patch ntp-4.2.6.p2+dfsg/debian/patches/ntpd-sleep.patch
--- ntp-4.2.6.p2+dfsg/debian/patches/ntpd-sleep.patch 1969-12-31 19:00:00.000000000 -0500
+++ ntp-4.2.6.p2+dfsg/debian/patches/ntpd-sleep.patch 2011-01-18 09:42:09.000000000 -0600
@@ -0,0 +1,507 @@
+From: cristiklein at gmail.com
+Description: Promote power savings by not waking up every second.
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ntp/+bug/697676
+
+Index: ntp-4.2.6.p2+dfsg/include/ntp_refclock.h
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/include/ntp_refclock.h 2009-12-09 01:36:35.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/include/ntp_refclock.h 2011-01-18 09:35:20.658203002 -0600
+@@ -260,6 +260,7 @@
+ struct refclockstat *);
+ extern int refclock_open (char *, u_int, u_int);
+ extern int refclock_setup (int, u_int, u_int);
++extern int refclock_timer_needed (struct peer *);
+ extern void refclock_timer (struct peer *);
+ extern void refclock_transmit (struct peer *);
+ extern int refclock_ioctl (int, u_int);
+Index: ntp-4.2.6.p2+dfsg/include/ntp_stdlib.h
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/include/ntp_stdlib.h 2010-06-03 01:05:26.000000000 -0500
++++ ntp-4.2.6.p2+dfsg/include/ntp_stdlib.h 2011-01-18 09:35:20.662203002 -0600
+@@ -117,6 +117,7 @@
+ extern void signal_no_reset (int, RETSIGTYPE (*func)(int));
+
+ extern void getauthkeys (const char *);
++extern int auth_agekeys_needed (void);
+ extern void auth_agekeys (void);
+ extern void rereadkeys (void);
+
+Index: ntp-4.2.6.p2+dfsg/include/ntpd.h
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/include/ntpd.h 2011-01-18 09:33:45.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/include/ntpd.h 2011-01-18 09:35:20.662203002 -0600
+@@ -113,8 +113,10 @@
+ /* ntp_loopfilter.c */
+ extern void init_loopfilter(void);
+ extern int local_clock(struct peer *, double);
+-extern void adj_host_clock(void);
++extern int adj_host_clock_needed(void);
++extern void adj_host_clock(int);
+ extern void loop_config(int, double);
++extern int huffpuff_enabled(void);
+ extern void huffpuff(void);
+ extern u_long sys_clocktime;
+ extern u_int sys_tai;
+@@ -220,6 +222,8 @@
+ /* ntp_timer.c */
+ extern void init_timer (void);
+ extern void reinit_timer (void);
++extern double get_timeout (l_fp *);
++extern int timer_elapsed (l_fp, int);
+ extern void timer (void);
+ extern void timer_clr_stats (void);
+ extern void timer_interfacetimeout (u_long);
+Index: ntp-4.2.6.p2+dfsg/libntp/authkeys.c
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/libntp/authkeys.c 2009-12-09 01:36:35.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/libntp/authkeys.c 2011-01-18 09:35:20.662203002 -0600
+@@ -445,6 +445,25 @@
+ }
+ }
+
++int
++auth_agekeys_needed(void) {
++ struct savekey *sk;
++ int i;
++
++ if (authnumkeys > 20)
++ return 1;
++
++ for (i = 0; i < HASHSIZE; i++) {
++ sk = key_hash[i];
++ while (sk != 0) {
++ if (sk->lifetime > 0)
++ return 1;
++ sk = sk->next;
++ }
++ }
++ return 0;
++}
++
+ /*
+ * auth_agekeys - delete keys whose lifetimes have expired
+ */
+Index: ntp-4.2.6.p2+dfsg/ntpd/ntp_loopfilter.c
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/ntpd/ntp_loopfilter.c 2011-01-18 09:33:45.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/ntpd/ntp_loopfilter.c 2011-01-18 09:35:20.662203002 -0600
+@@ -675,6 +675,13 @@
+ #endif /* LOCKCLOCK */
+ }
+
++int
++adj_host_clock_needed(void)
++{
++ return !(!ntp_enable || mode_ntpdate || (pll_control &&
++ kern_enable));
++}
++
+
+ /*
+ * adj_host_clock - Called once every second to update the local clock.
+@@ -684,7 +691,7 @@
+ */
+ void
+ adj_host_clock(
+- void
++ int time_elapsed
+ )
+ {
+ double adjustment;
+@@ -696,7 +703,7 @@
+ * since the poll interval can exceed one day, the old test
+ * would be counterproductive.
+ */
+- sys_rootdisp += clock_phi;
++ sys_rootdisp += clock_phi * time_elapsed;
+
+ #ifndef LOCKCLOCK
+ /*
+@@ -816,6 +823,12 @@
+ #endif /* KERNEL_PLL */
+ }
+
++int
++huffpuff_enabled(void)
++{
++ return sys_huffpuff != NULL;
++}
++
+ /*
+ * huff-n'-puff filter
+ */
+Index: ntp-4.2.6.p2+dfsg/ntpd/ntp_refclock.c
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/ntpd/ntp_refclock.c 2010-06-19 01:40:31.000000000 -0500
++++ ntp-4.2.6.p2+dfsg/ntpd/ntp_refclock.c 2011-01-18 09:35:20.666203002 -0600
+@@ -269,6 +269,21 @@
+ }
+
+
++int
++refclock_timer_needed(
++ struct peer *peer /* peer structure pointer */
++ )
++{
++ u_char clktype;
++ int unit;
++
++ clktype = peer->refclktype;
++ unit = peer->refclkunit;
++ if (refclock_conf[clktype]->clock_timer != noentry)
++ return 1;
++ return 0;
++}
++
+ /*
+ * refclock_timer - called once per second for housekeeping.
+ */
+Index: ntp-4.2.6.p2+dfsg/ntpd/ntp_timer.c
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/ntpd/ntp_timer.c 2009-12-09 01:36:35.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/ntpd/ntp_timer.c 2011-01-18 09:35:20.666203002 -0600
+@@ -56,7 +56,6 @@
+ static u_long stats_timer; /* stats timer */
+ static u_long huffpuff_timer; /* huff-n'-puff timer */
+ u_long leapsec; /* leapseconds countdown */
+-l_fp sys_time; /* current system time */
+ #ifdef OPENSSL
+ static u_long revoke_timer; /* keys revoke timer */
+ static u_long keys_timer; /* session key timer */
+@@ -74,6 +73,12 @@
+ #define DAY (24 * HOUR)
+
+ u_long current_time; /* seconds since startup */
++l_fp timer_base;
++int time_elapsed;
++
++#define TIMEOUT_TS_SIZE 2
++l_fp timeout_ts[TIMEOUT_TS_SIZE];
++unsigned int timeout_ts_index;
+
+ /*
+ * Stats. Number of overflows and number of calls to transmit().
+@@ -110,6 +115,8 @@
+ void
+ reinit_timer(void)
+ {
++ get_systime(&timer_base);
++#if 0
+ #if !defined(SYS_WINNT) && !defined(VMS)
+ # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
+ timer_gettime(ntpd_timerid, &itimer);
+@@ -143,6 +150,7 @@
+ setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+ # endif
+ # endif /* VMS */
++#endif
+ }
+
+ /*
+@@ -165,6 +173,12 @@
+ timer_xmtcalls = 0;
+ timer_timereset = 0;
+
++ get_systime(&timer_base);
++
++ for (timeout_ts_index = 0; timeout_ts_index < TIMEOUT_TS_SIZE; timeout_ts_index++)
++ L_CLR(&timeout_ts[timeout_ts_index]);
++ timeout_ts_index = 0;
++#if 0
+ #if !defined(SYS_WINNT)
+ /*
+ * Set up the alarm interrupt. The first comes 2**EVENT_TIMEOUT
+@@ -226,6 +240,7 @@
+ }
+
+ #endif /* SYS_WINNT */
++#endif
+ }
+
+ #if defined(SYS_WINNT)
+@@ -236,6 +251,104 @@
+ }
+ #endif
+
++double
++get_timeout(l_fp *now)
++{
++ register struct peer *peer, *next_peer;
++ u_int n;
++ double r;
++ int next;
++ l_fp ts;
++
++ ts = *now;
++ L_SUB(&ts, &timeout_ts[timeout_ts_index]);
++ timeout_ts[timeout_ts_index] = *now;
++ timeout_ts_index = (timeout_ts_index + 1) % TIMEOUT_TS_SIZE;
++
++ /* don't waste CPU time if called too frequently */
++ if (ts.l_ui == 0) {
++ next = 1;
++ goto finish;
++ }
++
++ next = current_time + HOUR;
++
++ if (adj_host_clock_needed()) {
++ next = 1;
++ goto finish;
++ }
++ for (n = 0; n < NTP_HASH_SIZE; n++) {
++ for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
++ next_peer = peer->next;
++#ifdef REFCLOCK
++ if (peer->flags & FLAG_REFCLOCK && refclock_timer_needed(peer)) {
++ next = 1;
++ goto finish;
++ }
++#endif /* REFCLOCK */
++ if (peer->action)
++ next = min(next, peer->nextaction);
++ next = min(next, peer->nextdate);
++ }
++ }
++
++ if (leapsec > 0)
++ next = min(next, leapsec);
++
++ if (huffpuff_enabled())
++ next = min(next, huffpuff_timer);
++
++#ifdef OPENSSL
++ if (auth_agekeys_needed())
++ next = min(next, keys_timer);
++ if (sys_leap != LEAP_NOTINSYNC)
++ next = min(next, revoke_timer);
++#endif /* OPENSSL */
++
++ if (interface_interval)
++ next = min(next, interface_timer);
++
++ next = min(next, stats_timer);
++
++ next -= current_time;
++ if (next <= 0)
++ next = 1;
++finish:
++ ts = timer_base;
++ ts.l_ui += next;
++ L_SUB(&ts, now);
++ LFPTOD(&ts, r);
++#ifdef DEBUG
++ DPRINTF(2, ("timer: timeout %f\n", r));
++#endif
++
++ return r;
++}
++
++int
++timer_elapsed(l_fp now, int timeout)
++{
++ int elapsed;
++
++ L_SUB(&now, &timer_base);
++ elapsed = now.l_i;
++ if (elapsed < 0 || elapsed > timeout + 10) {
++#ifdef DEBUG
++ DPRINTF(2, ("timer: unexpected time jump\n"));
++#endif
++ elapsed = 0;
++ reinit_timer();
++
++ }
++ timer_base.l_ui += elapsed;
++ time_elapsed += elapsed;
++ current_time += elapsed;
++#ifdef DEBUG
++ DPRINTF(2, ("timer: time elapsed %d\n", time_elapsed));
++#endif
++ return time_elapsed;
++}
++
+ /*
+ * timer - event timer
+ */
+@@ -251,11 +364,9 @@
+ * kiss-o'-deatch function and implement the association
+ * polling function..
+ */
+- current_time++;
+- get_systime(&sys_time);
+ if (adjust_timer <= current_time) {
+- adjust_timer += 1;
+- adj_host_clock();
++ adjust_timer += time_elapsed;
++ adj_host_clock(time_elapsed);
+ #ifdef REFCLOCK
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
+ for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
+@@ -286,7 +397,7 @@
+ * 128 s or less.
+ */
+ if (peer->throttle > 0)
+- peer->throttle--;
++ peer->throttle -= min(peer->throttle, time_elapsed);
+ if (peer->nextdate <= current_time) {
+ #ifdef REFCLOCK
+ if (peer->flags & FLAG_REFCLOCK)
+@@ -333,7 +444,7 @@
+ * set.
+ */
+ if (leapsec > 0) {
+- leapsec--;
++ leapsec -= min(leapsec, time_elapsed);
+ if (leapsec == 0) {
+ sys_leap = LEAP_NOWARNING;
+ sys_tai = leap_tai;
+@@ -398,11 +509,15 @@
+ * Finally, write hourly stats.
+ */
+ if (stats_timer <= current_time) {
++ l_fp sys_time;
++ get_systime(&sys_time);
+ stats_timer += HOUR;
+ write_stats();
+ if (sys_tai != 0 && sys_time.l_ui > leap_expire)
+ report_event(EVNT_LEAPVAL, NULL, NULL);
+ }
++
++ time_elapsed = 0;
+ }
+
+
+Index: ntp-4.2.6.p2+dfsg/ntpd/ntpd.c
+===================================================================
+--- ntp-4.2.6.p2+dfsg.orig/ntpd/ntpd.c 2011-01-18 09:33:45.000000000 -0600
++++ ntp-4.2.6.p2+dfsg/ntpd/ntpd.c 2011-01-18 09:35:20.670203002 -0600
+@@ -197,8 +197,6 @@
+
+ char const *progname;
+
+-int was_alarmed;
+-
+ #ifdef DECL_SYSCALL
+ /*
+ * We put this here, since the argument profile is syscall-specific
+@@ -1054,7 +1052,7 @@
+ #else /* normal I/O */
+
+ BLOCK_IO_AND_ALARM();
+- was_alarmed = 0;
++
+ for (;;)
+ {
+ # if !defined(HAVE_SIGNALED_IO)
+@@ -1062,42 +1060,39 @@
+ extern int maxactivefd;
+
+ fd_set rdfdes;
+- int nfound;
+-# endif
++ int nfound, time_elapsed;
+
+- if (alarm_flag) /* alarmed? */
+- {
+- was_alarmed = 1;
+- alarm_flag = 0;
+- }
++ time_elapsed = 0;
++# endif
+
+- if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
++ if (has_full_recv_buffer() == ISC_FALSE)
+ {
+ /*
+ * Nothing to do. Wait for something.
+ */
+ # ifndef HAVE_SIGNALED_IO
++ double timeout;
++
+ rdfdes = activefds;
+-# if defined(VMS) || defined(SYS_VXWORKS)
+- /* make select() wake up after one second */
+- {
+- struct timeval t1;
++ get_systime(&now);
++ timeout = get_timeout(&now);
+
+- t1.tv_sec = 1; t1.tv_usec = 0;
++ if (timeout > 0.0) {
++ struct timeval t1;
++
++ t1.tv_sec = timeout;
++ t1.tv_usec = (timeout - t1.tv_sec) * 1000000;
+ nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
+ (fd_set *)0, &t1);
+- }
+-# else
+- nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
+- (fd_set *)0, (struct timeval *)0);
+-# endif /* VMS */
+- if (nfound > 0)
+- {
+- l_fp ts;
++ get_systime(&now);
++ } else
++ nfound = 0;
+
+- get_systime(&ts);
++ time_elapsed = timer_elapsed(now, timeout);
+
+- (void)input_handler(&ts);
++ if (nfound > 0)
++ {
++ (void)input_handler(&now);
+ }
+ else if (nfound == -1 && errno != EINTR)
+ msyslog(LOG_ERR, "select() error: %m");
+@@ -1106,17 +1101,13 @@
+ msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
+ # endif /* DEBUG */
+ # else /* HAVE_SIGNALED_IO */
++# error not supported by sleep patch
+
+ wait_for_signal();
+ # endif /* HAVE_SIGNALED_IO */
+- if (alarm_flag) /* alarmed? */
+- {
+- was_alarmed = 1;
+- alarm_flag = 0;
+- }
+ }
+
+- if (was_alarmed)
++ if (time_elapsed > 0)
+ {
+ UNBLOCK_IO_AND_ALARM();
+ /*
+@@ -1124,7 +1115,6 @@
+ * to process expiry.
+ */
+ timer();
+- was_alarmed = 0;
+ BLOCK_IO_AND_ALARM();
+ }
+
+@@ -1142,19 +1132,8 @@
+ rbuf = get_full_recv_buffer();
+ while (rbuf != NULL)
+ {
+- if (alarm_flag)
+- {
+- was_alarmed = 1;
+- alarm_flag = 0;
+- }
+ UNBLOCK_IO_AND_ALARM();
+
+- if (was_alarmed)
+- { /* avoid timer starvation during lengthy I/O handling */
+- timer();
+- was_alarmed = 0;
+- }
+-
+ /*
+ * Call the data procedure to handle each received
+ * packet.
diff -Nru ntp-4.2.6.p2+dfsg/debian/patches/series ntp-4.2.6.p2+dfsg/debian/patches/series
--- ntp-4.2.6.p2+dfsg/debian/patches/series 2010-05-24 05:28:33.000000000 -0500
+++ ntp-4.2.6.p2+dfsg/debian/patches/series 2011-01-18 09:35:16.000000000 -0600
@@ -9,3 +9,4 @@
autotools.patch
mod_nano.patch
nanokernel-status.patch
+ntpd-sleep.patch
More information about the pkg-ntp-maintainers
mailing list