From 6fe7cf6a1b4b5defd553338afeb05471efd213b5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 6 Apr 2013 10:10:27 +0200 Subject: [PATCH] --- yaml --- r: 362524 b: refs/heads/master c: a1cbcaa9ea87b87a96b9fc465951dcf36e459ca2 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/kernel/sched/clock.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index a132cefac022..5d402329c76f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 383efcd00053ec40023010ce5034bd702e7ab373 +refs/heads/master: a1cbcaa9ea87b87a96b9fc465951dcf36e459ca2 diff --git a/trunk/kernel/sched/clock.c b/trunk/kernel/sched/clock.c index c685e31492df..c3ae1446461c 100644 --- a/trunk/kernel/sched/clock.c +++ b/trunk/kernel/sched/clock.c @@ -176,10 +176,36 @@ static u64 sched_clock_remote(struct sched_clock_data *scd) u64 this_clock, remote_clock; u64 *ptr, old_val, val; +#if BITS_PER_LONG != 64 +again: + /* + * Careful here: The local and the remote clock values need to + * be read out atomic as we need to compare the values and + * then update either the local or the remote side. So the + * cmpxchg64 below only protects one readout. + * + * We must reread via sched_clock_local() in the retry case on + * 32bit as an NMI could use sched_clock_local() via the + * tracer and hit between the readout of + * the low32bit and the high 32bit portion. + */ + this_clock = sched_clock_local(my_scd); + /* + * We must enforce atomic readout on 32bit, otherwise the + * update on the remote cpu can hit inbetween the readout of + * the low32bit and the high 32bit portion. + */ + remote_clock = cmpxchg64(&scd->clock, 0, 0); +#else + /* + * On 64bit the read of [my]scd->clock is atomic versus the + * update, so we can avoid the above 32bit dance. + */ sched_clock_local(my_scd); again: this_clock = my_scd->clock; remote_clock = scd->clock; +#endif /* * Use the opportunity that we have both locks