lkml.org 
[lkml]   [2010]   [May]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/4] perf: Add exclude_task perf event attribute
    Date
    Excluding is useful when you want to trace only hard and softirqs.

    For this we use a new generic perf_exclude_event() (the previous
    one beeing turned into perf_exclude_swevent) to which you can pass
    the preemption offset to which your events trigger.

    Computing preempt_count() - offset gives us the preempt_count() of
    the context that the event has interrupted, on top of which we
    can filter the non-irq contexts.

    Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Paul Mackerras <paulus@samba.org>
    ---
    include/linux/perf_event.h | 3 ++-
    kernel/perf_event.c | 41 ++++++++++++++++++++++++++++++++++-------
    2 files changed, 36 insertions(+), 8 deletions(-)

    diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
    index fe50347..d939fc7 100644
    --- a/include/linux/perf_event.h
    +++ b/include/linux/perf_event.h
    @@ -214,8 +214,9 @@ struct perf_event_attr {
    * See also PERF_RECORD_MISC_EXACT_IP
    */
    precise_ip : 2, /* skid constraint */
    + exclude_task : 1, /* don't count task context */

    - __reserved_1 : 47;
    + __reserved_1 : 46;

    union {
    __u32 wakeup_events; /* wakeup every n events */
    diff --git a/kernel/perf_event.c b/kernel/perf_event.c
    index 45b7aec..ab96411 100644
    --- a/kernel/perf_event.c
    +++ b/kernel/perf_event.c
    @@ -3907,10 +3907,33 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
    return ret;
    }

    +static bool
    +perf_exclude_event(struct perf_event *event, int offset)
    +{
    + if (!in_interrupt_offset(preempt_count() - offset)) {
    + if (event->attr.exclude_task)
    + return true;
    + }
    +
    + return false;
    +}
    +
    int perf_event_overflow(struct perf_event *event, int nmi,
    struct perf_sample_data *data,
    struct pt_regs *regs)
    {
    + int offset = HARDIRQ_OFFSET;
    +
    + if (nmi)
    + offset += NMI_OFFSET;
    + /*
    + * Hardware events trigger on NMI or simple hardirq, which offset we
    + * need to substract to get the preempt_count() of the interrupted
    + * context.
    + */
    + if (perf_exclude_event(event, offset))
    + return 0;
    +
    return __perf_event_overflow(event, nmi, 1, data, regs);
    }

    @@ -4008,8 +4031,8 @@ static void perf_swevent_add(struct perf_event *event, u64 nr,
    static int perf_tp_event_match(struct perf_event *event,
    struct perf_sample_data *data);

    -static int perf_exclude_event(struct perf_event *event,
    - struct pt_regs *regs)
    +static int perf_exclude_swevent(struct perf_event *event,
    + struct pt_regs *regs, int offset)
    {
    if (regs) {
    if (event->attr.exclude_user && user_mode(regs))
    @@ -4019,7 +4042,7 @@ static int perf_exclude_event(struct perf_event *event,
    return 1;
    }

    - return 0;
    + return perf_exclude_event(event, offset);
    }

    static int perf_swevent_match(struct perf_event *event,
    @@ -4034,7 +4057,7 @@ static int perf_swevent_match(struct perf_event *event,
    if (event->attr.config != event_id)
    return 0;

    - if (perf_exclude_event(event, regs))
    + if (perf_exclude_swevent(event, regs, 0))
    return 0;

    if (event->attr.type == PERF_TYPE_TRACEPOINT &&
    @@ -4230,9 +4253,13 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
    data.period = event->hw.last_period;
    regs = get_irq_regs();

    - if (regs && !perf_exclude_event(event, regs)) {
    + /*
    + * we are in hardirq, so we need to substract our preempt offset
    + * to retrieve the interrupted one
    + */
    + if (regs && !perf_exclude_swevent(event, regs, HARDIRQ_OFFSET)) {
    if (!(event->attr.exclude_idle && current->pid == 0))
    - if (perf_event_overflow(event, 0, &data, regs))
    + if (__perf_event_overflow(event, 0, 1, &data, regs))
    ret = HRTIMER_NORESTART;
    }

    @@ -4624,7 +4651,7 @@ void perf_bp_event(struct perf_event *bp, void *data)

    perf_sample_data_init(&sample, bp->attr.bp_addr);

    - if (!perf_exclude_event(bp, regs))
    + if (!perf_exclude_swevent(bp, regs, 0))
    perf_swevent_add(bp, 1, 1, &sample, regs);
    }
    #else
    --
    1.6.2.3


    \
     
     \ /
      Last update: 2010-05-21 16:13    [W:0.024 / U:183.808 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site