aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/clocksource.c
diff options
context:
space:
mode:
authorJon Hunter <jon-hunter@ti.com>2009-08-18 13:45:10 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-11-13 14:46:24 -0500
commit98962465ed9e6ea99c38e0af63fe1dcb5a79dc25 (patch)
treef3f69ad8f6cd47e72a75da6de49eb3402f15cd9b /kernel/time/clocksource.c
parent529eaccd900a59724619b4a6ef6579fd518d5218 (diff)
nohz: Prevent clocksource wrapping during idle
The dynamic tick allows the kernel to sleep for periods longer than a single tick, but it does not limit the sleep time currently. In the worst case the kernel could sleep longer than the wrap around time of the time keeping clock source which would result in losing track of time. Prevent this by limiting it to the safe maximum sleep time of the current time keeping clock source. The value is calculated when the clock source is registered. [ tglx: simplified the code a bit and massaged the commit msg ] Signed-off-by: Jon Hunter <jon-hunter@ti.com> Cc: John Stultz <johnstul@us.ibm.com> LKML-Reference: <1250617512-23567-2-git-send-email-jon-hunter@ti.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r--kernel/time/clocksource.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 407c0894ef3..b65b242f04d 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -469,6 +469,47 @@ void clocksource_touch_watchdog(void)
469#ifdef CONFIG_GENERIC_TIME 469#ifdef CONFIG_GENERIC_TIME
470 470
471/** 471/**
472 * clocksource_max_deferment - Returns max time the clocksource can be deferred
473 * @cs: Pointer to clocksource
474 *
475 */
476static u64 clocksource_max_deferment(struct clocksource *cs)
477{
478 u64 max_nsecs, max_cycles;
479
480 /*
481 * Calculate the maximum number of cycles that we can pass to the
482 * cyc2ns function without overflowing a 64-bit signed result. The
483 * maximum number of cycles is equal to ULLONG_MAX/cs->mult which
484 * is equivalent to the below.
485 * max_cycles < (2^63)/cs->mult
486 * max_cycles < 2^(log2((2^63)/cs->mult))
487 * max_cycles < 2^(log2(2^63) - log2(cs->mult))
488 * max_cycles < 2^(63 - log2(cs->mult))
489 * max_cycles < 1 << (63 - log2(cs->mult))
490 * Please note that we add 1 to the result of the log2 to account for
491 * any rounding errors, ensure the above inequality is satisfied and
492 * no overflow will occur.
493 */
494 max_cycles = 1ULL << (63 - (ilog2(cs->mult) + 1));
495
496 /*
497 * The actual maximum number of cycles we can defer the clocksource is
498 * determined by the minimum of max_cycles and cs->mask.
499 */
500 max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
501 max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift);
502
503 /*
504 * To ensure that the clocksource does not wrap whilst we are idle,
505 * limit the time the clocksource can be deferred by 12.5%. Please
506 * note a margin of 12.5% is used because this can be computed with
507 * a shift, versus say 10% which would require division.
508 */
509 return max_nsecs - (max_nsecs >> 5);
510}
511
512/**
472 * clocksource_select - Select the best clocksource available 513 * clocksource_select - Select the best clocksource available
473 * 514 *
474 * Private function. Must hold clocksource_mutex when called. 515 * Private function. Must hold clocksource_mutex when called.
@@ -564,6 +605,9 @@ static void clocksource_enqueue(struct clocksource *cs)
564 */ 605 */
565int clocksource_register(struct clocksource *cs) 606int clocksource_register(struct clocksource *cs)
566{ 607{
608 /* calculate max idle time permitted for this clocksource */
609 cs->max_idle_ns = clocksource_max_deferment(cs);
610
567 mutex_lock(&clocksource_mutex); 611 mutex_lock(&clocksource_mutex);
568 clocksource_enqueue(cs); 612 clocksource_enqueue(cs);
569 clocksource_select(); 613 clocksource_select();