summaryrefslogtreecommitdiff
path: root/kernel/events
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2011-06-23 20:34:38 (GMT)
committerIngo Molnar <mingo@elte.hu>2011-08-31 13:56:29 (GMT)
commit7f310a5d4e8525ac0cc2f58c973d2100ce034410 (patch)
tree7e61573e73b80d65d29b259c7d1a228038a4439e /kernel/events
parenta8d757ef076f0f95f13a918808824058de25b3eb (diff)
downloadlinux-7f310a5d4e8525ac0cc2f58c973d2100ce034410.tar.xz
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>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 45847fb..0f85778 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3396,8 +3396,8 @@ static int perf_event_index(struct perf_event *event)
}
static void calc_timer_values(struct perf_event *event,
- u64 *running,
- u64 *enabled)
+ u64 *enabled,
+ u64 *running)
{
u64 now, ctx_time;