diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-17 11:24:08 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-20 00:22:30 +0200 |
commit | c44d70a340554a33071339064a303ac0f1a31623 (patch) | |
tree | a620d5b82a07b2e2c8c7c57d2e81d5bfdcdd4c25 /kernel | |
parent | 33b2fb303fe7f6b08bbb32f708e67b96eaa94a7a (diff) | |
download | op-kernel-dev-c44d70a340554a33071339064a303ac0f1a31623.zip op-kernel-dev-c44d70a340554a33071339064a303ac0f1a31623.tar.gz |
perf_counter: fix counter inheritance race
Context rotation should not occur when we are in the middle of
walking the counter list when inheriting counters ...
[ Impact: fix occasionally incorrect perf stat results ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/perf_counter.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 7af16d1..4d8f973 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1120,7 +1120,8 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu) __perf_counter_task_sched_out(ctx); rotate_ctx(&cpuctx->ctx); - rotate_ctx(ctx); + if (ctx->rr_allowed) + rotate_ctx(ctx); perf_counter_cpu_sched_in(cpuctx, cpu); perf_counter_task_sched_in(curr, cpu); @@ -3108,6 +3109,7 @@ __perf_counter_init_context(struct perf_counter_context *ctx, mutex_init(&ctx->mutex); INIT_LIST_HEAD(&ctx->counter_list); INIT_LIST_HEAD(&ctx->event_list); + ctx->rr_allowed = 1; ctx->task = task; } @@ -3348,6 +3350,9 @@ void perf_counter_init_task(struct task_struct *child) */ mutex_lock(&parent_ctx->mutex); + parent_ctx->rr_allowed = 0; + barrier(); /* irqs */ + /* * We dont have to disable NMIs - we are only looking at * the list, not manipulating it: @@ -3361,6 +3366,9 @@ void perf_counter_init_task(struct task_struct *child) break; } + barrier(); /* irqs */ + parent_ctx->rr_allowed = 1; + mutex_unlock(&parent_ctx->mutex); } |