lkml.org 
[lkml]   [2014]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 18/20] perf: Allocate ring buffers for inherited per-task kernel events
    Date
    Normally, per-task events can't be inherited parents' ring buffers to
    avoid multiple events contending for the same buffer. And since buffer
    allocation is typically done by the userspace consumer, there is no
    practical interface to allocate new buffers for inherited counters.

    However, for kernel users we can allocate new buffers for inherited
    events as soon as they are created (and also reap them on event
    destruction). This pattern has a number of use cases, such as event
    sample annotation and process core dump annotation.

    When a new event is inherited from a per-task kernel event that has a
    ring buffer, allocate a new buffer for this event so that data from the
    child task is collected and can later be retrieved for sample annotation
    or core dump inclusion. This ring buffer is released when the event is
    freed, for example, when the child task exits.

    Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    ---
    kernel/events/core.c | 9 +++++++++
    kernel/events/internal.h | 11 +++++++++++
    2 files changed, 20 insertions(+)

    diff --git a/kernel/events/core.c b/kernel/events/core.c
    index 5da1bc403f..60e354d668 100644
    --- a/kernel/events/core.c
    +++ b/kernel/events/core.c
    @@ -8267,6 +8267,15 @@ inherit_event(struct perf_event *parent_event,
    = parent_event->overflow_handler_context;

    /*
    + * For per-task kernel events with ring buffers, set_output doesn't
    + * make sense, but we can allocate a new buffer here.
    + */
    + if (parent_event->cpu == -1 && kernel_rb_event(parent_event)) {
    + (void)rb_alloc_kernel(child_event, parent_event->rb->nr_pages,
    + parent_event->rb->aux_nr_pages);
    + }
    +
    + /*
    * Precalculate sample_data sizes
    */
    perf_event__header_size(child_event);
    diff --git a/kernel/events/internal.h b/kernel/events/internal.h
    index 81cb7afec4..373ac012f5 100644
    --- a/kernel/events/internal.h
    +++ b/kernel/events/internal.h
    @@ -122,6 +122,17 @@ static inline unsigned long perf_aux_size(struct ring_buffer *rb)
    return rb->aux_nr_pages << PAGE_SHIFT;
    }

    +static inline bool kernel_rb_event(struct perf_event *event)
    +{
    + /*
    + * Having a ring buffer and not being on any ring buffers' wakeup
    + * list means it was attached by rb_alloc_kernel() and not
    + * ring_buffer_attach(). It's the only case when these two
    + * conditions take place at the same time.
    + */
    + return event->rb && list_empty(&event->rb_entry);
    +}
    +
    #define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \
    static inline unsigned long \
    func_name(struct perf_output_handle *handle, \
    --
    2.1.0


    \
     
     \ /
      Last update: 2014-10-13 16:21    [W:2.520 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site