Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1365360 > unrolled thread

[PATCH 0/4] perf core: Support reading from overwritable ring buffer

Started byWang Nan <wangnan0@huawei.com>
First post2016-03-28 08:50 +0200
Last post2016-03-31 11:30 +0200
Articles 14 — 5 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/4] perf core: Support reading from overwritable ring buffer Wang Nan <wangnan0@huawei.com> - 2016-03-28 08:50 +0200
    [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer Wang Nan <wangnan0@huawei.com> - 2016-03-28 08:50 +0200
      [PATCH][manpages 1/2] perf_event_open.2: Document PERF_EVENT_IOC_PAUSE_OUTPUT Wang Nan <wangnan0@huawei.com> - 2016-03-28 12:20 +0200
      Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2016-03-29 02:30 +0200
        Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer "Wangnan (F)" <wangnan0@huawei.com> - 2016-03-29 03:20 +0200
        [PATCH 1/4 fix] perf core: Introduce new ioctl options to pause and resume ring buffer Wang Nan <wangnan0@huawei.com> - 2016-03-29 04:10 +0200
          Re: [PATCH 1/4 fix] perf core: Introduce new ioctl options to pause  and resume ring buffer Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2016-03-29 06:50 +0200
      Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer Peter Zijlstra <peterz@infradead.org> - 2016-03-29 15:00 +0200
        Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer Peter Zijlstra <peterz@infradead.org> - 2016-03-29 15:00 +0200
        Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer "Wangnan (F)" <wangnan0@huawei.com> - 2016-03-30 04:00 +0200
          Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and  resume ring buffer Peter Zijlstra <peterz@infradead.org> - 2016-03-30 08:50 +0200
      [tip:perf/core] perf/ring_buffer: Introduce new ioctl options to  pause and resume the ring-buffer tip-bot for Wang Nan <tipbot@zytor.com> - 2016-03-31 11:30 +0200
    [PATCH 2/4] perf core: Set event's default overflow_handler Wang Nan <wangnan0@huawei.com> - 2016-03-28 08:50 +0200
      [tip:perf/core] perf/core: Set event's default ::overflow_handler() tip-bot for Wang Nan <tipbot@zytor.com> - 2016-03-31 11:30 +0200

#1365360 — [PATCH 0/4] perf core: Support reading from overwritable ring buffer

FromWang Nan <wangnan0@huawei.com>
Date2016-03-28 08:50 +0200
Subject[PATCH 0/4] perf core: Support reading from overwritable ring buffer
Message-ID<rhz9T-39T-3@gated-at.bofh.it>
Following Peter and Alexei's suggestion, this patchset:

 1. Append performance test result in commit message of patch 3/4 and 4/4;
 2. Describe history and design choice in commit message of patch 4/4;
 3. Change 'onward' to 'forward';
 4. Squash patches to make a better git log.

Wang Nan (4):
  perf core: Introduce new ioctl options to pause and resume ring buffer
  perf core: Set event's default overflow_handler
  perf core: Prepare writing into ring buffer from end
  perf core: Add backward attribute to perf event

 arch/arm/kernel/hw_breakpoint.c   |  4 +--
 arch/arm64/kernel/hw_breakpoint.c |  4 +--
 include/linux/perf_event.h        | 32 +++++++++++++++--
 include/uapi/linux/perf_event.h   |  4 ++-
 kernel/events/core.c              | 73 +++++++++++++++++++++++++++++++++------
 kernel/events/internal.h          | 11 ++++++
 kernel/events/ring_buffer.c       | 63 +++++++++++++++++++++++++++++----
 7 files changed, 167 insertions(+), 24 deletions(-)

-- 
1.8.3.4

[toc] | [next] | [standalone]


#1365365 — [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

FromWang Nan <wangnan0@huawei.com>
Date2016-03-28 08:50 +0200
Subject[PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rhz9U-39T-13@gated-at.bofh.it>
In reply to#1365360
Add new ioctl() to pause/resume ring-buffer output.

In some situations we want to read from ring buffer only when we
ensure nothing can write to the ring buffer during reading. Without
this patch we have to turn off all events attached to this ring buffer
to achieve this.

This patch is for supporting overwrite ring buffer. Following
commits will introduce new methods support reading from overwrite ring
buffer. Before reading, caller must ensure the ring buffer is frozen, or
the reading is unreliable.

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
---
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 13 +++++++++++++
 kernel/events/internal.h        | 11 +++++++++++
 kernel/events/ring_buffer.c     |  7 ++++++-
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 1afe962..a3c1903 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -401,6 +401,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
 #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
 #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
+#define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
 
 enum perf_event_ioc_flags {
 	PERF_IOC_FLAG_GROUP		= 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index de24fbc..cb47da3 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4341,6 +4341,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
 	case PERF_EVENT_IOC_SET_BPF:
 		return perf_event_set_bpf_prog(event, arg);
 
+	case PERF_EVENT_IOC_PAUSE_OUTPUT: {
+		struct ring_buffer *rb;
+
+		rcu_read_lock();
+		rb = rcu_dereference(event->rb);
+		if (!event->rb) {
+			rcu_read_unlock();
+			return -EINVAL;
+		}
+		rb_toggle_paused(rb, !!arg);
+		rcu_read_unlock();
+		return 0;
+	}
 	default:
 		return -ENOTTY;
 	}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 2bbad9c..6a93d1b 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -18,6 +18,7 @@ struct ring_buffer {
 #endif
 	int				nr_pages;	/* nr of data pages  */
 	int				overwrite;	/* can overwrite itself */
+	int				paused;		/* can write into ring buffer */
 
 	atomic_t			poll;		/* POLL_ for wakeups */
 
@@ -65,6 +66,16 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head)
 	rb_free(rb);
 }
 
+static inline void
+rb_toggle_paused(struct ring_buffer *rb,
+		 bool pause)
+{
+	if (!pause && rb->nr_pages)
+		rb->paused = 0;
+	else
+		rb->paused = 1;
+}
+
 extern struct ring_buffer *
 rb_alloc(int nr_pages, long watermark, int cpu, int flags);
 extern void perf_event_wakeup(struct perf_event *event);
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index c61f0cb..17de83b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -125,8 +125,11 @@ int perf_output_begin(struct perf_output_handle *handle,
 	if (unlikely(!rb))
 		goto out;
 
-	if (unlikely(!rb->nr_pages))
+	if (unlikely(rb->paused)) {
+		if (rb->nr_pages)
+			local_inc(&rb->lost);
 		goto out;
+	}
 
 	handle->rb    = rb;
 	handle->event = event;
@@ -244,6 +247,8 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
 	INIT_LIST_HEAD(&rb->event_list);
 	spin_lock_init(&rb->event_lock);
 	init_irq_work(&rb->irq_work, rb_irq_work);
+
+	rb->paused = rb->nr_pages ? 0 : 1;
 }
 
 static void ring_buffer_put_async(struct ring_buffer *rb)
-- 
1.8.3.4

[toc] | [prev] | [next] | [standalone]


#1365430 — [PATCH][manpages 1/2] perf_event_open.2: Document PERF_EVENT_IOC_PAUSE_OUTPUT

FromWang Nan <wangnan0@huawei.com>
Date2016-03-28 12:20 +0200
Subject[PATCH][manpages 1/2] perf_event_open.2: Document PERF_EVENT_IOC_PAUSE_OUTPUT
Message-ID<rhCr7-5yX-1@gated-at.bofh.it>
In reply to#1365365
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 man2/perf_event_open.2 | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/man2/perf_event_open.2 b/man2/perf_event_open.2
index c90fc51..b232cba 100644
--- a/man2/perf_event_open.2
+++ b/man2/perf_event_open.2
@@ -2719,6 +2719,17 @@ The argument is a BPF program file descriptor that was created by
 a previous
 .BR bpf (2)
 system call.
+.TP
+.BR PERF_EVENT_IOC_PAUSE_OUTPUT " (since Linux 4.6)"
+.\" commit ? (http://lkml.kernel.org/g/1459147292-239310-2-git-send-email-wangnan0@huawei.com)
+This allows pausing and resuming the event's ring-buffer. A
+paused ring-buffer does not prevent samples generation, but simply
+discards them. The discarded samples are considered lost, causes
+.BR PERF_RECORD_LOST
+to be generated when possible.
+
+The argument is an integer. Nonzero value pauses the ring-buffer,
+zero value resumes the ring-buffer.
 .SS Using prctl
 A process can enable or disable all the event groups that are
 attached to it using the
-- 
1.8.3.4

[toc] | [prev] | [next] | [standalone]


#1365730 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

FromAlexei Starovoitov <alexei.starovoitov@gmail.com>
Date2016-03-29 02:30 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rhPHI-6uL-5@gated-at.bofh.it>
In reply to#1365365
On Mon, Mar 28, 2016 at 06:41:29AM +0000, Wang Nan wrote:
> Add new ioctl() to pause/resume ring-buffer output.
> 
> In some situations we want to read from ring buffer only when we
> ensure nothing can write to the ring buffer during reading. Without
> this patch we have to turn off all events attached to this ring buffer
> to achieve this.
> 
> This patch is for supporting overwrite ring buffer. Following
> commits will introduce new methods support reading from overwrite ring
> buffer. Before reading, caller must ensure the ring buffer is frozen, or
> the reading is unreliable.
> 
> 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
> ---
>  include/uapi/linux/perf_event.h |  1 +
>  kernel/events/core.c            | 13 +++++++++++++
>  kernel/events/internal.h        | 11 +++++++++++
>  kernel/events/ring_buffer.c     |  7 ++++++-
>  4 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 1afe962..a3c1903 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -401,6 +401,7 @@ struct perf_event_attr {
>  #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
>  #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
>  #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
> +#define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
>  
>  enum perf_event_ioc_flags {
>  	PERF_IOC_FLAG_GROUP		= 1U << 0,
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index de24fbc..cb47da3 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -4341,6 +4341,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
>  	case PERF_EVENT_IOC_SET_BPF:
>  		return perf_event_set_bpf_prog(event, arg);
>  
> +	case PERF_EVENT_IOC_PAUSE_OUTPUT: {
> +		struct ring_buffer *rb;
> +
> +		rcu_read_lock();
> +		rb = rcu_dereference(event->rb);
> +		if (!event->rb) {

should have been 'if (!rb)', right?

[toc] | [prev] | [next] | [standalone]


#1365751 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

From"Wangnan (F)" <wangnan0@huawei.com>
Date2016-03-29 03:20 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rhQu5-77q-1@gated-at.bofh.it>
In reply to#1365730

On 2016/3/29 8:27, Alexei Starovoitov wrote:
> On Mon, Mar 28, 2016 at 06:41:29AM +0000, Wang Nan wrote:
>> Add new ioctl() to pause/resume ring-buffer output.
>>
>> In some situations we want to read from ring buffer only when we
>> ensure nothing can write to the ring buffer during reading. Without
>> this patch we have to turn off all events attached to this ring buffer
>> to achieve this.
>>
>> This patch is for supporting overwrite ring buffer. Following
>> commits will introduce new methods support reading from overwrite ring
>> buffer. Before reading, caller must ensure the ring buffer is frozen, or
>> the reading is unreliable.
>>
>> 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
>> ---
>>   include/uapi/linux/perf_event.h |  1 +
>>   kernel/events/core.c            | 13 +++++++++++++
>>   kernel/events/internal.h        | 11 +++++++++++
>>   kernel/events/ring_buffer.c     |  7 ++++++-
>>   4 files changed, 31 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
>> index 1afe962..a3c1903 100644
>> --- a/include/uapi/linux/perf_event.h
>> +++ b/include/uapi/linux/perf_event.h
>> @@ -401,6 +401,7 @@ struct perf_event_attr {
>>   #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
>>   #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
>>   #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
>> +#define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
>>   
>>   enum perf_event_ioc_flags {
>>   	PERF_IOC_FLAG_GROUP		= 1U << 0,
>> diff --git a/kernel/events/core.c b/kernel/events/core.c
>> index de24fbc..cb47da3 100644
>> --- a/kernel/events/core.c
>> +++ b/kernel/events/core.c
>> @@ -4341,6 +4341,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
>>   	case PERF_EVENT_IOC_SET_BPF:
>>   		return perf_event_set_bpf_prog(event, arg);
>>   
>> +	case PERF_EVENT_IOC_PAUSE_OUTPUT: {
>> +		struct ring_buffer *rb;
>> +
>> +		rcu_read_lock();
>> +		rb = rcu_dereference(event->rb);
>> +		if (!event->rb) {
> should have been 'if (!rb)', right?

Good catch. Thank you!

[toc] | [prev] | [next] | [standalone]


#1365800 — [PATCH 1/4 fix] perf core: Introduce new ioctl options to pause and resume ring buffer

FromWang Nan <wangnan0@huawei.com>
Date2016-03-29 04:10 +0200
Subject[PATCH 1/4 fix] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rhRgt-7Hz-9@gated-at.bofh.it>
In reply to#1365730
Add new ioctl() to pause/resume ring-buffer output.

In some situations we want to read from ring buffer only when we
ensure nothing can write to the ring buffer during reading. Without
this patch we have to turn off all events attached to this ring buffer
to achieve this.

This patch is for supporting overwrite ring buffer. Following
commits will introduce new methods support reading from overwrite ring
buffer. Before reading, caller must ensure the ring buffer is frozen, or
the reading is unreliable.

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
---
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 13 +++++++++++++
 kernel/events/internal.h        | 11 +++++++++++
 kernel/events/ring_buffer.c     |  7 ++++++-
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 1afe962..a3c1903 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -401,6 +401,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
 #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
 #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
+#define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
 
 enum perf_event_ioc_flags {
 	PERF_IOC_FLAG_GROUP		= 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index de24fbc..a1636d3 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4341,6 +4341,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
 	case PERF_EVENT_IOC_SET_BPF:
 		return perf_event_set_bpf_prog(event, arg);
 
+	case PERF_EVENT_IOC_PAUSE_OUTPUT: {
+		struct ring_buffer *rb;
+
+		rcu_read_lock();
+		rb = rcu_dereference(event->rb);
+		if (!rb) {
+			rcu_read_unlock();
+			return -EINVAL;
+		}
+		rb_toggle_paused(rb, !!arg);
+		rcu_read_unlock();
+		return 0;
+	}
 	default:
 		return -ENOTTY;
 	}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 2bbad9c..6a93d1b 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -18,6 +18,7 @@ struct ring_buffer {
 #endif
 	int				nr_pages;	/* nr of data pages  */
 	int				overwrite;	/* can overwrite itself */
+	int				paused;		/* can write into ring buffer */
 
 	atomic_t			poll;		/* POLL_ for wakeups */
 
@@ -65,6 +66,16 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head)
 	rb_free(rb);
 }
 
+static inline void
+rb_toggle_paused(struct ring_buffer *rb,
+		 bool pause)
+{
+	if (!pause && rb->nr_pages)
+		rb->paused = 0;
+	else
+		rb->paused = 1;
+}
+
 extern struct ring_buffer *
 rb_alloc(int nr_pages, long watermark, int cpu, int flags);
 extern void perf_event_wakeup(struct perf_event *event);
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index c61f0cb..17de83b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -125,8 +125,11 @@ int perf_output_begin(struct perf_output_handle *handle,
 	if (unlikely(!rb))
 		goto out;
 
-	if (unlikely(!rb->nr_pages))
+	if (unlikely(rb->paused)) {
+		if (rb->nr_pages)
+			local_inc(&rb->lost);
 		goto out;
+	}
 
 	handle->rb    = rb;
 	handle->event = event;
@@ -244,6 +247,8 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
 	INIT_LIST_HEAD(&rb->event_list);
 	spin_lock_init(&rb->event_lock);
 	init_irq_work(&rb->irq_work, rb_irq_work);
+
+	rb->paused = rb->nr_pages ? 0 : 1;
 }
 
 static void ring_buffer_put_async(struct ring_buffer *rb)
-- 
1.8.3.4

[toc] | [prev] | [next] | [standalone]


#1365850 — Re: [PATCH 1/4 fix] perf core: Introduce new ioctl options to pause and resume ring buffer

FromAlexei Starovoitov <alexei.starovoitov@gmail.com>
Date2016-03-29 06:50 +0200
SubjectRe: [PATCH 1/4 fix] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rhTLj-Yu-7@gated-at.bofh.it>
In reply to#1365800
On Tue, Mar 29, 2016 at 02:05:07AM +0000, Wang Nan wrote:
> Add new ioctl() to pause/resume ring-buffer output.
> 
> In some situations we want to read from ring buffer only when we
> ensure nothing can write to the ring buffer during reading. Without
> this patch we have to turn off all events attached to this ring buffer
> to achieve this.
> 
> This patch is for supporting overwrite ring buffer. Following
> commits will introduce new methods support reading from overwrite ring
> buffer. Before reading, caller must ensure the ring buffer is frozen, or
> the reading is unreliable.
> 
> 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
> ---
>  include/uapi/linux/perf_event.h |  1 +
>  kernel/events/core.c            | 13 +++++++++++++
>  kernel/events/internal.h        | 11 +++++++++++
>  kernel/events/ring_buffer.c     |  7 ++++++-
>  4 files changed, 31 insertions(+), 1 deletion(-)

Acked-by: Alexei Starovoitov <ast@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1366236 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

FromPeter Zijlstra <peterz@infradead.org>
Date2016-03-29 15:00 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<ri1pv-6kK-1@gated-at.bofh.it>
In reply to#1365365
On Mon, Mar 28, 2016 at 06:41:29AM +0000, Wang Nan wrote:
> Add new ioctl() to pause/resume ring-buffer output.
> 
> In some situations we want to read from ring buffer only when we
> ensure nothing can write to the ring buffer during reading. Without
> this patch we have to turn off all events attached to this ring buffer
> to achieve this.
> 
> This patch is for supporting overwrite ring buffer. Following
> commits will introduce new methods support reading from overwrite ring
> buffer. Before reading, caller must ensure the ring buffer is frozen, or
> the reading is unreliable.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>

I made the below changes.

--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4346,7 +4346,7 @@ static long _perf_ioctl(struct perf_even
 
 		rcu_read_lock();
 		rb = rcu_dereference(event->rb);
-		if (!event->rb) {
+		if (!event->rb || !event->nr_pages) {
 			rcu_read_unlock();
 			return -EINVAL;
 		}
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -66,9 +66,7 @@ static inline void rb_free_rcu(struct rc
 	rb_free(rb);
 }
 
-static inline void
-rb_toggle_paused(struct ring_buffer *rb,
-		 bool pause)
+static inline void rb_toggle_paused(struct ring_buffer *rb, bool pause)
 {
 	if (!pause && rb->nr_pages)
 		rb->paused = 0;
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -248,7 +248,12 @@ ring_buffer_init(struct ring_buffer *rb,
 	spin_lock_init(&rb->event_lock);
 	init_irq_work(&rb->irq_work, rb_irq_work);
 
-	rb->paused = rb->nr_pages ? 0 : 1;
+	/*
+	 * perf_output_begin() only checks rb->paused, therefore
+	 * rb->paused must be true if we have no pages for output.
+	 */
+	if (!rb->nr_pages)
+		rb->paused = 1;
 }
 
 static void ring_buffer_put_async(struct ring_buffer *rb)

[toc] | [prev] | [next] | [standalone]


#1366240 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

FromPeter Zijlstra <peterz@infradead.org>
Date2016-03-29 15:00 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<ri1pv-6kK-15@gated-at.bofh.it>
In reply to#1366236
On Tue, Mar 29, 2016 at 02:54:23PM +0200, Peter Zijlstra wrote:
> +++ b/kernel/events/core.c
> @@ -4346,7 +4346,7 @@ static long _perf_ioctl(struct perf_even
>  
>  		rcu_read_lock();
>  		rb = rcu_dereference(event->rb);
> -		if (!event->rb) {
> +		if (!event->rb || !event->nr_pages) {
>  			rcu_read_unlock();
>  			return -EINVAL;
>  		}

Clearly that should've been:

--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4346,7 +4346,7 @@ static long _perf_ioctl(struct perf_even
 
 		rcu_read_lock();
 		rb = rcu_dereference(event->rb);
-		if (!event->rb || !event->nr_pages) {
+		if (!rb || !rb->nr_pages) {
 			rcu_read_unlock();
 			return -EINVAL;
 		}

[toc] | [prev] | [next] | [standalone]


#1366849 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

From"Wangnan (F)" <wangnan0@huawei.com>
Date2016-03-30 04:00 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<ridAl-6zf-5@gated-at.bofh.it>
In reply to#1366236

On 2016/3/29 20:54, Peter Zijlstra wrote:
> On Mon, Mar 28, 2016 at 06:41:29AM +0000, Wang Nan wrote:
>> Add new ioctl() to pause/resume ring-buffer output.
>>
>> In some situations we want to read from ring buffer only when we
>> ensure nothing can write to the ring buffer during reading. Without
>> this patch we have to turn off all events attached to this ring buffer
>> to achieve this.
>>
>> This patch is for supporting overwrite ring buffer. Following
>> commits will introduce new methods support reading from overwrite ring
>> buffer. Before reading, caller must ensure the ring buffer is frozen, or
>> the reading is unreliable.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> I made the below changes.

Can I add your SOB when I resend it?

> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -4346,7 +4346,7 @@ static long _perf_ioctl(struct perf_even
>   
>   		rcu_read_lock();
>   		rb = rcu_dereference(event->rb);
> -		if (!event->rb) {
> +		if (!event->rb || !event->nr_pages) {
>   			rcu_read_unlock();
>   			return -EINVAL;
>   		}
> --- a/kernel/events/internal.h
> +++ b/kernel/events/internal.h
> @@ -66,9 +66,7 @@ static inline void rb_free_rcu(struct rc
>   	rb_free(rb);
>   }
>   
> -static inline void
> -rb_toggle_paused(struct ring_buffer *rb,
> -		 bool pause)
> +static inline void rb_toggle_paused(struct ring_buffer *rb, bool pause)
>   {
>   	if (!pause && rb->nr_pages)
>   		rb->paused = 0;
> --- a/kernel/events/ring_buffer.c
> +++ b/kernel/events/ring_buffer.c
> @@ -248,7 +248,12 @@ ring_buffer_init(struct ring_buffer *rb,
>   	spin_lock_init(&rb->event_lock);
>   	init_irq_work(&rb->irq_work, rb_irq_work);
>   
> -	rb->paused = rb->nr_pages ? 0 : 1;
> +	/*
> +	 * perf_output_begin() only checks rb->paused, therefore
> +	 * rb->paused must be true if we have no pages for output.
> +	 */
> +	if (!rb->nr_pages)
> +		rb->paused = 1;
>   }

I still think we need to explicitly set rb->paused to 0
when rb->nr_pages is non-zero to avoid further improvement
re-init an old 'struct ring_buffer':

         rb->paused = 0;
         if (unlikely(!rb->nr_pages))
                 rb->paused = 1;

Thank you.

>   
>   static void ring_buffer_put_async(struct ring_buffer *rb)

[toc] | [prev] | [next] | [standalone]


#1366918 — Re: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer

FromPeter Zijlstra <peterz@infradead.org>
Date2016-03-30 08:50 +0200
SubjectRe: [PATCH 1/4] perf core: Introduce new ioctl options to pause and resume ring buffer
Message-ID<rii70-1t9-13@gated-at.bofh.it>
In reply to#1366849
On Wed, Mar 30, 2016 at 09:57:02AM +0800, Wangnan (F) wrote:
> 
> 
> On 2016/3/29 20:54, Peter Zijlstra wrote:
> >On Mon, Mar 28, 2016 at 06:41:29AM +0000, Wang Nan wrote:
> >>Add new ioctl() to pause/resume ring-buffer output.
> >>
> >>In some situations we want to read from ring buffer only when we
> >>ensure nothing can write to the ring buffer during reading. Without
> >>this patch we have to turn off all events attached to this ring buffer
> >>to achieve this.
> >>
> >>This patch is for supporting overwrite ring buffer. Following
> >>commits will introduce new methods support reading from overwrite ring
> >>buffer. Before reading, caller must ensure the ring buffer is frozen, or
> >>the reading is unreliable.
> >>
> >>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >I made the below changes.
> 
> Can I add your SOB when I resend it?

No need, I've got it.

[toc] | [prev] | [next] | [standalone]


#1368087 — [tip:perf/core] perf/ring_buffer: Introduce new ioctl options to pause and resume the ring-buffer

Fromtip-bot for Wang Nan <tipbot@zytor.com>
Date2016-03-31 11:30 +0200
Subject[tip:perf/core] perf/ring_buffer: Introduce new ioctl options to pause and resume the ring-buffer
Message-ID<riH5q-2PS-63@gated-at.bofh.it>
In reply to#1365365
Commit-ID:  86e7972f690c1017fd086cdfe53d8524e68c661c
Gitweb:     http://git.kernel.org/tip/86e7972f690c1017fd086cdfe53d8524e68c661c
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Mon, 28 Mar 2016 06:41:29 +0000
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 31 Mar 2016 10:30:45 +0200

perf/ring_buffer: Introduce new ioctl options to pause and resume the ring-buffer

Add new ioctl() to pause/resume ring-buffer output.

In some situations we want to read from the ring-buffer only when we
ensure nothing can write to the ring-buffer during reading. Without
this patch we have to turn off all events attached to this ring-buffer
to achieve this.

This patch is a prerequisite to enable overwrite support for the
perf ring-buffer support. Following commits will introduce new methods
support reading from overwrite ring buffer. Before reading, caller
must ensure the ring buffer is frozen, or the reading is unreliable.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: <pi3orama@163.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1459147292-239310-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 13 +++++++++++++
 kernel/events/internal.h        |  9 +++++++++
 kernel/events/ring_buffer.c     | 12 +++++++++++-
 4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 1afe962..a3c1903 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -401,6 +401,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_SET_FILTER	_IOW('$', 6, char *)
 #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
 #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
+#define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
 
 enum perf_event_ioc_flags {
 	PERF_IOC_FLAG_GROUP		= 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 243df4b..51386e8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4379,6 +4379,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
 	case PERF_EVENT_IOC_SET_BPF:
 		return perf_event_set_bpf_prog(event, arg);
 
+	case PERF_EVENT_IOC_PAUSE_OUTPUT: {
+		struct ring_buffer *rb;
+
+		rcu_read_lock();
+		rb = rcu_dereference(event->rb);
+		if (!rb || !rb->nr_pages) {
+			rcu_read_unlock();
+			return -EINVAL;
+		}
+		rb_toggle_paused(rb, !!arg);
+		rcu_read_unlock();
+		return 0;
+	}
 	default:
 		return -ENOTTY;
 	}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 2b229fd..2d67327 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -17,6 +17,7 @@ struct ring_buffer {
 #endif
 	int				nr_pages;	/* nr of data pages  */
 	int				overwrite;	/* can overwrite itself */
+	int				paused;		/* can write into ring buffer */
 
 	atomic_t			poll;		/* POLL_ for wakeups */
 
@@ -64,6 +65,14 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head)
 	rb_free(rb);
 }
 
+static inline void rb_toggle_paused(struct ring_buffer *rb, bool pause)
+{
+	if (!pause && rb->nr_pages)
+		rb->paused = 0;
+	else
+		rb->paused = 1;
+}
+
 extern struct ring_buffer *
 rb_alloc(int nr_pages, long watermark, int cpu, int flags);
 extern void perf_event_wakeup(struct perf_event *event);
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 0ed4555..72d8127 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -125,8 +125,11 @@ int perf_output_begin(struct perf_output_handle *handle,
 	if (unlikely(!rb))
 		goto out;
 
-	if (unlikely(!rb->nr_pages))
+	if (unlikely(rb->paused)) {
+		if (rb->nr_pages)
+			local_inc(&rb->lost);
 		goto out;
+	}
 
 	handle->rb    = rb;
 	handle->event = event;
@@ -241,6 +244,13 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
 
 	INIT_LIST_HEAD(&rb->event_list);
 	spin_lock_init(&rb->event_lock);
+
+	/*
+	 * perf_output_begin() only checks rb->paused, therefore
+	 * rb->paused must be true if we have no pages for output.
+	 */
+	if (!rb->nr_pages)
+		rb->paused = 1;
 }
 
 /*

[toc] | [prev] | [next] | [standalone]


#1365366 — [PATCH 2/4] perf core: Set event's default overflow_handler

FromWang Nan <wangnan0@huawei.com>
Date2016-03-28 08:50 +0200
Subject[PATCH 2/4] perf core: Set event's default overflow_handler
Message-ID<rhz9U-39T-19@gated-at.bofh.it>
In reply to#1365360
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

[toc] | [prev] | [next] | [standalone]


#1368079 — [tip:perf/core] perf/core: Set event's default ::overflow_handler()

Fromtip-bot for Wang Nan <tipbot@zytor.com>
Date2016-03-31 11:30 +0200
Subject[tip:perf/core] perf/core: Set event's default ::overflow_handler()
Message-ID<riH5q-2PS-47@gated-at.bofh.it>
In reply to#1365366
Commit-ID:  1879445dfa7bbd6fe21b09c5cc72f4934798afed
Gitweb:     http://git.kernel.org/tip/1879445dfa7bbd6fe21b09c5cc72f4934798afed
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Mon, 28 Mar 2016 06:41:30 +0000
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 31 Mar 2016 10:30:47 +0200

perf/core: Set event's default ::overflow_handler()

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/20130708121557.GA17211@twins.programming.kicks-ass.net

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 <wangnan0@huawei.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: <pi3orama@163.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1459147292-239310-3-git-send-email-wangnan0@huawei.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 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 51386e8..8c3b35f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -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;
@@ -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);
 

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web