lkml.org 
[lkml]   [2009]   [Apr]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 06/15] perf_counter: theres more to overflow than writing events
    Prepare for more generic overflow handling. The new perf_counter_overflow()
    method will handle the generic bits of the counter overflow, and can return
    a !0 return value, in which case the counter should be (soft) disabled, so
    that it won't count until it's properly disabled.

    XXX: do powerpc and swcounter

    Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    ---
    arch/powerpc/kernel/perf_counter.c | 2 +-
    arch/x86/kernel/cpu/perf_counter.c | 3 ++-
    include/linux/perf_counter.h | 4 ++--
    kernel/perf_counter.c | 29 +++++++++++++++++++++++------
    4 files changed, 28 insertions(+), 10 deletions(-)

    Index: linux-2.6/arch/powerpc/kernel/perf_counter.c
    ===================================================================
    --- linux-2.6.orig/arch/powerpc/kernel/perf_counter.c
    +++ linux-2.6/arch/powerpc/kernel/perf_counter.c
    @@ -732,7 +732,7 @@ static void record_and_restart(struct pe
    * Finally record data if requested.
    */
    if (record)
    - perf_counter_output(counter, 1, regs);
    + perf_counter_overflow(counter, 1, regs);
    }

    /*
    Index: linux-2.6/arch/x86/kernel/cpu/perf_counter.c
    ===================================================================
    --- linux-2.6.orig/arch/x86/kernel/cpu/perf_counter.c
    +++ linux-2.6/arch/x86/kernel/cpu/perf_counter.c
    @@ -800,7 +800,8 @@ again:
    continue;

    perf_save_and_restart(counter);
    - perf_counter_output(counter, nmi, regs);
    + if (perf_counter_overflow(counter, nmi, regs))
    + __pmc_generic_disable(counter, &counter->hw, bit);
    }

    hw_perf_ack_status(ack);
    Index: linux-2.6/include/linux/perf_counter.h
    ===================================================================
    --- linux-2.6.orig/include/linux/perf_counter.h
    +++ linux-2.6/include/linux/perf_counter.h
    @@ -491,8 +491,8 @@ extern int hw_perf_group_sched_in(struct
    struct perf_counter_context *ctx, int cpu);
    extern void perf_counter_update_userpage(struct perf_counter *counter);

    -extern void perf_counter_output(struct perf_counter *counter,
    - int nmi, struct pt_regs *regs);
    +extern int perf_counter_overflow(struct perf_counter *counter,
    + int nmi, struct pt_regs *regs);
    /*
    * Return 1 for a software counter, 0 for a hardware counter
    */
    Index: linux-2.6/kernel/perf_counter.c
    ===================================================================
    --- linux-2.6.orig/kernel/perf_counter.c
    +++ linux-2.6/kernel/perf_counter.c
    @@ -1800,8 +1800,8 @@ static void perf_output_end(struct perf_
    rcu_read_unlock();
    }

    -void perf_counter_output(struct perf_counter *counter,
    - int nmi, struct pt_regs *regs)
    +static void perf_counter_output(struct perf_counter *counter,
    + int nmi, struct pt_regs *regs)
    {
    int ret;
    u64 record_type = counter->hw_event.record_type;
    @@ -2034,6 +2034,17 @@ void perf_counter_munmap(unsigned long a
    }

    /*
    + * Generic counter overflow handling.
    + */
    +
    +int perf_counter_overflow(struct perf_counter *counter,
    + int nmi, struct pt_regs *regs)
    +{
    + perf_counter_output(counter, nmi, regs);
    + return 0;
    +}
    +
    +/*
    * Generic software counter infrastructure
    */

    @@ -2077,6 +2088,7 @@ static void perf_swcounter_set_period(st

    static enum hrtimer_restart perf_swcounter_hrtimer(struct hrtimer *hrtimer)
    {
    + enum hrtimer_restart ret = HRTIMER_RESTART;
    struct perf_counter *counter;
    struct pt_regs *regs;

    @@ -2092,12 +2104,14 @@ static enum hrtimer_restart perf_swcount
    !counter->hw_event.exclude_user)
    regs = task_pt_regs(current);

    - if (regs)
    - perf_counter_output(counter, 0, regs);
    + if (regs) {
    + if (perf_counter_overflow(counter, 0, regs))
    + ret = HRTIMER_NORESTART;
    + }

    hrtimer_forward_now(hrtimer, ns_to_ktime(counter->hw.irq_period));

    - return HRTIMER_RESTART;
    + return ret;
    }

    static void perf_swcounter_overflow(struct perf_counter *counter,
    @@ -2105,7 +2119,10 @@ static void perf_swcounter_overflow(stru
    {
    perf_swcounter_update(counter);
    perf_swcounter_set_period(counter);
    - perf_counter_output(counter, nmi, regs);
    + if (perf_counter_overflow(counter, nmi, regs))
    + /* soft-disable the counter */
    + ;
    +
    }

    static int perf_swcounter_match(struct perf_counter *counter,
    --



    \
     
     \ /
      Last update: 2009-04-06 11:53    [W:0.028 / U:32.104 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site