[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20070122192712.GC12911@elte.hu>
Date: Mon, 22 Jan 2007 20:27:12 +0100
From: Ingo Molnar <mingo@...e.hu>
To: john stultz <johnstul@...ibm.com>
Cc: Roman Zippel <zippel@...ux-m68k.org>,
Thomas Gleixner <tglx@...utronix.de>,
Andrew Morton <akpm@...l.org>, linux-kernel@...r.kernel.org
Subject: [patch] HZ-free NTP
* john stultz <johnstul@...ibm.com> wrote:
> And here would be the follow on patch (again *untested*) for
> CONFIG_NO_HZ slowing the time accumulation down to once per second.
thanks John - i've applied the combined patch below to -rt. It appears
to work fine for me.
Ingo
------------------------>
From: John Stultz <johnstul@...ibm.com>
Subject: [patch] HZ-free NTP
Basically INTERVAL_LENGTH_NSEC defines the NTP interval length that the
time code will use to accumulate with. In this patch I've pushed it out
to a full second, but it could be set via config (NSEC_PER_SEC/HZ for
regular systems, something larger for systems using dynticks).
Signed-off-by: Ingo Molnar <mingo@...e.hu>
---
include/linux/timex.h | 4 ++++
kernel/hrtimer.c | 4 +++-
kernel/time/ntp.c | 30 +++++++++++++++++++-----------
kernel/timer.c | 4 ++--
4 files changed, 28 insertions(+), 14 deletions(-)
Index: linux/include/linux/timex.h
===================================================================
--- linux.orig/include/linux/timex.h
+++ linux/include/linux/timex.h
@@ -286,7 +286,11 @@ static inline void time_interpolator_upd
#define TICK_LENGTH_SHIFT 32
+#ifdef CONFIG_NO_HZ
+#define NTP_INTERVAL_FREQ (1)
+#else
#define NTP_INTERVAL_FREQ (HZ)
+#endif
#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
Index: linux/kernel/hrtimer.c
===================================================================
--- linux.orig/kernel/hrtimer.c
+++ linux/kernel/hrtimer.c
@@ -135,12 +135,14 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
*/
static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
{
+ struct timespec ts;
ktime_t xtim, tomono;
unsigned long seq;
do {
seq = read_seqbegin(&xtime_lock);
- xtim = timespec_to_ktime(xtime);
+ getnstimeofday(&ts);
+ xtim = timespec_to_ktime(ts);
tomono = timespec_to_ktime(wall_to_monotonic);
} while (read_seqretry(&xtime_lock, seq));
Index: linux/kernel/time/ntp.c
===================================================================
--- linux.orig/kernel/time/ntp.c
+++ linux/kernel/time/ntp.c
@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base
#define MAX_TICKADJ 500 /* microsecs */
#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
- TICK_LENGTH_SHIFT) / HZ)
+ TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
/*
* phase-lock loop variables
@@ -46,13 +46,17 @@ long time_adjust;
static void ntp_update_frequency(void)
{
- tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
- tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
- tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+ u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
+ << TICK_LENGTH_SHIFT;
+ second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
+ second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
- do_div(tick_length_base, HZ);
+ tick_length_base = second_length;
- tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
+ do_div(second_length, HZ);
+ tick_nsec = second_length >> TICK_LENGTH_SHIFT;
+
+ do_div(tick_length_base, NTP_INTERVAL_FREQ);
}
/**
@@ -164,7 +168,7 @@ void second_overflow(void)
tick_length -= MAX_TICKADJ_SCALED;
} else {
tick_length += (s64)(time_adjust * NSEC_PER_USEC /
- HZ) << TICK_LENGTH_SHIFT;
+ NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
time_adjust = 0;
}
}
@@ -241,7 +245,8 @@ int do_adjtimex(struct timex *txc)
result = -EINVAL;
goto leave;
}
- time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC);
+ time_freq = ((s64)txc->freq * NSEC_PER_USEC)
+ >> (SHIFT_USEC - SHIFT_NSEC);
}
if (txc->modes & ADJ_MAXERROR) {
@@ -311,7 +316,8 @@ int do_adjtimex(struct timex *txc)
freq_adj += time_freq;
freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
- time_offset = (time_offset / HZ) << SHIFT_UPDATE;
+ time_offset = (time_offset / NTP_INTERVAL_FREQ)
+ << SHIFT_UPDATE;
} /* STA_PLL */
} /* txc->modes & ADJ_OFFSET */
if (txc->modes & ADJ_TICK)
@@ -326,8 +332,10 @@ leave: if ((time_status & (STA_UNSYNC|ST
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
txc->offset = save_adjust;
else
- txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
- txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC);
+ txc->offset = shift_right(time_offset, SHIFT_UPDATE)
+ * NTP_INTERVAL_FREQ / 1000;
+ txc->freq = (time_freq / NSEC_PER_USEC)
+ << (SHIFT_USEC - SHIFT_NSEC);
txc->maxerror = time_maxerror;
txc->esterror = time_esterror;
txc->status = time_status;
Index: linux/kernel/timer.c
===================================================================
--- linux.orig/kernel/timer.c
+++ linux/kernel/timer.c
@@ -1030,7 +1030,7 @@ static void change_clocksource(void)
clock->error = 0;
clock->xtime_nsec = 0;
- clocksource_calculate_interval(clock, tick_nsec);
+ clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
tick_clock_notify();
@@ -1086,7 +1086,7 @@ void __init timekeeping_init(void)
ntp_clear();
clock = clocksource_get_next();
- clocksource_calculate_interval(clock, tick_nsec);
+ clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
clock->cycle_last = clocksource_read(clock);
xtime.tv_sec = sec;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists