aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2013-02-01 05:23:45 -0500
committerIngo Molnar <mingo@kernel.org>2013-02-03 06:01:29 -0500
commit0231bb5336758426b44ccd798ccd3c5419c95d58 (patch)
treea2b584263ace5acfda61830fb57591d49fdad34c /kernel
parent923d8697e24847000490c187de1aeaca622611a3 (diff)
perf: Fix event group context move
When we have group with mixed events (hw/sw) we want to end up with group leader being in hw context. So if group leader is initialy sw event, we move all the events under hw context. The move is done for each event by removing it from its context and adding it back into proper one. As a part of the removal the event is automatically disabled, which is not what we want at this stage of creating groups. The fix is to initialize event state after removal from sw context. This fix resulted from the following discussion: http://thread.gmane.org/gmane.linux.kernel.perf.user/1144 Reported-by: Andreas Hollmann <hollmann@in.tum.de> Signed-off-by: Jiri Olsa <jolsa@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Cc: Vince Weaver <vince@deater.net> Link: http://lkml.kernel.org/r/1359714225-4231-1-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 301079d06f24..7b6646a8c067 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -908,6 +908,15 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
908} 908}
909 909
910/* 910/*
911 * Initialize event state based on the perf_event_attr::disabled.
912 */
913static inline void perf_event__state_init(struct perf_event *event)
914{
915 event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF :
916 PERF_EVENT_STATE_INACTIVE;
917}
918
919/*
911 * Called at perf_event creation and when events are attached/detached from a 920 * Called at perf_event creation and when events are attached/detached from a
912 * group. 921 * group.
913 */ 922 */
@@ -6179,8 +6188,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
6179 event->overflow_handler = overflow_handler; 6188 event->overflow_handler = overflow_handler;
6180 event->overflow_handler_context = context; 6189 event->overflow_handler_context = context;
6181 6190
6182 if (attr->disabled) 6191 perf_event__state_init(event);
6183 event->state = PERF_EVENT_STATE_OFF;
6184 6192
6185 pmu = NULL; 6193 pmu = NULL;
6186 6194
@@ -6609,9 +6617,17 @@ SYSCALL_DEFINE5(perf_event_open,
6609 6617
6610 mutex_lock(&gctx->mutex); 6618 mutex_lock(&gctx->mutex);
6611 perf_remove_from_context(group_leader); 6619 perf_remove_from_context(group_leader);
6620
6621 /*
6622 * Removing from the context ends up with disabled
6623 * event. What we want here is event in the initial
6624 * startup state, ready to be add into new context.
6625 */
6626 perf_event__state_init(group_leader);
6612 list_for_each_entry(sibling, &group_leader->sibling_list, 6627 list_for_each_entry(sibling, &group_leader->sibling_list,
6613 group_entry) { 6628 group_entry) {
6614 perf_remove_from_context(sibling); 6629 perf_remove_from_context(sibling);
6630 perf_event__state_init(sibling);
6615 put_ctx(gctx); 6631 put_ctx(gctx);
6616 } 6632 }
6617 mutex_unlock(&gctx->mutex); 6633 mutex_unlock(&gctx->mutex);