Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b58f6b0d authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

perf, core: Fix initial task_ctx/event installation



A lost Quilt refresh of 2c29ef0f (perf: Simplify and fix
__perf_install_in_context()) is causing grief and lockups,
reported by Jiri Olsa.

When installing an event in a task context, there's a number of
issues:

 - there might not be an existing task context, in which case
   we should install the now current context;

 - there might already be a context, not the current one, in
   which case we should de-schedule the old and install the new;

these cases were dealt with in the lost refresh, however there is one
further case that was found in testing:

 - there might already be a context, the current one, in which
   case we should still de-schedule, and should take care
   to re-install it (note that task_ctx_sched_out() clears
   cpuctx->task_ctx).

Reported-by: default avatarJiri Olsa <jolsa@redhat.com>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1307399008.2497.971.camel@laptop


Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 3ce2a0bc
Loading
Loading
Loading
Loading
+17 −11
Original line number Original line Diff line number Diff line
@@ -1505,25 +1505,31 @@ static int __perf_install_in_context(void *info)
	struct perf_event_context *task_ctx = cpuctx->task_ctx;
	struct perf_event_context *task_ctx = cpuctx->task_ctx;
	struct task_struct *task = current;
	struct task_struct *task = current;


	perf_ctx_lock(cpuctx, cpuctx->task_ctx);
	perf_ctx_lock(cpuctx, task_ctx);
	perf_pmu_disable(cpuctx->ctx.pmu);
	perf_pmu_disable(cpuctx->ctx.pmu);


	/*
	/*
	 * If there was an active task_ctx schedule it out.
	 * If there was an active task_ctx schedule it out.
	 */
	 */
	if (task_ctx) {
	if (task_ctx)
		task_ctx_sched_out(task_ctx);
		task_ctx_sched_out(task_ctx);

	/*
	/*
	 * If the context we're installing events in is not the
	 * If the context we're installing events in is not the
	 * active task_ctx, flip them.
	 * active task_ctx, flip them.
	 */
	 */
	if (ctx->task && task_ctx != ctx) {
	if (ctx->task && task_ctx != ctx) {
			raw_spin_unlock(&cpuctx->ctx.lock);
		if (task_ctx)
			raw_spin_unlock(&task_ctx->lock);
		raw_spin_lock(&ctx->lock);
		raw_spin_lock(&ctx->lock);
			cpuctx->task_ctx = task_ctx = ctx;
		task_ctx = ctx;
	}
	}

	if (task_ctx) {
		cpuctx->task_ctx = task_ctx;
		task = task_ctx->task;
		task = task_ctx->task;
	}
	}

	cpu_ctx_sched_out(cpuctx, EVENT_ALL);
	cpu_ctx_sched_out(cpuctx, EVENT_ALL);


	update_context_time(ctx);
	update_context_time(ctx);