diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-10-18 09:33:50 -0400 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-11-03 13:11:53 -0500 |
| commit | 97eaf5300b9d0cd99c310bf8c4a0f2f3296d88a3 (patch) | |
| tree | aa047f4c078e2c9aeabcbcc9e33d93a50366b8e9 | |
| parent | 41a48d14f6991020c9bb6b93e289ca5b411ed09a (diff) | |
perf/core: Add a callback to perf events
A simple callback in a perf event can be used for multiple purposes.
For example it is useful for triggered based events like hardware
breakpoints that need a callback to dispatch a triggered breakpoint
event.
v2: Simplify a bit the callback attribution as suggested by Paul
Mackerras
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "K.Prasad" <prasad@linux.vnet.ibm.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mundt <lethal@linux-sh.org>
| -rw-r--r-- | include/linux/perf_event.h | 7 | ||||
| -rw-r--r-- | kernel/perf_event.c | 14 |
2 files changed, 16 insertions, 5 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index fa151d49a2ee..8d54e6d25eeb 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -544,6 +544,8 @@ struct perf_pending_entry { | |||
| 544 | void (*func)(struct perf_pending_entry *); | 544 | void (*func)(struct perf_pending_entry *); |
| 545 | }; | 545 | }; |
| 546 | 546 | ||
| 547 | typedef void (*perf_callback_t)(struct perf_event *, void *); | ||
| 548 | |||
| 547 | /** | 549 | /** |
| 548 | * struct perf_event - performance event kernel representation: | 550 | * struct perf_event - performance event kernel representation: |
| 549 | */ | 551 | */ |
| @@ -639,6 +641,8 @@ struct perf_event { | |||
| 639 | struct event_filter *filter; | 641 | struct event_filter *filter; |
| 640 | #endif | 642 | #endif |
| 641 | 643 | ||
| 644 | perf_callback_t callback; | ||
| 645 | |||
| 642 | #endif /* CONFIG_PERF_EVENTS */ | 646 | #endif /* CONFIG_PERF_EVENTS */ |
| 643 | }; | 647 | }; |
| 644 | 648 | ||
| @@ -748,7 +752,8 @@ extern int perf_event_release_kernel(struct perf_event *event); | |||
| 748 | extern struct perf_event * | 752 | extern struct perf_event * |
| 749 | perf_event_create_kernel_counter(struct perf_event_attr *attr, | 753 | perf_event_create_kernel_counter(struct perf_event_attr *attr, |
| 750 | int cpu, | 754 | int cpu, |
| 751 | pid_t pid); | 755 | pid_t pid, |
| 756 | perf_callback_t callback); | ||
| 752 | extern u64 perf_event_read_value(struct perf_event *event); | 757 | extern u64 perf_event_read_value(struct perf_event *event); |
| 753 | 758 | ||
| 754 | struct perf_sample_data { | 759 | struct perf_sample_data { |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 02d4ff041b01..5087125e2a00 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -4293,6 +4293,7 @@ perf_event_alloc(struct perf_event_attr *attr, | |||
| 4293 | struct perf_event_context *ctx, | 4293 | struct perf_event_context *ctx, |
| 4294 | struct perf_event *group_leader, | 4294 | struct perf_event *group_leader, |
| 4295 | struct perf_event *parent_event, | 4295 | struct perf_event *parent_event, |
| 4296 | perf_callback_t callback, | ||
| 4296 | gfp_t gfpflags) | 4297 | gfp_t gfpflags) |
| 4297 | { | 4298 | { |
| 4298 | const struct pmu *pmu; | 4299 | const struct pmu *pmu; |
| @@ -4335,6 +4336,11 @@ perf_event_alloc(struct perf_event_attr *attr, | |||
| 4335 | 4336 | ||
| 4336 | event->state = PERF_EVENT_STATE_INACTIVE; | 4337 | event->state = PERF_EVENT_STATE_INACTIVE; |
| 4337 | 4338 | ||
| 4339 | if (!callback && parent_event) | ||
| 4340 | callback = parent_event->callback; | ||
| 4341 | |||
| 4342 | event->callback = callback; | ||
| 4343 | |||
| 4338 | if (attr->disabled) | 4344 | if (attr->disabled) |
| 4339 | event->state = PERF_EVENT_STATE_OFF; | 4345 | event->state = PERF_EVENT_STATE_OFF; |
| 4340 | 4346 | ||
| @@ -4611,7 +4617,7 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 4611 | } | 4617 | } |
| 4612 | 4618 | ||
| 4613 | event = perf_event_alloc(&attr, cpu, ctx, group_leader, | 4619 | event = perf_event_alloc(&attr, cpu, ctx, group_leader, |
| 4614 | NULL, GFP_KERNEL); | 4620 | NULL, NULL, GFP_KERNEL); |
| 4615 | err = PTR_ERR(event); | 4621 | err = PTR_ERR(event); |
| 4616 | if (IS_ERR(event)) | 4622 | if (IS_ERR(event)) |
| 4617 | goto err_put_context; | 4623 | goto err_put_context; |
| @@ -4668,7 +4674,7 @@ err_put_context: | |||
| 4668 | */ | 4674 | */ |
| 4669 | struct perf_event * | 4675 | struct perf_event * |
| 4670 | perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | 4676 | perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, |
| 4671 | pid_t pid) | 4677 | pid_t pid, perf_callback_t callback) |
| 4672 | { | 4678 | { |
| 4673 | struct perf_event *event; | 4679 | struct perf_event *event; |
| 4674 | struct perf_event_context *ctx; | 4680 | struct perf_event_context *ctx; |
| @@ -4683,7 +4689,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, | |||
| 4683 | return NULL ; | 4689 | return NULL ; |
| 4684 | 4690 | ||
| 4685 | event = perf_event_alloc(attr, cpu, ctx, NULL, | 4691 | event = perf_event_alloc(attr, cpu, ctx, NULL, |
| 4686 | NULL, GFP_KERNEL); | 4692 | NULL, callback, GFP_KERNEL); |
| 4687 | err = PTR_ERR(event); | 4693 | err = PTR_ERR(event); |
| 4688 | if (IS_ERR(event)) | 4694 | if (IS_ERR(event)) |
| 4689 | goto err_put_context; | 4695 | goto err_put_context; |
| @@ -4736,7 +4742,7 @@ inherit_event(struct perf_event *parent_event, | |||
| 4736 | child_event = perf_event_alloc(&parent_event->attr, | 4742 | child_event = perf_event_alloc(&parent_event->attr, |
| 4737 | parent_event->cpu, child_ctx, | 4743 | parent_event->cpu, child_ctx, |
| 4738 | group_leader, parent_event, | 4744 | group_leader, parent_event, |
| 4739 | GFP_KERNEL); | 4745 | NULL, GFP_KERNEL); |
| 4740 | if (IS_ERR(child_event)) | 4746 | if (IS_ERR(child_event)) |
| 4741 | return child_event; | 4747 | return child_event; |
| 4742 | get_ctx(child_ctx); | 4748 | get_ctx(child_ctx); |
