perf: Simplify the ring-buffer code
authorPeter Zijlstra <[email protected]>
Thu, 31 Oct 2013 09:19:59 +0000 (10:19 +0100)
committerIngo Molnar <[email protected]>
Wed, 6 Nov 2013 11:34:18 +0000 (12:34 +0100)
By using CIRC_SPACE() we can obviate the need for perf_output_space().

Shrinks the size of perf_output_begin() by 17 bytes on
x86_64-defconfig.

Signed-off-by: Peter Zijlstra <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: Michael Neuling <[email protected]>
Cc: "Paul E. McKenney" <[email protected]>
Cc: [email protected]
Cc: Vince Weaver <[email protected]>
Cc: Victor Kaplansky <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Anton Blanchard <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
kernel/events/ring_buffer.c

index 9c2ddfbf452554902d9ad1c23deba5794d0ed664..6929c5848d4ff5ad19a20d6804d809d45da82396 100644 (file)
 #include <linux/perf_event.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/circ_buf.h>
 
 #include "internal.h"
 
-static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
-                             unsigned long offset, unsigned long head)
-{
-       unsigned long sz = perf_data_size(rb);
-       unsigned long mask = sz - 1;
-
-       /*
-        * check if user-writable
-        * overwrite : over-write its own tail
-        * !overwrite: buffer possibly drops events.
-        */
-       if (rb->overwrite)
-               return true;
-
-       /*
-        * verify that payload is not bigger than buffer
-        * otherwise masking logic may fail to detect
-        * the "not enough space" condition
-        */
-       if ((head - offset) > sz)
-               return false;
-
-       offset = (offset - tail) & mask;
-       head   = (head   - tail) & mask;
-
-       if ((int)(head - offset) < 0)
-               return false;
-
-       return true;
-}
-
 static void perf_output_wakeup(struct perf_output_handle *handle)
 {
        atomic_set(&handle->rb->poll, POLL_IN);
@@ -181,9 +151,10 @@ int perf_output_begin(struct perf_output_handle *handle,
                tail = ACCESS_ONCE(rb->user_page->data_tail);
                smp_mb();
                offset = head = local_read(&rb->head);
-               head += size;
-               if (unlikely(!perf_output_space(rb, tail, offset, head)))
+               if (!rb->overwrite &&
+                   unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))
                        goto fail;
+               head += size;
        } while (local_cmpxchg(&rb->head, offset, head) != offset);
 
        if (head - local_read(&rb->wakeup) > rb->watermark)