All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Stephane Eranian <eranian@google.com>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu, acme@redhat.com,
	jolsa@redhat.com, kan.liang@intel.com, songliubraving@fb.com,
	irogers@google.com
Subject: Re: [PATCH] perf/core: fix multiplexing event scheduling issue
Date: Mon, 21 Oct 2019 12:05:58 +0200	[thread overview]
Message-ID: <20191021100558.GC1800@hirez.programming.kicks-ass.net> (raw)
In-Reply-To: <20191018002746.149200-1-eranian@google.com>

On Thu, Oct 17, 2019 at 05:27:46PM -0700, Stephane Eranian wrote:
> @@ -2153,6 +2157,7 @@ __perf_remove_from_context(struct perf_event *event,
>  			   void *info)
>  {
>  	unsigned long flags = (unsigned long)info;
> +	int was_necessary = ctx->rotate_necessary;
>  
>  	if (ctx->is_active & EVENT_TIME) {
>  		update_context_time(ctx);
> @@ -2171,6 +2176,37 @@ __perf_remove_from_context(struct perf_event *event,
>  			cpuctx->task_ctx = NULL;
>  		}
>  	}
> +
> +	/*
> +	 * sanity check that event_sched_out() does not and will not
> +	 * change the state of ctx->rotate_necessary
> +	 */
> +	WARN_ON(was_necessary != event->ctx->rotate_necessary);

It doesn't... why is this important to check?

> +	/*
> +	 * if we remove an event AND we were multiplexing then, that means
> +	 * we had more events than we have counters for, and thus, at least,
> +	 * one event was in INACTIVE state. Now, that we removed an event,
> +	 * we need to resched to give a chance to all events to get scheduled,
> +	 * otherwise some may get stuck.
> +	 *
> +	 * By the time this function is called the event is usually in the OFF
> +	 * state.
> +	 * Note that this is not a duplicate of the same code in _perf_event_disable()
> +	 * because the call path are different. Some events may be simply disabled

It is the exact same code twice though; IIRC this C language has a
feature to help with that.

> +	 * others removed. There is a way to get removed and not be disabled first.
> +	 */
> +	if (ctx->rotate_necessary && ctx->nr_events) {
> +		int type = get_event_type(event);
> +		/*
> +		 * In case we removed a pinned event, then we need to
> +		 * resched for both pinned and flexible events. The
> +		 * opposite is not true. A pinned event can never be
> +		 * inactive due to multiplexing.
> +		 */
> +		if (type & EVENT_PINNED)
> +			type |= EVENT_FLEXIBLE;
> +		ctx_resched(cpuctx, cpuctx->task_ctx, type);
> +	}

What you're relying on is that ->rotate_necessary implies ->is_active
and there's pending events. And if we tighten ->rotate_necessary you can
remove the && ->nr_events.

> @@ -2232,6 +2270,35 @@ static void __perf_event_disable(struct perf_event *event,
>  		event_sched_out(event, cpuctx, ctx);
>  
>  	perf_event_set_state(event, PERF_EVENT_STATE_OFF);
> +	/*
> +	 * sanity check that event_sched_out() does not and will not
> +	 * change the state of ctx->rotate_necessary
> +	 */
> +	WARN_ON_ONCE(was_necessary != event->ctx->rotate_necessary);
> +
> +	/*
> +	 * if we disable an event AND we were multiplexing then, that means
> +	 * we had more events than we have counters for, and thus, at least,
> +	 * one event was in INACTIVE state. Now, that we disabled an event,
> +	 * we need to resched to give a chance to all events to be scheduled,
> +	 * otherwise some may get stuck.
> +	 *
> +	 * Note that this is not a duplicate of the same code in
> +	 * __perf_remove_from_context()
> +	 * because events can be disabled without being removed.

It _IS_ a duplicate, it is the _exact_ same code twice. What you're
trying to say is that we need it in both places, but that's something
else entirely.

> +	 */
> +	if (ctx->rotate_necessary && ctx->nr_events) {
> +		int type = get_event_type(event);
> +		/*
> +		 * In case we removed a pinned event, then we need to
> +		 * resched for both pinned and flexible events. The
> +		 * opposite is not true. A pinned event can never be
> +		 * inactive due to multiplexing.
> +		 */
> +		if (type & EVENT_PINNED)
> +			type |= EVENT_FLEXIBLE;
> +		ctx_resched(cpuctx, cpuctx->task_ctx, type);
> +	}
>  }



  parent reply	other threads:[~2019-10-21 10:06 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18  0:27 [PATCH] perf/core: fix multiplexing event scheduling issue Stephane Eranian
2019-10-18  6:13 ` Song Liu
2019-10-18  6:19   ` Stephane Eranian
2019-10-18  6:55     ` Song Liu
2019-10-21 10:05 ` Peter Zijlstra [this message]
2019-10-23  7:06   ` Stephane Eranian
2019-10-23  9:37     ` Peter Zijlstra
2019-10-23 15:29       ` Peter Zijlstra
2019-10-21 10:20 ` Peter Zijlstra
2019-10-23  7:30   ` Stephane Eranian
2019-10-23 11:02     ` Peter Zijlstra
2019-10-23 17:44       ` Stephane Eranian

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191021100558.GC1800@hirez.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=acme@redhat.com \
    --cc=eranian@google.com \
    --cc=irogers@google.com \
    --cc=jolsa@redhat.com \
    --cc=kan.liang@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=songliubraving@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.