Skip to content

Commit

Permalink
perf_counter: Simplify and fix task migration counting
Browse files Browse the repository at this point in the history
The task migrations counter was causing rare and hard to decypher
memory corruptions under load. After a day of debugging and bisection
we found that the problem was introduced with:

  3f731ca: perf_counter: Fix cpu migration counter

Turning them off fixes the crashes. Incidentally, the whole
perf_counter_task_migration() logic can be done simpler as well,
by injecting a proper sw-counter event.

This cleanup also fixed the crashes. The precise failure mode is
not completely clear yet, but we are clearly not unhappy about
having a fix ;-)

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Jun 19, 2009
1 parent f597055 commit e5289d4
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 27 deletions.
4 changes: 0 additions & 4 deletions include/linux/perf_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -682,8 +682,6 @@ static inline void perf_counter_mmap(struct vm_area_struct *vma)
extern void perf_counter_comm(struct task_struct *tsk);
extern void perf_counter_fork(struct task_struct *tsk);

extern void perf_counter_task_migration(struct task_struct *task, int cpu);

extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs);

extern int sysctl_perf_counter_paranoid;
Expand Down Expand Up @@ -724,8 +722,6 @@ static inline void perf_counter_mmap(struct vm_area_struct *vma) { }
static inline void perf_counter_comm(struct task_struct *tsk) { }
static inline void perf_counter_fork(struct task_struct *tsk) { }
static inline void perf_counter_init(void) { }
static inline void perf_counter_task_migration(struct task_struct *task,
int cpu) { }
#endif

#endif /* __KERNEL__ */
Expand Down
23 changes: 1 addition & 22 deletions kernel/perf_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ void perf_enable(void)

static void get_ctx(struct perf_counter_context *ctx)
{
atomic_inc(&ctx->refcount);
WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
}

static void free_ctx(struct rcu_head *head)
Expand Down Expand Up @@ -3467,27 +3467,6 @@ static const struct pmu perf_ops_task_clock = {
.read = task_clock_perf_counter_read,
};

/*
* Software counter: cpu migrations
*/
void perf_counter_task_migration(struct task_struct *task, int cpu)
{
struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
struct perf_counter_context *ctx;

perf_swcounter_ctx_event(&cpuctx->ctx, PERF_TYPE_SOFTWARE,
PERF_COUNT_SW_CPU_MIGRATIONS,
1, 1, NULL, 0);

ctx = perf_pin_task_context(task);
if (ctx) {
perf_swcounter_ctx_event(ctx, PERF_TYPE_SOFTWARE,
PERF_COUNT_SW_CPU_MIGRATIONS,
1, 1, NULL, 0);
perf_unpin_context(ctx);
}
}

#ifdef CONFIG_EVENT_PROFILE
void perf_tpcounter_event(int event_id)
{
Expand Down
3 changes: 2 additions & 1 deletion kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1978,7 +1978,8 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
if (task_hot(p, old_rq->clock, NULL))
schedstat_inc(p, se.nr_forced2_migrations);
#endif
perf_counter_task_migration(p, new_cpu);
perf_swcounter_event(PERF_COUNT_SW_CPU_MIGRATIONS,
1, 1, NULL, 0);
}
p->se.vruntime -= old_cfsrq->min_vruntime -
new_cfsrq->min_vruntime;
Expand Down

0 comments on commit e5289d4

Please sign in to comment.