Skip to content

Commit

Permalink
perf/core: Set event's default ::overflow_handler()
Browse files Browse the repository at this point in the history
Set a default event->overflow_handler in perf_event_alloc() so don't
need to check event->overflow_handler in __perf_event_overflow().
Following commits can give a different default overflow_handler.

Initial idea comes from Peter:

  http://lkml.kernel.org/r/[email protected]

Since the default value of event->overflow_handler is not NULL, existing
'if (!overflow_handler)' checks need to be changed.

is_default_overflow_handler() is introduced for this.

No extra performance overhead is introduced into the hot path because in the
original code we still need to read this handler from memory. A conditional
branch is avoided so actually we remove some instructions.

Signed-off-by: Wang Nan <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Cc: <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexei Starovoitov <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Brendan Gregg <[email protected]>
Cc: He Kuang <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Vince Weaver <[email protected]>
Cc: Zefan Li <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
WangNan0 authored and Ingo Molnar committed Mar 31, 2016
1 parent 86e7972 commit 1879445
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 10 deletions.
4 changes: 2 additions & 2 deletions arch/arm/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
info->address &= ~alignment_mask;
info->ctrl.len <<= offset;

if (!bp->overflow_handler) {
if (is_default_overflow_handler(bp)) {
/*
* Mismatch breakpoints are required for single-stepping
* breakpoints.
Expand Down Expand Up @@ -754,7 +754,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
* mismatch breakpoint so we can single-step over the
* watchpoint trigger.
*/
if (!wp->overflow_handler)
if (is_default_overflow_handler(wp))
enable_single_step(wp, instruction_pointer(regs));

unlock:
Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ static int breakpoint_handler(unsigned long unused, unsigned int esr,
perf_bp_event(bp, regs);

/* Do we need to handle the stepping? */
if (!bp->overflow_handler)
if (is_default_overflow_handler(bp))
step = 1;
unlock:
rcu_read_unlock();
Expand Down Expand Up @@ -712,7 +712,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
perf_bp_event(wp, regs);

/* Do we need to handle the stepping? */
if (!wp->overflow_handler)
if (is_default_overflow_handler(wp))
step = 1;

unlock:
Expand Down
6 changes: 6 additions & 0 deletions include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,12 @@ extern void perf_event_output(struct perf_event *event,
struct perf_sample_data *data,
struct pt_regs *regs);

static inline bool
is_default_overflow_handler(struct perf_event *event)
{
return (event->overflow_handler == perf_event_output);
}

extern void
perf_event_header__init_id(struct perf_event_header *header,
struct perf_sample_data *data,
Expand Down
14 changes: 8 additions & 6 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -6628,10 +6628,7 @@ static int __perf_event_overflow(struct perf_event *event,
irq_work_queue(&event->pending);
}

if (event->overflow_handler)
event->overflow_handler(event, data, regs);
else
perf_event_output(event, data, regs);
event->overflow_handler(event, data, regs);

if (*perf_event_fasync(event) && event->pending_kill) {
event->pending_wakeup = 1;
Expand Down Expand Up @@ -8152,8 +8149,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
context = parent_event->overflow_handler_context;
}

event->overflow_handler = overflow_handler;
event->overflow_handler_context = context;
if (overflow_handler) {
event->overflow_handler = overflow_handler;
event->overflow_handler_context = context;
} else {
event->overflow_handler = perf_event_output;
event->overflow_handler_context = NULL;
}

perf_event__state_init(event);

Expand Down

0 comments on commit 1879445

Please sign in to comment.