Skip to content

Commit

Permalink
perf_counter: fix counter inheritance race
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ingo Molnar committed May 19, 2009
1 parent 33b2fb3 commit c44d70a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/linux/perf_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ struct perf_counter_context {
int nr_counters;
int nr_active;
int is_active;
int rr_allowed;
struct task_struct *task;

/*
Expand Down
10 changes: 9 additions & 1 deletion kernel/perf_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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:
Expand All @@ -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);
}

Expand Down

0 comments on commit c44d70a

Please sign in to comment.