aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-06-29 11:42:35 -0400
committerIngo Molnar <mingo@elte.hu>2011-07-01 05:06:38 -0400
commit4dc0da86967d5463708631d02a70cfed5b104884 (patch)
treee09071a62f2457b710ff69df3be1bff39340a4c6 /kernel/events
parent89d6c0b5bdbb1927775584dcf532d98b3efe1477 (diff)
perf: Add context field to perf_event
The perf_event overflow handler does not receive any caller-derived argument, so many callers need to resort to looking up the perf_event in their local data structure. This is ugly and doesn't scale if a single callback services many perf_events. Fix by adding a context parameter to perf_event_create_kernel_counter() (and derived hardware breakpoints APIs) and storing it in the perf_event. The field can be accessed from the callback as event->overflow_handler_context. All callers are updated. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1309362157-6596-2-git-send-email-avi@redhat.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c21
-rw-r--r--kernel/events/hw_breakpoint.c10
2 files changed, 22 insertions, 9 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 81de28dcca8c..ba8e0f4a20e6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5745,7 +5745,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
5745 struct task_struct *task, 5745 struct task_struct *task,
5746 struct perf_event *group_leader, 5746 struct perf_event *group_leader,
5747 struct perf_event *parent_event, 5747 struct perf_event *parent_event,
5748 perf_overflow_handler_t overflow_handler) 5748 perf_overflow_handler_t overflow_handler,
5749 void *context)
5749{ 5750{
5750 struct pmu *pmu; 5751 struct pmu *pmu;
5751 struct perf_event *event; 5752 struct perf_event *event;
@@ -5803,10 +5804,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
5803#endif 5804#endif
5804 } 5805 }
5805 5806
5806 if (!overflow_handler && parent_event) 5807 if (!overflow_handler && parent_event) {
5807 overflow_handler = parent_event->overflow_handler; 5808 overflow_handler = parent_event->overflow_handler;
5809 context = parent_event->overflow_handler_context;
5810 }
5808 5811
5809 event->overflow_handler = overflow_handler; 5812 event->overflow_handler = overflow_handler;
5813 event->overflow_handler_context = context;
5810 5814
5811 if (attr->disabled) 5815 if (attr->disabled)
5812 event->state = PERF_EVENT_STATE_OFF; 5816 event->state = PERF_EVENT_STATE_OFF;
@@ -6073,7 +6077,8 @@ SYSCALL_DEFINE5(perf_event_open,
6073 } 6077 }
6074 } 6078 }
6075 6079
6076 event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, NULL); 6080 event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
6081 NULL, NULL);
6077 if (IS_ERR(event)) { 6082 if (IS_ERR(event)) {
6078 err = PTR_ERR(event); 6083 err = PTR_ERR(event);
6079 goto err_task; 6084 goto err_task;
@@ -6258,7 +6263,8 @@ err_fd:
6258struct perf_event * 6263struct perf_event *
6259perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, 6264perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
6260 struct task_struct *task, 6265 struct task_struct *task,
6261 perf_overflow_handler_t overflow_handler) 6266 perf_overflow_handler_t overflow_handler,
6267 void *context)
6262{ 6268{
6263 struct perf_event_context *ctx; 6269 struct perf_event_context *ctx;
6264 struct perf_event *event; 6270 struct perf_event *event;
@@ -6268,7 +6274,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
6268 * Get the target context (task or percpu): 6274 * Get the target context (task or percpu):
6269 */ 6275 */
6270 6276
6271 event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler); 6277 event = perf_event_alloc(attr, cpu, task, NULL, NULL,
6278 overflow_handler, context);
6272 if (IS_ERR(event)) { 6279 if (IS_ERR(event)) {
6273 err = PTR_ERR(event); 6280 err = PTR_ERR(event);
6274 goto err; 6281 goto err;
@@ -6552,7 +6559,7 @@ inherit_event(struct perf_event *parent_event,
6552 parent_event->cpu, 6559 parent_event->cpu,
6553 child, 6560 child,
6554 group_leader, parent_event, 6561 group_leader, parent_event,
6555 NULL); 6562 NULL, NULL);
6556 if (IS_ERR(child_event)) 6563 if (IS_ERR(child_event))
6557 return child_event; 6564 return child_event;
6558 get_ctx(child_ctx); 6565 get_ctx(child_ctx);
@@ -6579,6 +6586,8 @@ inherit_event(struct perf_event *parent_event,
6579 6586
6580 child_event->ctx = child_ctx; 6587 child_event->ctx = child_ctx;
6581 child_event->overflow_handler = parent_event->overflow_handler; 6588 child_event->overflow_handler = parent_event->overflow_handler;
6589 child_event->overflow_handler_context
6590 = parent_event->overflow_handler_context;
6582 6591
6583 /* 6592 /*
6584 * Precalculate sample_data sizes 6593 * Precalculate sample_data sizes
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 086adf25a55e..b7971d6f38bf 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -431,9 +431,11 @@ int register_perf_hw_breakpoint(struct perf_event *bp)
431struct perf_event * 431struct perf_event *
432register_user_hw_breakpoint(struct perf_event_attr *attr, 432register_user_hw_breakpoint(struct perf_event_attr *attr,
433 perf_overflow_handler_t triggered, 433 perf_overflow_handler_t triggered,
434 void *context,
434 struct task_struct *tsk) 435 struct task_struct *tsk)
435{ 436{
436 return perf_event_create_kernel_counter(attr, -1, tsk, triggered); 437 return perf_event_create_kernel_counter(attr, -1, tsk, triggered,
438 context);
437} 439}
438EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); 440EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
439 441
@@ -502,7 +504,8 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
502 */ 504 */
503struct perf_event * __percpu * 505struct perf_event * __percpu *
504register_wide_hw_breakpoint(struct perf_event_attr *attr, 506register_wide_hw_breakpoint(struct perf_event_attr *attr,
505 perf_overflow_handler_t triggered) 507 perf_overflow_handler_t triggered,
508 void *context)
506{ 509{
507 struct perf_event * __percpu *cpu_events, **pevent, *bp; 510 struct perf_event * __percpu *cpu_events, **pevent, *bp;
508 long err; 511 long err;
@@ -515,7 +518,8 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
515 get_online_cpus(); 518 get_online_cpus();
516 for_each_online_cpu(cpu) { 519 for_each_online_cpu(cpu) {
517 pevent = per_cpu_ptr(cpu_events, cpu); 520 pevent = per_cpu_ptr(cpu_events, cpu);
518 bp = perf_event_create_kernel_counter(attr, cpu, NULL, triggered); 521 bp = perf_event_create_kernel_counter(attr, cpu, NULL,
522 triggered, context);
519 523
520 *pevent = bp; 524 *pevent = bp;
521 525