diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-04-21 10:57:33 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-04-21 10:57:33 +0200 |
commit | 73e21ce28d8d2b75140b742b01373c3a085ecc52 (patch) | |
tree | add380154271f9a68be4099590f912b4ab4bed9f /kernel/sched/clock.c | |
parent | b5210b2a34bae35fc00675462333af45676d727c (diff) | |
parent | f1923820c447e986a9da0fc6bf60c1dccdf0408e (diff) | |
download | linux-73e21ce28d8d2b75140b742b01373c3a085ecc52.tar.bz2 |
Merge branch 'perf/urgent' into perf/core
Conflicts:
arch/x86/kernel/cpu/perf_event_intel.c
Merge in the latest fixes before applying new patches, resolve the conflict.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/clock.c')
-rw-r--r-- | kernel/sched/clock.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index c685e31492df..c3ae1446461c 100644 --- a/kernel/sched/clock.c +++ b/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 |