diff options
author | Eric B Munson <emunson@mgebm.net> | 2011-06-23 16:34:38 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-08-31 09:56:29 -0400 |
commit | 7f310a5d4e8525ac0cc2f58c973d2100ce034410 (patch) | |
tree | 7e61573e73b80d65d29b259c7d1a228038a4439e | |
parent | a8d757ef076f0f95f13a918808824058de25b3eb (diff) |
perf_event: Fix broken calc_timer_values()
We detected a serious issue with PERF_SAMPLE_READ and
timing information when events were being multiplexing.
Samples would have time_running > time_enabled. That
was easy to reproduce with a libpfm4 example (ran 3
times to cause multiplexing on Core 2):
$ syst_smpl -e uops_retired:freq=1 &
$ syst_smpl -e uops_retired:freq=1 &
$ syst_smpl -e uops_retired:freq=1 &
IIP:0x0000000040062d ... PERIOD:2355332948 ENA=40144625315 RUN=60014875184
syst_smpl: WARNING: time_running > time_enabled
63277537998 uops_retired:freq=1 , scaled
The bug was not present in kernel up to (and including) 3.0. It turns
out the bug was introduced by the following commit:
commit c4794295917ebeda8013b6cb9c8d71ab4f74a1fa
events: Move lockless timer calculation into helper function
The parameters of the function got reversed yet the call sites
were not updated to reflect the change. That lead to time_running
and time_enabled being swapped. That had no effect when there was
no multiplexing because in that case time_running = time_enabled
but it would show up in any other scenario.
Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20110829124112.GA4828@quad
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/events/core.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 45847fbb599a..0f857782d06f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -3396,8 +3396,8 @@ static int perf_event_index(struct perf_event *event) | |||
3396 | } | 3396 | } |
3397 | 3397 | ||
3398 | static void calc_timer_values(struct perf_event *event, | 3398 | static void calc_timer_values(struct perf_event *event, |
3399 | u64 *running, | 3399 | u64 *enabled, |
3400 | u64 *enabled) | 3400 | u64 *running) |
3401 | { | 3401 | { |
3402 | u64 now, ctx_time; | 3402 | u64 now, ctx_time; |
3403 | 3403 | ||