mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-24 23:19:31 -05:00
92 lines
3.0 KiB
Diff
92 lines
3.0 KiB
Diff
From c3c87e770458aa004bd7ed3f29945ff436fd6511 Mon Sep 17 00:00:00 2001
|
|
From: Peter Zijlstra <peterz@infradead.org>
|
|
Date: Fri, 23 Jan 2015 11:19:48 +0100
|
|
Subject: perf: Tighten (and fix) the grouping condition
|
|
|
|
The fix from 9fc81d87420d ("perf: Fix events installation during
|
|
moving group") was incomplete in that it failed to recognise that
|
|
creating a group with events for different CPUs is semantically
|
|
broken -- they cannot be co-scheduled.
|
|
|
|
Furthermore, it leads to real breakage where, when we create an event
|
|
for CPU Y and then migrate it to form a group on CPU X, the code gets
|
|
confused where the counter is programmed -- triggered in practice
|
|
as well by me via the perf fuzzer.
|
|
|
|
Fix this by tightening the rules for creating groups. Only allow
|
|
grouping of counters that can be co-scheduled in the same context.
|
|
This means for the same task and/or the same cpu.
|
|
|
|
Fixes: 9fc81d87420d ("perf: Fix events installation during moving group")
|
|
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
|
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
|
|
Cc: Jiri Olsa <jolsa@redhat.com>
|
|
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Link: http://lkml.kernel.org/r/20150123125834.090683288@infradead.org
|
|
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
|
---
|
|
include/linux/perf_event.h | 6 ------
|
|
kernel/events/core.c | 15 +++++++++++++--
|
|
2 files changed, 13 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
|
|
index 4f7a61c..664de5a 100644
|
|
--- a/include/linux/perf_event.h
|
|
+++ b/include/linux/perf_event.h
|
|
@@ -450,11 +450,6 @@ struct perf_event {
|
|
#endif /* CONFIG_PERF_EVENTS */
|
|
};
|
|
|
|
-enum perf_event_context_type {
|
|
- task_context,
|
|
- cpu_context,
|
|
-};
|
|
-
|
|
/**
|
|
* struct perf_event_context - event context structure
|
|
*
|
|
@@ -462,7 +457,6 @@ enum perf_event_context_type {
|
|
*/
|
|
struct perf_event_context {
|
|
struct pmu *pmu;
|
|
- enum perf_event_context_type type;
|
|
/*
|
|
* Protect the states of the events in the list,
|
|
* nr_active, and the list:
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index 882f835a..19efcf1 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -6776,7 +6776,6 @@ skip_type:
|
|
__perf_event_init_context(&cpuctx->ctx);
|
|
lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex);
|
|
lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock);
|
|
- cpuctx->ctx.type = cpu_context;
|
|
cpuctx->ctx.pmu = pmu;
|
|
|
|
__perf_cpu_hrtimer_init(cpuctx, cpu);
|
|
@@ -7420,7 +7419,19 @@ SYSCALL_DEFINE5(perf_event_open,
|
|
* task or CPU context:
|
|
*/
|
|
if (move_group) {
|
|
- if (group_leader->ctx->type != ctx->type)
|
|
+ /*
|
|
+ * Make sure we're both on the same task, or both
|
|
+ * per-cpu events.
|
|
+ */
|
|
+ if (group_leader->ctx->task != ctx->task)
|
|
+ goto err_context;
|
|
+
|
|
+ /*
|
|
+ * Make sure we're both events for the same CPU;
|
|
+ * grouping events for different CPUs is broken; since
|
|
+ * you can never concurrently schedule them anyhow.
|
|
+ */
|
|
+ if (group_leader->cpu != event->cpu)
|
|
goto err_context;
|
|
} else {
|
|
if (group_leader->ctx != ctx)
|
|
--
|
|
cgit v1.1
|
|
|