lkml.org 
[lkml]   [2016]   [Mar]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/4] perf core: Set event's default overflow_handler
    Date
    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 at [1]

    Since default value of event->overflow_handler is not null, existing
    'if (!overflow_handler)' need to be changed.
    is_default_overflow_handler() is introduced for this.

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

    [1] http://lkml.kernel.org/r/20130708121557.GA17211@twins.programming.kicks-ass.net

    Signed-off-by: Wang Nan <wangnan0@huawei.com>
    Cc: He Kuang <hekuang@huawei.com>
    Cc: Alexei Starovoitov <ast@kernel.org>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
    Cc: Jiri Olsa <jolsa@kernel.org>
    Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Zefan Li <lizefan@huawei.com>
    Cc: pi3orama@163.com
    ---
    arch/arm/kernel/hw_breakpoint.c | 4 ++--
    arch/arm64/kernel/hw_breakpoint.c | 4 ++--
    include/linux/perf_event.h | 6 ++++++
    kernel/events/core.c | 14 ++++++++------
    4 files changed, 18 insertions(+), 10 deletions(-)

    diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
    index 6284779..b8df458 100644
    --- a/arch/arm/kernel/hw_breakpoint.c
    +++ b/arch/arm/kernel/hw_breakpoint.c
    @@ -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.
    @@ -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:
    diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
    index b45c95d..4ef5373 100644
    --- a/arch/arm64/kernel/hw_breakpoint.c
    +++ b/arch/arm64/kernel/hw_breakpoint.c
    @@ -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();
    @@ -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:
    diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
    index 15588d4..4065ca2 100644
    --- a/include/linux/perf_event.h
    +++ b/include/linux/perf_event.h
    @@ -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,
    diff --git a/kernel/events/core.c b/kernel/events/core.c
    index cb47da3..3bd4b2b 100644
    --- a/kernel/events/core.c
    +++ b/kernel/events/core.c
    @@ -6502,10 +6502,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;
    @@ -8017,8 +8014,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);

    --
    1.8.3.4
    \
     
     \ /
      Last update: 2016-03-28 09:01    [W:4.380 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site