aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_event.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-09-07 11:34:50 -0400
committerIngo Molnar <mingo@elte.hu>2010-09-09 14:46:34 -0400
commit89a1e18731959e9953fae15ddc1a983eb15a4f19 (patch)
tree5a52e77acb23f47254c94e23eb6ed35a422fce1d /kernel/perf_event.c
parent8dc85d547285668e509f86c177bcd4ea055bcaaf (diff)
perf: Provide a separate task context for swevents
Since software events are always schedulable, mixing them up with hardware events (who are not) can lead to funny scheduling oddities. Giving them their own context solves this. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: paulus <paulus@samba.org> Cc: stephane eranian <eranian@googlemail.com> Cc: Robert Richter <robert.richter@amd.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Lin Ming <ming.m.lin@intel.com> Cc: Yanmin <yanmin_zhang@linux.intel.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r--kernel/perf_event.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 7223ea875861..357ee8d5e8ae 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4709,6 +4709,8 @@ static int perf_swevent_init(struct perf_event *event)
4709} 4709}
4710 4710
4711static struct pmu perf_swevent = { 4711static struct pmu perf_swevent = {
4712 .task_ctx_nr = perf_sw_context,
4713
4712 .event_init = perf_swevent_init, 4714 .event_init = perf_swevent_init,
4713 .add = perf_swevent_add, 4715 .add = perf_swevent_add,
4714 .del = perf_swevent_del, 4716 .del = perf_swevent_del,
@@ -4800,6 +4802,8 @@ static int perf_tp_event_init(struct perf_event *event)
4800} 4802}
4801 4803
4802static struct pmu perf_tracepoint = { 4804static struct pmu perf_tracepoint = {
4805 .task_ctx_nr = perf_sw_context,
4806
4803 .event_init = perf_tp_event_init, 4807 .event_init = perf_tp_event_init,
4804 .add = perf_trace_add, 4808 .add = perf_trace_add,
4805 .del = perf_trace_del, 4809 .del = perf_trace_del,
@@ -4988,6 +4992,8 @@ static int cpu_clock_event_init(struct perf_event *event)
4988} 4992}
4989 4993
4990static struct pmu perf_cpu_clock = { 4994static struct pmu perf_cpu_clock = {
4995 .task_ctx_nr = perf_sw_context,
4996
4991 .event_init = cpu_clock_event_init, 4997 .event_init = cpu_clock_event_init,
4992 .add = cpu_clock_event_add, 4998 .add = cpu_clock_event_add,
4993 .del = cpu_clock_event_del, 4999 .del = cpu_clock_event_del,
@@ -5063,6 +5069,8 @@ static int task_clock_event_init(struct perf_event *event)
5063} 5069}
5064 5070
5065static struct pmu perf_task_clock = { 5071static struct pmu perf_task_clock = {
5072 .task_ctx_nr = perf_sw_context,
5073
5066 .event_init = task_clock_event_init, 5074 .event_init = task_clock_event_init,
5067 .add = task_clock_event_add, 5075 .add = task_clock_event_add,
5068 .del = task_clock_event_del, 5076 .del = task_clock_event_del,
@@ -5490,6 +5498,7 @@ SYSCALL_DEFINE5(perf_event_open,
5490 struct perf_event_context *ctx; 5498 struct perf_event_context *ctx;
5491 struct file *event_file = NULL; 5499 struct file *event_file = NULL;
5492 struct file *group_file = NULL; 5500 struct file *group_file = NULL;
5501 struct pmu *pmu;
5493 int event_fd; 5502 int event_fd;
5494 int fput_needed = 0; 5503 int fput_needed = 0;
5495 int err; 5504 int err;
@@ -5522,20 +5531,11 @@ SYSCALL_DEFINE5(perf_event_open,
5522 goto err_fd; 5531 goto err_fd;
5523 } 5532 }
5524 5533
5525 /*
5526 * Get the target context (task or percpu):
5527 */
5528 ctx = find_get_context(event->pmu, pid, cpu);
5529 if (IS_ERR(ctx)) {
5530 err = PTR_ERR(ctx);
5531 goto err_alloc;
5532 }
5533
5534 if (group_fd != -1) { 5534 if (group_fd != -1) {
5535 group_leader = perf_fget_light(group_fd, &fput_needed); 5535 group_leader = perf_fget_light(group_fd, &fput_needed);
5536 if (IS_ERR(group_leader)) { 5536 if (IS_ERR(group_leader)) {
5537 err = PTR_ERR(group_leader); 5537 err = PTR_ERR(group_leader);
5538 goto err_context; 5538 goto err_alloc;
5539 } 5539 }
5540 group_file = group_leader->filp; 5540 group_file = group_leader->filp;
5541 if (flags & PERF_FLAG_FD_OUTPUT) 5541 if (flags & PERF_FLAG_FD_OUTPUT)
@@ -5545,6 +5545,23 @@ SYSCALL_DEFINE5(perf_event_open,
5545 } 5545 }
5546 5546
5547 /* 5547 /*
5548 * Special case software events and allow them to be part of
5549 * any hardware group.
5550 */
5551 pmu = event->pmu;
5552 if ((pmu->task_ctx_nr == perf_sw_context) && group_leader)
5553 pmu = group_leader->pmu;
5554
5555 /*
5556 * Get the target context (task or percpu):
5557 */
5558 ctx = find_get_context(pmu, pid, cpu);
5559 if (IS_ERR(ctx)) {
5560 err = PTR_ERR(ctx);
5561 goto err_group_fd;
5562 }
5563
5564 /*
5548 * Look up the group leader (we will attach this event to it): 5565 * Look up the group leader (we will attach this event to it):
5549 */ 5566 */
5550 if (group_leader) { 5567 if (group_leader) {
@@ -5605,8 +5622,9 @@ SYSCALL_DEFINE5(perf_event_open,
5605 return event_fd; 5622 return event_fd;
5606 5623
5607err_context: 5624err_context:
5608 fput_light(group_file, fput_needed);
5609 put_ctx(ctx); 5625 put_ctx(ctx);
5626err_group_fd:
5627 fput_light(group_file, fput_needed);
5610err_alloc: 5628err_alloc:
5611 free_event(event); 5629 free_event(event);
5612err_fd: 5630err_fd: