diff options
author | john stultz <johnstul@us.ibm.com> | 2007-02-16 04:27:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 11:13:56 -0500 |
commit | f4304ab21513b834c8fe3403927c60c2b81a72d7 (patch) | |
tree | 212c8fa327d9cf3f29cccf172f0707a3eb6524f8 | |
parent | 771ee3b04eaac6184312825eb600b4c598f027a5 (diff) |
[PATCH] HZ free ntp
Distangle the NTP update from HZ. This is necessary for dynamic tick enabled
kernels.
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/timex.h | 7 | ||||
-rw-r--r-- | kernel/hrtimer.c | 11 | ||||
-rw-r--r-- | kernel/time/ntp.c | 30 | ||||
-rw-r--r-- | kernel/timer.c | 4 |
4 files changed, 36 insertions, 16 deletions
diff --git a/include/linux/timex.h b/include/linux/timex.h index 9a24e500c311..da929dbbea2a 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h | |||
@@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec) | |||
286 | 286 | ||
287 | #define TICK_LENGTH_SHIFT 32 | 287 | #define TICK_LENGTH_SHIFT 32 |
288 | 288 | ||
289 | #ifdef CONFIG_NO_HZ | ||
290 | #define NTP_INTERVAL_FREQ (2) | ||
291 | #else | ||
292 | #define NTP_INTERVAL_FREQ (HZ) | ||
293 | #endif | ||
294 | #define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) | ||
295 | |||
289 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ | 296 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ |
290 | extern u64 current_tick_length(void); | 297 | extern u64 current_tick_length(void); |
291 | 298 | ||
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f44e499e8fca..80666f6cd4f9 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -128,15 +128,20 @@ EXPORT_SYMBOL_GPL(ktime_get_ts); | |||
128 | static void hrtimer_get_softirq_time(struct hrtimer_base *base) | 128 | static void hrtimer_get_softirq_time(struct hrtimer_base *base) |
129 | { | 129 | { |
130 | ktime_t xtim, tomono; | 130 | ktime_t xtim, tomono; |
131 | struct timespec xts; | ||
131 | unsigned long seq; | 132 | unsigned long seq; |
132 | 133 | ||
133 | do { | 134 | do { |
134 | seq = read_seqbegin(&xtime_lock); | 135 | seq = read_seqbegin(&xtime_lock); |
135 | xtim = timespec_to_ktime(xtime); | 136 | #ifdef CONFIG_NO_HZ |
136 | tomono = timespec_to_ktime(wall_to_monotonic); | 137 | getnstimeofday(&xts); |
137 | 138 | #else | |
139 | xts = xtime; | ||
140 | #endif | ||
138 | } while (read_seqretry(&xtime_lock, seq)); | 141 | } while (read_seqretry(&xtime_lock, seq)); |
139 | 142 | ||
143 | xtim = timespec_to_ktime(xts); | ||
144 | tomono = timespec_to_ktime(wall_to_monotonic); | ||
140 | base[CLOCK_REALTIME].softirq_time = xtim; | 145 | base[CLOCK_REALTIME].softirq_time = xtim; |
141 | base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); | 146 | base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); |
142 | } | 147 | } |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 3afeaa3a73f9..eb12509e00bd 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base; | |||
24 | 24 | ||
25 | #define MAX_TICKADJ 500 /* microsecs */ | 25 | #define MAX_TICKADJ 500 /* microsecs */ |
26 | #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ | 26 | #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ |
27 | TICK_LENGTH_SHIFT) / HZ) | 27 | TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ) |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * phase-lock loop variables | 30 | * phase-lock loop variables |
@@ -46,13 +46,17 @@ long time_adjust; | |||
46 | 46 | ||
47 | static void ntp_update_frequency(void) | 47 | static void ntp_update_frequency(void) |
48 | { | 48 | { |
49 | tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; | 49 | u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) |
50 | tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; | 50 | << TICK_LENGTH_SHIFT; |
51 | tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); | 51 | second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; |
52 | second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); | ||
52 | 53 | ||
53 | do_div(tick_length_base, HZ); | 54 | tick_length_base = second_length; |
54 | 55 | ||
55 | tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT; | 56 | do_div(second_length, HZ); |
57 | tick_nsec = second_length >> TICK_LENGTH_SHIFT; | ||
58 | |||
59 | do_div(tick_length_base, NTP_INTERVAL_FREQ); | ||
56 | } | 60 | } |
57 | 61 | ||
58 | /** | 62 | /** |
@@ -162,7 +166,7 @@ void second_overflow(void) | |||
162 | tick_length -= MAX_TICKADJ_SCALED; | 166 | tick_length -= MAX_TICKADJ_SCALED; |
163 | } else { | 167 | } else { |
164 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / | 168 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / |
165 | HZ) << TICK_LENGTH_SHIFT; | 169 | NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT; |
166 | time_adjust = 0; | 170 | time_adjust = 0; |
167 | } | 171 | } |
168 | } | 172 | } |
@@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc) | |||
239 | result = -EINVAL; | 243 | result = -EINVAL; |
240 | goto leave; | 244 | goto leave; |
241 | } | 245 | } |
242 | time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC); | 246 | time_freq = ((s64)txc->freq * NSEC_PER_USEC) |
247 | >> (SHIFT_USEC - SHIFT_NSEC); | ||
243 | } | 248 | } |
244 | 249 | ||
245 | if (txc->modes & ADJ_MAXERROR) { | 250 | if (txc->modes & ADJ_MAXERROR) { |
@@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc) | |||
309 | freq_adj += time_freq; | 314 | freq_adj += time_freq; |
310 | freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); | 315 | freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); |
311 | time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); | 316 | time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); |
312 | time_offset = (time_offset / HZ) << SHIFT_UPDATE; | 317 | time_offset = (time_offset / NTP_INTERVAL_FREQ) |
318 | << SHIFT_UPDATE; | ||
313 | } /* STA_PLL */ | 319 | } /* STA_PLL */ |
314 | } /* txc->modes & ADJ_OFFSET */ | 320 | } /* txc->modes & ADJ_OFFSET */ |
315 | if (txc->modes & ADJ_TICK) | 321 | if (txc->modes & ADJ_TICK) |
@@ -324,8 +330,10 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) | |||
324 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) | 330 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) |
325 | txc->offset = save_adjust; | 331 | txc->offset = save_adjust; |
326 | else | 332 | else |
327 | txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000; | 333 | txc->offset = shift_right(time_offset, SHIFT_UPDATE) |
328 | txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC); | 334 | * NTP_INTERVAL_FREQ / 1000; |
335 | txc->freq = (time_freq / NSEC_PER_USEC) | ||
336 | << (SHIFT_USEC - SHIFT_NSEC); | ||
329 | txc->maxerror = time_maxerror; | 337 | txc->maxerror = time_maxerror; |
330 | txc->esterror = time_esterror; | 338 | txc->esterror = time_esterror; |
331 | txc->status = time_status; | 339 | txc->status = time_status; |
diff --git a/kernel/timer.c b/kernel/timer.c index 4902181e10e6..4f9cc2a48beb 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -890,7 +890,7 @@ void __init timekeeping_init(void) | |||
890 | ntp_clear(); | 890 | ntp_clear(); |
891 | 891 | ||
892 | clock = clocksource_get_next(); | 892 | clock = clocksource_get_next(); |
893 | clocksource_calculate_interval(clock, tick_nsec); | 893 | clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); |
894 | clock->cycle_last = clocksource_read(clock); | 894 | clock->cycle_last = clocksource_read(clock); |
895 | 895 | ||
896 | write_sequnlock_irqrestore(&xtime_lock, flags); | 896 | write_sequnlock_irqrestore(&xtime_lock, flags); |
@@ -1092,7 +1092,7 @@ static void update_wall_time(void) | |||
1092 | if (change_clocksource()) { | 1092 | if (change_clocksource()) { |
1093 | clock->error = 0; | 1093 | clock->error = 0; |
1094 | clock->xtime_nsec = 0; | 1094 | clock->xtime_nsec = 0; |
1095 | clocksource_calculate_interval(clock, tick_nsec); | 1095 | clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); |
1096 | } | 1096 | } |
1097 | } | 1097 | } |
1098 | 1098 | ||