From: Peter Zijlstra <peterz@infradead.org>
To: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Ingo Molnar <mingo@redhat.com>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
linux-kernel@vger.kernel.org,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Daniel Bristot de Oliveira <bristot@redhat.com>,
Valentin Schneider <vschneid@redhat.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
Imran Khan <imran.f.khan@oracle.com>,
Leonardo Bras <leobras@redhat.com>, Guo Ren <guoren@kernel.org>,
Rik van Riel <riel@surriel.com>, Tejun Heo <tj@kernel.org>,
Cruz Zhao <CruzZhao@linux.alibaba.com>,
Lai Jiangshan <jiangshanlai@gmail.com>,
Joel Fernandes <joel@joelfernandes.org>,
Zqiang <qiang.zhang1211@gmail.com>,
Julia Lawall <julia.lawall@inria.fr>,
"Gautham R. Shenoy" <gautham.shenoy@amd.com>
Subject: Re: [PATCH 1/3] sched/core: Remove the unnecessary need_resched() check in nohz_csd_func()
Date: Wed, 10 Jul 2024 16:53:20 +0200 [thread overview]
Message-ID: <20240710145320.GA27299@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20240710090210.41856-2-kprateek.nayak@amd.com>
On Wed, Jul 10, 2024 at 09:02:08AM +0000, K Prateek Nayak wrote:
> The need_resched() check currently in nohz_csd_func() can be tracked
> to have been added in scheduler_ipi() back in 2011 via commit
> ca38062e57e9 ("sched: Use resched IPI to kick off the nohz idle balance")
>
> Since then, it has travelled quite a bit but it seems like an idle_cpu()
> check currently is sufficient to detect the need to bail out from an
> idle load balancing. To justify this removal, consider all the following
> case where an idle load balancing could race with a task wakeup:
>
> o Since commit f3dd3f674555b ("sched: Remove the limitation of WF_ON_CPU
> on wakelist if wakee cpu is idle") a target perceived to be idle
> (target_rq->nr_running == 0) will return true for
> ttwu_queue_cond(target) which will offload the task wakeup to the idle
> target via an IPI.
>
> In all such cases target_rq->ttwu_pending will be set to 1 before
> queuing the wake function.
>
> If an idle load balance races here, following scenarios are possible:
>
> - The CPU is not in TIF_POLLING_NRFLAG mode in which case an actual
> IPI is sent to the CPU to wake it out of idle. If the
> nohz_csd_func() queues before sched_ttwu_pending(), the idle load
> balance will bail out since idle_cpu(target) returns 0 since
> target_rq->ttwu_pending is 1. If the nohz_csd_func() is queued after
> sched_ttwu_pending() it should see rq->nr_running to be non-zero and
> bail out of idle load balancing.
>
> - The CPU is in TIF_POLLING_NRFLAG mode and instead of an actual IPI,
> the sender will simply set TIF_NEED_RESCHED for the target to put it
> out of idle and flush_smp_call_function_queue() in do_idle() will
> execute the call function. Depending on the ordering of the queuing
> of nohz_csd_func() and sched_ttwu_pending(), the idle_cpu() check in
> nohz_csd_func() should either see target_rq->ttwu_pending = 1 or
> target_rq->nr_running to be non-zero if there is a genuine task
> wakeup racing with the idle load balance kick.
For completion sake, we should also consider the !TTWU_QUEUE case, this
configuration is default for PREEMPT_RT, where the wake_list is a source
of non-determinism.
In quick reading I think that case should be fine, since we directly
enqueue remotely and ->nr_running adjusts accordingly, but it is late in
the day and I'm easily mistaken.
> o The waker CPU perceives the target CPU to be busy
> (targer_rq->nr_running != 0) but the CPU is in fact going idle and due
> to a series of unfortunate events, the system reaches a case where the
> waker CPU decides to perform the wakeup by itself in ttwu_queue() on
> the target CPU but target is concurrently selected for idle load
> balance (Can this happen? I'm not sure, but we'll consider its
> possibility to estimate the worst case scenario).
>
> ttwu_do_activate() calls enqueue_task() which would increment
> "rq->nr_running" post which it calls wakeup_preempt() which is
> responsible for setting TIF_NEED_RESCHED (via a resched IPI or by
> setting TIF_NEED_RESCHED on a TIF_POLLING_NRFLAG idle CPU) The key
> thing to note in this case is that rq->nr_running is already non-zero
> in case of a wakeup before TIF_NEED_RESCHED is set which would
> lead to idle_cpu() check returning false.
>
> In all cases, it seems that need_resched() check is unnecessary when
> checking for idle_cpu() first since an impending wakeup racing with idle
> load balancer will either set the "rq->ttwu_pending" or indicate a newly
> woken task via "rq->nr_running".
Right.
> Chasing the reason why this check might have existed in the first place,
> I came across Peter's suggestion on the fist iteration of Suresh's
> patch from 2011 [1] where the condition to raise the SCHED_SOFTIRQ was:
>
> sched_ttwu_do_pending(list);
>
> if (unlikely((rq->idle == current) &&
> rq->nohz_balance_kick &&
> !need_resched()))
> raise_softirq_irqoff(SCHED_SOFTIRQ);
>
> However, since this was preceded by sched_ttwu_do_pending() which is
> equivalent of sched_ttwu_pending() in the current upstream kernel, the
> need_resched() check was necessary to catch a newly queued task. Peter
> suggested modifying it to:
>
> if (idle_cpu() && rq->nohz_balance_kick && !need_resched())
> raise_softirq_irqoff(SCHED_SOFTIRQ);
>
> where idle_cpu() seems to have replaced "rq->idle == current" check.
> However, even back then, the idle_cpu() check would have been sufficient
> to have caught the enqueue of a new task and since commit b2a02fc43a1f
> ("smp: Optimize send_call_function_single_ipi()") overloads the
> interpretation of TIF_NEED_RESCHED for TIF_POLLING_NRFLAG idling, remove
> the need_resched() check in nohz_csd_func() to raise SCHED_SOFTIRQ based
> on Peter's suggestion.
... sooo many years ago :-)
> Link: https://lore.kernel.org/all/1317670590.20367.38.camel@twins/ [1]
> Link: https://lore.kernel.org/lkml/20240615014521.GR8774@noisy.programming.kicks-ass.net/
> Fixes: b2a02fc43a1f ("smp: Optimize send_call_function_single_ipi()")
> Suggested-by: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
> ---
> kernel/sched/core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index 0935f9d4bb7b..1e0c77eac65a 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -1205,7 +1205,7 @@ static void nohz_csd_func(void *info)
> WARN_ON(!(flags & NOHZ_KICK_MASK));
>
> rq->idle_balance = idle_cpu(cpu);
> - if (rq->idle_balance && !need_resched()) {
> + if (rq->idle_balance) {
> rq->nohz_idle_balance = flags;
> raise_softirq_irqoff(SCHED_SOFTIRQ);
> }
> --
> 2.34.1
>
next prev parent reply other threads:[~2024-07-10 14:53 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-10 9:02 [PATCH 0/3] sched/core: Fixes and enhancements around spurious need_resched() and idle load balancing K Prateek Nayak
2024-07-10 9:02 ` [PATCH 1/3] sched/core: Remove the unnecessary need_resched() check in nohz_csd_func() K Prateek Nayak
2024-07-10 14:53 ` Peter Zijlstra [this message]
2024-07-10 17:57 ` K Prateek Nayak
2024-07-23 6:46 ` K Prateek Nayak
2024-07-10 9:02 ` [PATCH 2/3] sched/core: Introduce SM_IDLE and an idle re-entry fast-path in __schedule() K Prateek Nayak
2024-07-11 8:00 ` Vincent Guittot
2024-07-11 9:19 ` Peter Zijlstra
2024-07-11 13:14 ` Vincent Guittot
2024-07-12 6:40 ` K Prateek Nayak
2024-07-30 16:13 ` Chen Yu
2024-08-04 4:05 ` Chen Yu
2024-08-05 4:03 ` K Prateek Nayak
2024-07-10 9:02 ` [RFC PATCH 3/3] softirq: Avoid waking up ksoftirqd from flush_smp_call_function_queue() K Prateek Nayak
2024-07-10 15:05 ` Peter Zijlstra
2024-07-10 18:20 ` K Prateek Nayak
2024-07-23 4:50 ` K Prateek Nayak
2024-07-29 2:42 ` [PATCH 0/3] sched/core: Fixes and enhancements around spurious need_resched() and idle load balancing Chen Yu
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=20240710145320.GA27299@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=CruzZhao@linux.alibaba.com \
--cc=bristot@redhat.com \
--cc=bsegall@google.com \
--cc=dietmar.eggemann@arm.com \
--cc=gautham.shenoy@amd.com \
--cc=guoren@kernel.org \
--cc=imran.f.khan@oracle.com \
--cc=jiangshanlai@gmail.com \
--cc=joel@joelfernandes.org \
--cc=julia.lawall@inria.fr \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=leobras@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=paulmck@kernel.org \
--cc=qiang.zhang1211@gmail.com \
--cc=riel@surriel.com \
--cc=rostedt@goodmis.org \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.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.