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>
This commit is contained in:
@@ -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 {
|
|||||||
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);
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@ err_put_context:
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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,
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user