Commit 97eaf530 authored by Frederic Weisbecker's avatar Frederic Weisbecker

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: default avatarFrederic 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>
parent 41a48d14
...@@ -544,6 +544,8 @@ struct perf_pending_entry { ...@@ -544,6 +544,8 @@ struct perf_pending_entry {
void (*func)(struct perf_pending_entry *); void (*func)(struct perf_pending_entry *);
}; };
typedef void (*perf_callback_t)(struct perf_event *, void *);
/** /**
* struct perf_event - performance event kernel representation: * struct perf_event - performance event kernel representation:
*/ */
...@@ -639,6 +641,8 @@ struct perf_event { ...@@ -639,6 +641,8 @@ struct perf_event {
struct event_filter *filter; struct event_filter *filter;
#endif #endif
perf_callback_t callback;
#endif /* CONFIG_PERF_EVENTS */ #endif /* CONFIG_PERF_EVENTS */
}; };
...@@ -748,7 +752,8 @@ extern int perf_event_release_kernel(struct perf_event *event); ...@@ -748,7 +752,8 @@ extern int perf_event_release_kernel(struct perf_event *event);
extern struct perf_event * extern struct perf_event *
perf_event_create_kernel_counter(struct perf_event_attr *attr, perf_event_create_kernel_counter(struct perf_event_attr *attr,
int cpu, int cpu,
pid_t pid); pid_t pid,
perf_callback_t callback);
extern u64 perf_event_read_value(struct perf_event *event); extern u64 perf_event_read_value(struct perf_event *event);
struct perf_sample_data { struct perf_sample_data {
......
...@@ -4293,6 +4293,7 @@ perf_event_alloc(struct perf_event_attr *attr, ...@@ -4293,6 +4293,7 @@ perf_event_alloc(struct perf_event_attr *attr,
struct perf_event_context *ctx, struct perf_event_context *ctx,
struct perf_event *group_leader, struct perf_event *group_leader,
struct perf_event *parent_event, struct perf_event *parent_event,
perf_callback_t callback,
gfp_t gfpflags) gfp_t gfpflags)
{ {
const struct pmu *pmu; const struct pmu *pmu;
...@@ -4335,6 +4336,11 @@ perf_event_alloc(struct perf_event_attr *attr, ...@@ -4335,6 +4336,11 @@ perf_event_alloc(struct perf_event_attr *attr,
event->state = PERF_EVENT_STATE_INACTIVE; event->state = PERF_EVENT_STATE_INACTIVE;
if (!callback && parent_event)
callback = parent_event->callback;
event->callback = callback;
if (attr->disabled) if (attr->disabled)
event->state = PERF_EVENT_STATE_OFF; event->state = PERF_EVENT_STATE_OFF;
...@@ -4611,7 +4617,7 @@ SYSCALL_DEFINE5(perf_event_open, ...@@ -4611,7 +4617,7 @@ SYSCALL_DEFINE5(perf_event_open,
} }
event = perf_event_alloc(&attr, cpu, ctx, group_leader, event = perf_event_alloc(&attr, cpu, ctx, group_leader,
NULL, GFP_KERNEL); NULL, NULL, GFP_KERNEL);
err = PTR_ERR(event); err = PTR_ERR(event);
if (IS_ERR(event)) if (IS_ERR(event))
goto err_put_context; goto err_put_context;
...@@ -4668,7 +4674,7 @@ SYSCALL_DEFINE5(perf_event_open, ...@@ -4668,7 +4674,7 @@ SYSCALL_DEFINE5(perf_event_open,
*/ */
struct perf_event * struct perf_event *
perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
pid_t pid) pid_t pid, perf_callback_t callback)
{ {
struct perf_event *event; struct perf_event *event;
struct perf_event_context *ctx; struct perf_event_context *ctx;
...@@ -4683,7 +4689,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, ...@@ -4683,7 +4689,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
return NULL ; return NULL ;
event = perf_event_alloc(attr, cpu, ctx, NULL, event = perf_event_alloc(attr, cpu, ctx, NULL,
NULL, GFP_KERNEL); NULL, callback, GFP_KERNEL);
err = PTR_ERR(event); err = PTR_ERR(event);
if (IS_ERR(event)) if (IS_ERR(event))
goto err_put_context; goto err_put_context;
...@@ -4736,7 +4742,7 @@ inherit_event(struct perf_event *parent_event, ...@@ -4736,7 +4742,7 @@ inherit_event(struct perf_event *parent_event,
child_event = perf_event_alloc(&parent_event->attr, child_event = perf_event_alloc(&parent_event->attr,
parent_event->cpu, child_ctx, parent_event->cpu, child_ctx,
group_leader, parent_event, group_leader, parent_event,
GFP_KERNEL); NULL, GFP_KERNEL);
if (IS_ERR(child_event)) if (IS_ERR(child_event))
return child_event; return child_event;
get_ctx(child_ctx); get_ctx(child_ctx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment