All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] perf/aux: Only update aux_wakeup in non-overwrite mode
@ 2017-09-06 16:08 Alexander Shishkin
  2017-09-12 22:37 ` Will Deacon
  2017-09-29  9:28 ` [tip:perf/urgent] perf/aux: Only update ->aux_wakeup " tip-bot for Alexander Shishkin
  0 siblings, 2 replies; 6+ messages in thread
From: Alexander Shishkin @ 2017-09-06 16:08 UTC (permalink / raw)
  To: Peter Zijlstra, will.deacon; +Cc: Ingo Molnar, linux-kernel, Alexander Shishkin

Commit d9a50b0256 ("perf/aux: Ensure aux_wakeup represents most recent
wakeup index") changed aux wakeup position calculation to rounddown(),
which causes a division-by-zero in AUX overwrite mode (aka "snapshot
mode").

The zero denominator results from the fact that perf record doesn't set
aux_watermark to anything, in which case the kernel will set it to half
the AUX buffer size, but only for non-overwrite mode. In the overwrite
mode aux_watermark stays zero.

The good news is that, AUX overwrite mode, wakeups don't happen and
related bookkeeping is not relevant, so we can simply forego the whole
wakeup updates.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
---
 kernel/events/ring_buffer.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index f4ebe42879..4dae1da4c1 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -412,6 +412,19 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
 	return NULL;
 }
 
+static bool __always_inline rb_need_aux_wakeup(struct ring_buffer *rb)
+{
+	if (rb->aux_overwrite)
+		return false;
+
+	if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+		rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
+		return true;
+	}
+
+	return false;
+}
+
 /*
  * Commit the data written by hardware into the ring buffer by adjusting
  * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the
@@ -451,10 +464,8 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
 	}
 
 	rb->user_page->aux_head = rb->aux_head;
-	if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+	if (rb_need_aux_wakeup(rb))
 		wakeup = true;
-		rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
-	}
 
 	if (wakeup) {
 		if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
@@ -484,9 +495,8 @@ int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size)
 	rb->aux_head += size;
 
 	rb->user_page->aux_head = rb->aux_head;
-	if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+	if (rb_need_aux_wakeup(rb)) {
 		perf_output_wakeup(handle);
-		rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
 		handle->wakeup = rb->aux_wakeup + rb->aux_watermark;
 	}
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-09-29  9:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-06 16:08 [PATCH] perf/aux: Only update aux_wakeup in non-overwrite mode Alexander Shishkin
2017-09-12 22:37 ` Will Deacon
2017-09-13 10:34   ` Alexander Shishkin
2017-09-28 11:29     ` Will Deacon
2017-09-28 11:40       ` Peter Zijlstra
2017-09-29  9:28 ` [tip:perf/urgent] perf/aux: Only update ->aux_wakeup " tip-bot for Alexander Shishkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.