[PATCH 01/16] ARM: Remove dependency of plat-orion time code on mach directory includes.
Nicolas Pitre
nico at fluxnic.net
Tue Dec 14 21:44:14 EST 2010
On Wed, 15 Dec 2010, Lennert Buytenhek wrote:
> This patch makes the various mach dirs that use the plat-orion time
> code pass in timer and bridge addresses explicitly, instead of having
> plat-orion get those values by including a mach dir include file --
> the latter mechanism is problematic if you want to support multiple
> ARM platforms in the same kernel image.
>
> Signed-off-by: Lennert Buytenhek <buytenh at secretlab.ca>
[...]
> @@ -57,8 +71,11 @@ static unsigned long tclk2ns_scale;
>
> unsigned long long sched_clock(void)
> {
> - unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL));
> - return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
> + unsigned long val;
> +
> + val = ~readl(timer_base + TIMER0_VAL_OFF);
> +
> + return (cnt32_to_63(val) * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
> }
This is wrong.
The implementation of cnt32_to_63() looks like this:
#define cnt32_to_63(cnt_lo) \
({ \
static u32 __m_cnt_hi; \
union cnt32_to_63 __x; \
__x.hi = __m_cnt_hi; \
smp_rmb(); \
__x.lo = (cnt_lo); \
[...]
Notice the smp_rmb() _before_ the cnt_lo argument is evaluated, and
_after_ __m_cnt_hi is retrieved. Tthis ordering is important for the
lockless algorithm used here, otherwise a racing thread could make the
hardware counter look like it went backward, or that it actually jumped
ahead almost one full period. If you are caching the hardware counter
value in a variable then you are defeating the algorithm.
I realize that this constraint is not properly documented in
cnt32_to_63.h so I should fix that.
Nicolas
More information about the linux-arm-kernel
mailing list