Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751239AbcCNKBp (ORCPT ); Mon, 14 Mar 2016 06:01:45 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:29975 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933851AbcCNKBY (ORCPT ); Mon, 14 Mar 2016 06:01:24 -0400 From: Wang Nan To: , CC: , Wang Nan , He Kuang , Alexei Starovoitov , "Arnaldo Carvalho de Melo" , Brendan Gregg , "Jiri Olsa" , Masami Hiramatsu , Namhyung Kim , Zefan Li , Subject: [PATCH 5/5] perf core: Reduce perf event output overhead by new overflow handler Date: Mon, 14 Mar 2016 09:59:45 +0000 Message-ID: <1457949585-191064-6-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1457949585-191064-1-git-send-email-wangnan0@huawei.com> References: <1457949585-191064-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090204.56E68BA5.0106,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 205e695c5bc9a59d409cc34b1a252959 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5668 Lines: 170 By creating onward and backward specific overflow handlers and setting them according to event's backward setting, normal sampling events don't need checking backward setting of an event any more. This is the last patch of backward writing patchset. After this patch, there's no extra overhead introduced to the fast path of sampling output. Signed-off-by: Wang Nan Cc: He Kuang Cc: Alexei Starovoitov Cc: Arnaldo Carvalho de Melo Cc: Brendan Gregg Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com --- include/linux/perf_event.h | 23 ++++++++++++++++++++--- kernel/events/core.c | 41 ++++++++++++++++++++++++++++++++++++----- kernel/events/ring_buffer.c | 12 ++++++++++++ 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2bf23c9..9adfaa4 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -829,14 +829,24 @@ extern int perf_event_overflow(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs); +extern void perf_event_output_onward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs); +extern void perf_event_output_backward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs); extern void perf_event_output(struct perf_event *event, - struct perf_sample_data *data, - struct pt_regs *regs); + 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); + if (likely(event->overflow_handler == perf_event_output_onward)) + return true; + if (unlikely(event->overflow_handler == perf_event_output_backward)) + return true; + return false; } extern void @@ -1044,6 +1054,13 @@ static inline bool is_write_backward(struct perf_event *event) extern int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size); +extern int perf_output_begin_onward(struct perf_output_handle *handle, + struct perf_event *event, + unsigned int size); +extern int perf_output_begin_backward(struct perf_output_handle *handle, + struct perf_event *event, + unsigned int size); + extern void perf_output_end(struct perf_output_handle *handle); extern unsigned int perf_output_copy(struct perf_output_handle *handle, const void *buf, unsigned int len); diff --git a/kernel/events/core.c b/kernel/events/core.c index 3da3e38..c80b113 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5606,9 +5606,13 @@ void perf_prepare_sample(struct perf_event_header *header, } } -void perf_event_output(struct perf_event *event, - struct perf_sample_data *data, - struct pt_regs *regs) +static void __always_inline +__perf_event_output(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs, + int (*output_begin)(struct perf_output_handle *, + struct perf_event *, + unsigned int)) { struct perf_output_handle handle; struct perf_event_header header; @@ -5618,7 +5622,7 @@ void perf_event_output(struct perf_event *event, perf_prepare_sample(&header, data, event, regs); - if (perf_output_begin(&handle, event, header.size)) + if (output_begin(&handle, event, header.size)) goto exit; perf_output_sample(&handle, &header, data, event); @@ -5629,6 +5633,30 @@ exit: rcu_read_unlock(); } +void +perf_event_output_onward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin_onward); +} + +void +perf_event_output_backward(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin_backward); +} + +void +perf_event_output(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + __perf_event_output(event, data, regs, perf_output_begin); +} + /* * read event_id */ @@ -7963,8 +7991,11 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (overflow_handler) { event->overflow_handler = overflow_handler; event->overflow_handler_context = context; + } else if (is_write_backward(event)){ + event->overflow_handler = perf_event_output_backward; + event->overflow_handler_context = NULL; } else { - event->overflow_handler = perf_event_output; + event->overflow_handler = perf_event_output_onward; event->overflow_handler_context = NULL; } diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 80b1fa7..7e30e012 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -230,6 +230,18 @@ out: return -ENOSPC; } +int perf_output_begin_onward(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size) +{ + return __perf_output_begin(handle, event, size, false); +} + +int perf_output_begin_backward(struct perf_output_handle *handle, + struct perf_event *event, unsigned int size) +{ + return __perf_output_begin(handle, event, size, true); +} + int perf_output_begin(struct perf_output_handle *handle, struct perf_event *event, unsigned int size) { -- 1.8.3.4