From patchwork Mon Mar 14 09:59:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 63798 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp2383579lbc; Mon, 14 Mar 2016 03:01:50 -0700 (PDT) X-Received: by 10.98.10.21 with SMTP id s21mr12344772pfi.5.1457949709363; Mon, 14 Mar 2016 03:01:49 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q190si24110450pfq.247.2016.03.14.03.01.49; Mon, 14 Mar 2016 03:01:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754152AbcCNKBp (ORCPT + 31 others); 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 Received: from 172.24.1.50 (EHLO szxeml425-hub.china.huawei.com) ([172.24.1.50]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BXY50735; Mon, 14 Mar 2016 18:00:04 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml425-hub.china.huawei.com (10.82.67.180) with Microsoft SMTP Server id 14.3.235.1; Mon, 14 Mar 2016 17:59:55 +0800 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 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 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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(-) -- 1.8.3.4 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) {