From: Qais Yousef <qais.yousef@arm.com>
To: Xuewen Yan <xuewen.yan94@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
linux-kernel@vger.kernel.org, Wei Wang <wvw@google.com>,
Jonathan JMChen <Jonathan.JMChen@mediatek.com>,
Hank <han.lin@mediatek.com>, Yun Hsiang <hsiang023167@gmail.com>
Subject: Re: [PATCH 3/7] sched/uclamp: Fix fits_capacity() check in feec()
Date: Thu, 21 Jul 2022 15:19:18 +0100 [thread overview]
Message-ID: <20220721141918.s2xlvrwqvulp6lyb@wubuntu> (raw)
In-Reply-To: <CAB8ipk_mjv6RGAL+2ZY2AKoRrf6LR-d5yJ=4Fz-+DW=aHDOpYQ@mail.gmail.com>
On 07/20/22 15:30, Xuewen Yan wrote:
> Hi Qais
>
> On Thu, Jun 30, 2022 at 3:48 AM Qais Yousef <qais.yousef@arm.com> wrote:
> >
> > As reported by Yun Hsiang [1], if a task has its uclamp_min >= 0.8 * 1024,
> > it'll always pick the previous CPU because fits_capacity() will always
> > return false in this case.
> >
> > The new util_fits_cpu() logic should handle this correctly for us beside
> > more corner cases where similar failures could occur, like when using
> > UCLAMP_MAX.
> >
> > We open code uclamp_rq_util_with() except for the clamp() part,
> > util_fits_cpu() needs the 'raw' values to be passed to it.
> >
> > Also introduce uclamp_rq_{set, get}() shorthand accessors to get uclamp
> > value for the rq. Makes the code more readable and ensures the right
> > rules (use READ_ONCE/WRITE_ONCE) are respected transparently.
> >
> > [1] https://lists.linaro.org/pipermail/eas-dev/2020-July/001488.html
> >
> > Fixes: 1d42509e475c ("sched/fair: Make EAS wakeup placement consider uclamp restrictions")
> > Reported-by: Yun Hsiang <hsiang023167@gmail.com>
> > Signed-off-by: Qais Yousef <qais.yousef@arm.com>
> > ---
> > kernel/sched/core.c | 10 +++++-----
> > kernel/sched/fair.c | 26 ++++++++++++++++++++++++--
> > kernel/sched/sched.h | 40 ++++++++++++++++++++++++++++++++++++++--
> > 3 files changed, 67 insertions(+), 9 deletions(-)
> >
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index d3e2c5a7c1b7..f5dac570d6c5 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -1404,7 +1404,7 @@ static inline void uclamp_idle_reset(struct rq *rq, enum uclamp_id clamp_id,
> > if (!(rq->uclamp_flags & UCLAMP_FLAG_IDLE))
> > return;
> >
> > - WRITE_ONCE(rq->uclamp[clamp_id].value, clamp_value);
> > + uclamp_rq_set(rq, clamp_id, clamp_value);
> > }
> >
> > static inline
> > @@ -1555,8 +1555,8 @@ static inline void uclamp_rq_inc_id(struct rq *rq, struct task_struct *p,
> > if (bucket->tasks == 1 || uc_se->value > bucket->value)
> > bucket->value = uc_se->value;
> >
> > - if (uc_se->value > READ_ONCE(uc_rq->value))
> > - WRITE_ONCE(uc_rq->value, uc_se->value);
> > + if (uc_se->value > uclamp_rq_get(rq, clamp_id))
> > + uclamp_rq_set(rq, clamp_id, uc_se->value);
> > }
> >
> > /*
> > @@ -1622,7 +1622,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p,
> > if (likely(bucket->tasks))
> > return;
> >
> > - rq_clamp = READ_ONCE(uc_rq->value);
> > + rq_clamp = uclamp_rq_get(rq, clamp_id);
> > /*
> > * Defensive programming: this should never happen. If it happens,
> > * e.g. due to future modification, warn and fixup the expected value.
> > @@ -1630,7 +1630,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p,
> > SCHED_WARN_ON(bucket->value > rq_clamp);
> > if (bucket->value >= rq_clamp) {
> > bkt_clamp = uclamp_rq_max_value(rq, clamp_id, uc_se->value);
> > - WRITE_ONCE(uc_rq->value, bkt_clamp);
> > + uclamp_rq_set(rq, clamp_id, bkt_clamp);
> > }
> > }
> >
> > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> > index 313437bea5a2..c80c676ab1bc 100644
> > --- a/kernel/sched/fair.c
> > +++ b/kernel/sched/fair.c
> > @@ -6878,6 +6878,8 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
> > static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
> > {
> > unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX;
> > + unsigned long p_util_min = uclamp_is_used() ? uclamp_eff_value(p, UCLAMP_MIN) : 0;
> > + unsigned long p_util_max = uclamp_is_used() ? uclamp_eff_value(p, UCLAMP_MAX) : 1024;
> > struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
> > int cpu, best_energy_cpu = prev_cpu, target = -1;
> > unsigned long cpu_cap, util, base_energy = 0;
> > @@ -6907,6 +6909,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
> >
> > for (; pd; pd = pd->next) {
> > unsigned long cur_delta, spare_cap, max_spare_cap = 0;
> > + unsigned long rq_util_min, rq_util_max;
> > + unsigned long util_min, util_max;
> > bool compute_prev_delta = false;
> > unsigned long base_energy_pd;
> > int max_spare_cap_cpu = -1;
> > @@ -6927,8 +6931,26 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
> > * much capacity we can get out of the CPU; this is
> > * aligned with sched_cpu_util().
> > */
> > - util = uclamp_rq_util_with(cpu_rq(cpu), util, p);
> > - if (!fits_capacity(util, cpu_cap))
> > + if (uclamp_is_used()) {
> > + if (uclamp_rq_is_idle(cpu_rq(cpu))) {
> > + util_min = p_util_min;
> > + util_max = p_util_max;
> > + } else {
> > + /*
> > + * Open code uclamp_rq_util_with() except for
> > + * the clamp() part. Ie: apply max aggregation
> > + * only. util_fits_cpu() logic requires to
> > + * operate on non clamped util but must use the
> > + * max-aggregated uclamp_{min, max}.
> > + */
> > + rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN);
> > + rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX);
> > +
> > + util_min = max(rq_util_min, p_util_min);
> > + util_max = max(rq_util_max, p_util_max);
> > + }
> > + }
> > + if (!util_fits_cpu(util, util_min, util_max, cpu))
> > continue;
> >
> > if (cpu == prev_cpu) {
> > diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
> > index 9599d2eea3e7..69c4d35988b9 100644
> > --- a/kernel/sched/sched.h
> > +++ b/kernel/sched/sched.h
> > @@ -2907,6 +2907,23 @@ static inline unsigned long cpu_util_rt(struct rq *rq)
> > #ifdef CONFIG_UCLAMP_TASK
> > unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id);
> >
> > +static inline unsigned long uclamp_rq_get(struct rq *rq,
> > + enum uclamp_id clamp_id)
> > +{
> > + return READ_ONCE(rq->uclamp[clamp_id].value);
> > +}
> > +
> > +static inline void uclamp_rq_set(struct rq *rq, enum uclamp_id clamp_id,
> > + unsigned int value)
> > +{
> > + WRITE_ONCE(rq->uclamp[clamp_id].value, value);
> > +}
> > +
> > +static inline bool uclamp_rq_is_idle(struct rq *rq)
> > +{
> > + return rq->uclamp_flags & UCLAMP_FLAG_IDLE;
> > +}
>
> Can you replace the idle judgment in the uclamp_rq_util_with()
> function by the way?
Yep I missed it. Fixed.
Thanks!
--
Qais Yousef
next prev parent reply other threads:[~2022-07-21 14:19 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-29 19:46 [PATCH 0/7] Fix relationship between uclamp and fits_capacity() Qais Yousef
2022-06-29 19:46 ` [PATCH 1/7] sched/uclamp: Fix relationship between uclamp and migration margin Qais Yousef
2022-07-11 12:36 ` Vincent Guittot
2022-07-12 10:23 ` Qais Yousef
2022-07-12 13:21 ` Vincent Guittot
2022-07-12 14:20 ` Qais Yousef
2022-07-13 12:39 ` Vincent Guittot
2022-07-15 10:37 ` Qais Yousef
2022-07-20 7:29 ` Vincent Guittot
2022-07-21 14:04 ` Qais Yousef
2022-07-22 15:13 ` Vincent Guittot
2022-07-27 16:08 ` Qais Yousef
2022-08-04 14:59 ` Qais Yousef
2022-07-20 7:17 ` Xuewen Yan
2022-07-21 10:24 ` Qais Yousef
2022-07-25 11:59 ` Xuewen Yan
2022-07-27 16:25 ` Qais Yousef
2022-08-01 2:46 ` Xuewen Yan
2022-08-02 16:22 ` Qais Yousef
2022-06-29 19:46 ` [PATCH 2/7] sched/uclamp: Make task_fits_capacity() use util_fits_cpu() Qais Yousef
2022-07-11 13:09 ` Vincent Guittot
2022-07-12 10:48 ` Qais Yousef
2022-07-21 14:29 ` Qais Yousef
2022-07-22 8:19 ` Vincent Guittot
2022-07-27 16:05 ` Qais Yousef
2022-08-17 9:48 ` Vincent Guittot
2022-07-20 7:23 ` Xuewen Yan
2022-07-21 14:11 ` Qais Yousef
2022-06-29 19:46 ` [PATCH 3/7] sched/uclamp: Fix fits_capacity() check in feec() Qais Yousef
2022-07-20 7:30 ` Xuewen Yan
2022-07-21 14:19 ` Qais Yousef [this message]
2022-06-29 19:46 ` [PATCH 4/7] sched/uclamp: Make select_idle_capacity() use util_fits_cpu() Qais Yousef
2022-06-29 19:46 ` [PATCH 5/7] sched/uclamp: Make asym_fits_capacity() " Qais Yousef
2022-06-29 19:46 ` [PATCH 6/7] sched/uclamp: Make cpu_overutilized() " Qais Yousef
2022-06-29 19:46 ` [PATCH 7/7] sched/uclamp: Cater for uclamp in find_energy_efficient_cpu()'s early exit condition Qais Yousef
2022-07-20 7:39 ` Xuewen Yan
2022-07-21 14:24 ` Qais Yousef
2022-07-22 1:09 ` Xuewen Yan
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=20220721141918.s2xlvrwqvulp6lyb@wubuntu \
--to=qais.yousef@arm.com \
--cc=Jonathan.JMChen@mediatek.com \
--cc=dietmar.eggemann@arm.com \
--cc=han.lin@mediatek.com \
--cc=hsiang023167@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=vincent.guittot@linaro.org \
--cc=wvw@google.com \
--cc=xuewen.yan94@gmail.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.