diff options
author | John Stultz <john.stultz@linaro.org> | 2012-09-04 12:42:27 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2012-09-24 12:38:05 -0400 |
commit | b3c869d35b9b014f63ac0beacd31c57372084d01 (patch) | |
tree | ef60ae8b88a063dbe4d3894220223dd1fb39e639 /include/linux | |
parent | 7916a1f14f06ac93e4cec81139fe4f7ec13b572c (diff) | |
download | linux-stable-b3c869d35b9b014f63ac0beacd31c57372084d01.tar.gz linux-stable-b3c869d35b9b014f63ac0beacd31c57372084d01.tar.bz2 linux-stable-b3c869d35b9b014f63ac0beacd31c57372084d01.zip |
jiffies: Remove compile time assumptions about CLOCK_TICK_RATE
CLOCK_TICK_RATE is used to accurately caclulate exactly how
a tick will be at a given HZ.
This is useful, because while we'd expect NSEC_PER_SEC/HZ,
the underlying hardware will have some granularity limit,
so we won't be able to have exactly HZ ticks per second.
This slight error can cause timekeeping quality problems
when using the jiffies or other jiffies driven clocksources.
Thus we currently use compile time CLOCK_TICK_RATE value to
generate SHIFTED_HZ and NSEC_PER_JIFFIES, which we then use
to adjust the jiffies clocksource to correct this error.
Unfortunately though, since CLOCK_TICK_RATE is a compile
time value, and the jiffies clocksource is registered very
early during boot, there are a number of cases where there
are different possible hardware timers that have different
tick rates. This causes problems in cases like ARM where
there are numerous different types of hardware, each having
their own compile-time CLOCK_TICK_RATE, making it hard to
accurately support different hardware with a single kernel.
For the most part, this doesn't matter all that much, as not
too many systems actually utilize the jiffies or jiffies driven
clocksource. Usually there are other highres clocksources
who's granularity error is negligable.
Even so, we have some complicated calcualtions that we do
everywhere to handle these edge cases.
This patch removes the compile time SHIFTED_HZ value, and
introduces a register_refined_jiffies() function. This results
in the default jiffies clock as being assumed a perfect HZ
freq, and allows archtectures that care about jiffies accuracy
to call register_refined_jiffies() with the tick rate, specified
dynamically at boot.
This allows us, where necessary, to not have a compile time
CLOCK_TICK_RATE constant, simplifies the jiffies code, and
still provides a way to have an accurate jiffies clock.
NOTE: Since this patch does not add register_refinied_jiffies()
calls for every arch, it may cause time quality regressions
in some cases. Its likely these will not be noticable, but
if they are an issue, adding the following to the end of
setup_arch() should resolve the regression:
register_refinied_jiffies(CLOCK_TICK_RATE)
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/jiffies.h | 15 |
1 files changed, 2 insertions, 13 deletions
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 4a7e3864e80d..388edb54bfb6 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -51,21 +51,10 @@ #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) -#ifdef CLOCK_TICK_RATE -/* LATCH is used in the interval timer and ftape setup. */ -# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - -/* - * HZ is the requested value. However the CLOCK_TICK_RATE may not allow - * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy) - */ -# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) -#else -# define SHIFTED_HZ (HZ << 8) -#endif +extern int register_refined_jiffies(long clock_tick_rate); /* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ -#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8)) +#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ) /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) |