lkml.org 
[lkml]   [2010]   [Jan]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 1/3 v2] perf_event: fix race in perf_swevent_get_recursion_context()
    It only disable preemption in perf_swevent_get_recursion_context(),
    it can't avoid race of hard-irq and NMI since they are nested that
    will re-enter this path and make the recursion value chaotic

    In this patch, we use atomic operation to avoid it and reduce
    cpu_ctx->recursion size, it also make this patch no need disable
    preemption

    Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
    ---
    include/linux/perf_event.h | 2 +-
    kernel/perf_event.c | 14 ++++----------
    2 files changed, 5 insertions(+), 11 deletions(-)

    diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
    index c6f812e..8474ab0 100644
    --- a/include/linux/perf_event.h
    +++ b/include/linux/perf_event.h
    @@ -730,7 +730,7 @@ struct perf_cpu_context {
    *
    * task, softirq, irq, nmi context
    */
    - int recursion[4];
    + unsigned long recursion;
    };

    struct perf_output_handle {
    diff --git a/kernel/perf_event.c b/kernel/perf_event.c
    index eae6ff6..77ef16e 100644
    --- a/kernel/perf_event.c
    +++ b/kernel/perf_event.c
    @@ -3921,7 +3921,7 @@ static void perf_swevent_ctx_event(struct perf_event_context *ctx,

    int perf_swevent_get_recursion_context(void)
    {
    - struct perf_cpu_context *cpuctx = &get_cpu_var(perf_cpu_context);
    + struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
    int rctx;

    if (in_nmi())
    @@ -3933,13 +3933,8 @@ int perf_swevent_get_recursion_context(void)
    else
    rctx = 0;

    - if (cpuctx->recursion[rctx]) {
    - put_cpu_var(perf_cpu_context);
    + if (test_and_set_bit(rctx, &cpuctx->recursion))
    return -1;
    - }
    -
    - cpuctx->recursion[rctx]++;
    - barrier();

    return rctx;
    }
    @@ -3948,9 +3943,8 @@ EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context);
    void perf_swevent_put_recursion_context(int rctx)
    {
    struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
    - barrier();
    - cpuctx->recursion[rctx]--;
    - put_cpu_var(perf_cpu_context);
    +
    + clear_bit(rctx, &cpuctx->recursion);
    }
    EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context);

    --
    1.6.1.2



    \
     
     \ /
      Last update: 2010-01-19 09:43    [W:0.021 / U:2.016 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site