diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-08-14 09:47:30 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-08-15 04:55:46 -0400 |
commit | 75c5158f70c065b9704b924503d96e8297838f79 (patch) | |
tree | 74b02ba1f13aaf8292bd472a8a197ac900ff20e7 /kernel/time/timekeeping.c | |
parent | 2ba2a3054fdffc8e6452f4ee120760322a6fbd43 (diff) |
timekeeping: Update clocksource with stop_machine
update_wall_time calls change_clocksource HZ times per second to check
if a new clock source is available. In close to 100% of all calls
there is no new clock. Replace the tick based check by an update done
with stop_machine.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Acked-by: John Stultz <johnstul@us.ibm.com>
Cc: Daniel Walker <dwalker@fifo99.com>
LKML-Reference: <20090814134810.711836357@de.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r-- | kernel/time/timekeeping.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 27ae01b596b7..41579e7fcf9d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/time.h> | 19 | #include <linux/time.h> |
20 | #include <linux/tick.h> | 20 | #include <linux/tick.h> |
21 | #include <linux/stop_machine.h> | ||
21 | 22 | ||
22 | /* Structure holding internal timekeeping values. */ | 23 | /* Structure holding internal timekeeping values. */ |
23 | struct timekeeper { | 24 | struct timekeeper { |
@@ -179,6 +180,7 @@ void timekeeping_leap_insert(int leapsecond) | |||
179 | } | 180 | } |
180 | 181 | ||
181 | #ifdef CONFIG_GENERIC_TIME | 182 | #ifdef CONFIG_GENERIC_TIME |
183 | |||
182 | /** | 184 | /** |
183 | * timekeeping_forward_now - update clock to the current time | 185 | * timekeeping_forward_now - update clock to the current time |
184 | * | 186 | * |
@@ -351,31 +353,40 @@ EXPORT_SYMBOL(do_settimeofday); | |||
351 | * | 353 | * |
352 | * Accumulates current time interval and initializes new clocksource | 354 | * Accumulates current time interval and initializes new clocksource |
353 | */ | 355 | */ |
354 | static void change_clocksource(void) | 356 | static int change_clocksource(void *data) |
355 | { | 357 | { |
356 | struct clocksource *new, *old; | 358 | struct clocksource *new, *old; |
357 | 359 | ||
358 | new = clocksource_get_next(); | 360 | new = (struct clocksource *) data; |
359 | |||
360 | if (!new || timekeeper.clock == new) | ||
361 | return; | ||
362 | 361 | ||
363 | timekeeping_forward_now(); | 362 | timekeeping_forward_now(); |
363 | if (!new->enable || new->enable(new) == 0) { | ||
364 | old = timekeeper.clock; | ||
365 | timekeeper_setup_internals(new); | ||
366 | if (old->disable) | ||
367 | old->disable(old); | ||
368 | } | ||
369 | return 0; | ||
370 | } | ||
364 | 371 | ||
365 | if (new->enable && !new->enable(new)) | 372 | /** |
373 | * timekeeping_notify - Install a new clock source | ||
374 | * @clock: pointer to the clock source | ||
375 | * | ||
376 | * This function is called from clocksource.c after a new, better clock | ||
377 | * source has been registered. The caller holds the clocksource_mutex. | ||
378 | */ | ||
379 | void timekeeping_notify(struct clocksource *clock) | ||
380 | { | ||
381 | if (timekeeper.clock == clock) | ||
366 | return; | 382 | return; |
367 | 383 | stop_machine(change_clocksource, clock, NULL); | |
368 | old = timekeeper.clock; | ||
369 | timekeeper_setup_internals(new); | ||
370 | |||
371 | if (old->disable) | ||
372 | old->disable(old); | ||
373 | |||
374 | tick_clock_notify(); | 384 | tick_clock_notify(); |
375 | } | 385 | } |
386 | |||
376 | #else /* GENERIC_TIME */ | 387 | #else /* GENERIC_TIME */ |
388 | |||
377 | static inline void timekeeping_forward_now(void) { } | 389 | static inline void timekeeping_forward_now(void) { } |
378 | static inline void change_clocksource(void) { } | ||
379 | 390 | ||
380 | /** | 391 | /** |
381 | * ktime_get - get the monotonic time in ktime_t format | 392 | * ktime_get - get the monotonic time in ktime_t format |
@@ -416,6 +427,7 @@ void ktime_get_ts(struct timespec *ts) | |||
416 | ts->tv_nsec + tomono.tv_nsec); | 427 | ts->tv_nsec + tomono.tv_nsec); |
417 | } | 428 | } |
418 | EXPORT_SYMBOL_GPL(ktime_get_ts); | 429 | EXPORT_SYMBOL_GPL(ktime_get_ts); |
430 | |||
419 | #endif /* !GENERIC_TIME */ | 431 | #endif /* !GENERIC_TIME */ |
420 | 432 | ||
421 | /** | 433 | /** |
@@ -773,7 +785,6 @@ void update_wall_time(void) | |||
773 | update_xtime_cache(nsecs); | 785 | update_xtime_cache(nsecs); |
774 | 786 | ||
775 | /* check to see if there is a new clocksource to use */ | 787 | /* check to see if there is a new clocksource to use */ |
776 | change_clocksource(); | ||
777 | update_vsyscall(&xtime, timekeeper.clock); | 788 | update_vsyscall(&xtime, timekeeper.clock); |
778 | } | 789 | } |
779 | 790 | ||