Re: [RFC][PATCH 4/7] perf: Fix scaling vs enable_on_exec
From: Peter Zijlstra
Date: Tue Feb 23 2016 - 10:29:37 EST
On Fri, Feb 19, 2016 at 03:37:47PM +0100, Peter Zijlstra wrote:
> Oleg reported that enable_on_exec results in weird scale factors.
>
> The recent commit 3e349507d12d ("perf: Fix perf_enable_on_exec() event
> scheduling") caused this by moving task_ctx_sched_out() from before
> __perf_event_mask_enable() to after it.
>
> The overlooked concequence of that change is that task_ctx_sched_out()
> would update the ctx time fields, and now __perf_event_mask_enable()
> uses stale time.
>
> Fix this by adding an explicit time update.
>
> While looking at this, I also found that we need an ctx->is_active
> check in perf_install_in_context().
>
> XXX: does this actually fix the reported issue? I'm not sure what the
> reproduction case is. Also an earlier version made Jiri's machine
> explode -- something I've not managed to reproduce either.
Jiri, can you have a look at this and perhaps share the reproducer?
> Fixes: 3e349507d12d ("perf: Fix perf_enable_on_exec() event scheduling")
> Reported-by: Oleg Nesterov <oleg@xxxxxxxxxx>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
> ---
> kernel/events/core.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -2170,12 +2170,12 @@ perf_install_in_context(struct perf_even
> raw_spin_unlock_irq(&ctx->lock);
> return;
> }
> - update_context_time(ctx);
> - /*
> - * Update cgrp time only if current cgrp matches event->cgrp.
> - * Must be done before calling add_event_to_ctx().
> - */
> - update_cgrp_time_from_event(event);
> +
> + if (ctx->is_active) {
> + update_context_time(ctx);
> + update_cgrp_time_from_event(event);
> + }
> +
> add_event_to_ctx(event, ctx);
> raw_spin_unlock_irq(&ctx->lock);
>
> @@ -3122,6 +3122,12 @@ static void perf_event_enable_on_exec(in
>
> cpuctx = __get_cpu_context(ctx);
> perf_ctx_lock(cpuctx, ctx);
> +
> + if (ctx->is_active) {
> + update_context_time(ctx);
> + update_cgrp_time_from_cpuctx(cpuctx);
> + }
> +
> list_for_each_entry(event, &ctx->event_list, event_entry)
> enabled |= event_enable_on_exec(event, ctx);
>
>
>