Re: [PATCH V3 1/2] sched/core: Rename and move schedutil_cpu_util() to core.c

2020-11-23 Thread Rafael J. Wysocki
On Mon, Nov 23, 2020 at 11:05 AM Viresh Kumar  wrote:
>
> On 19-11-20, 13:30, Rafael J. Wysocki wrote:
> > On Thu, Nov 19, 2020 at 8:38 AM Viresh Kumar  
> > wrote:
> > >
> > > There is nothing schedutil specific in schedutil_cpu_util(), move it to
> > > core.c and rename it to sched_cpu_util(), so it can be used from other
> > > parts of the kernel as well.
> >
> > The patch does more than this, though.
> >
> > I would do that in two patches: (1) move the function as is and (2)
> > rename it and rearrange the users.
>
> Sure.
>
> > >  static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu)
> > >  {
> > > -   struct rq *rq = cpu_rq(sg_cpu->cpu);
> > > -   unsigned long util = cpu_util_cfs(rq);
> > > -   unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu);
> > > -
> > > -   sg_cpu->max = max;
> > > -   sg_cpu->bw_dl = cpu_bw_dl(rq);
> > > +   sg_cpu->max = arch_scale_cpu_capacity(sg_cpu->cpu);
> > > +   sg_cpu->bw_dl = cpu_bw_dl(cpu_rq(sg_cpu->cpu));
> > >
> > > -   return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, 
> > > NULL);
> > > +   return sched_cpu_util(sg_cpu->cpu, FREQUENCY_UTIL, sg_cpu->max);
> >
> > I don't see much value in using this wrapper here TBH and it
> > introduces an otherwise redundant cpu_rq() computation.
>
> You want to call effective_cpu_util() here instead, right ?

Right.


Re: [PATCH V3 1/2] sched/core: Rename and move schedutil_cpu_util() to core.c

2020-11-23 Thread Viresh Kumar
On 19-11-20, 13:30, Rafael J. Wysocki wrote:
> On Thu, Nov 19, 2020 at 8:38 AM Viresh Kumar  wrote:
> >
> > There is nothing schedutil specific in schedutil_cpu_util(), move it to
> > core.c and rename it to sched_cpu_util(), so it can be used from other
> > parts of the kernel as well.
> 
> The patch does more than this, though.
> 
> I would do that in two patches: (1) move the function as is and (2)
> rename it and rearrange the users.

Sure.

> >  static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu)
> >  {
> > -   struct rq *rq = cpu_rq(sg_cpu->cpu);
> > -   unsigned long util = cpu_util_cfs(rq);
> > -   unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu);
> > -
> > -   sg_cpu->max = max;
> > -   sg_cpu->bw_dl = cpu_bw_dl(rq);
> > +   sg_cpu->max = arch_scale_cpu_capacity(sg_cpu->cpu);
> > +   sg_cpu->bw_dl = cpu_bw_dl(cpu_rq(sg_cpu->cpu));
> >
> > -   return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, 
> > NULL);
> > +   return sched_cpu_util(sg_cpu->cpu, FREQUENCY_UTIL, sg_cpu->max);
> 
> I don't see much value in using this wrapper here TBH and it
> introduces an otherwise redundant cpu_rq() computation.

You want to call effective_cpu_util() here instead, right ?

-- 
viresh


Re: [PATCH V3 1/2] sched/core: Rename and move schedutil_cpu_util() to core.c

2020-11-19 Thread Rafael J. Wysocki
On Thu, Nov 19, 2020 at 8:38 AM Viresh Kumar  wrote:
>
> There is nothing schedutil specific in schedutil_cpu_util(), move it to
> core.c and rename it to sched_cpu_util(), so it can be used from other
> parts of the kernel as well.

The patch does more than this, though.

I would do that in two patches: (1) move the function as is and (2)
rename it and rearrange the users.

> The cpufreq_cooling stuff will make use of this in a later commit.
>
> Signed-off-by: Viresh Kumar 
> ---
>  include/linux/sched.h|  21 ++
>  kernel/sched/core.c  | 115 ++
>  kernel/sched/cpufreq_schedutil.c | 116 +--
>  kernel/sched/fair.c  |   6 +-
>  kernel/sched/sched.h |  31 +
>  5 files changed, 145 insertions(+), 144 deletions(-)
>
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 063cd120b459..926b944dae5e 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1926,6 +1926,27 @@ extern long sched_getaffinity(pid_t pid, struct 
> cpumask *mask);
>  #define TASK_SIZE_OF(tsk)  TASK_SIZE
>  #endif
>
> +#ifdef CONFIG_SMP
> +/**
> + * enum cpu_util_type - CPU utilization type
> + * @FREQUENCY_UTIL:Utilization used to select frequency
> + * @ENERGY_UTIL:   Utilization used during energy calculation
> + *
> + * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time
> + * need to be aggregated differently depending on the usage made of them. 
> This
> + * enum is used within sched_cpu_util() to differentiate the types of
> + * utilization expected by the callers, and adjust the aggregation 
> accordingly.
> + */
> +enum cpu_util_type {
> +   FREQUENCY_UTIL,
> +   ENERGY_UTIL,
> +};
> +
> +/* Returns effective CPU utilization, as seen by the scheduler */
> +unsigned long sched_cpu_util(int cpu, enum cpu_util_type type,
> +unsigned long max);
> +#endif /* CONFIG_SMP */
> +
>  #ifdef CONFIG_RSEQ
>
>  /*
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index d2003a7d5ab5..845c976ccd53 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -5117,6 +5117,121 @@ struct task_struct *idle_task(int cpu)
> return cpu_rq(cpu)->idle;
>  }
>
> +#ifdef CONFIG_SMP
> +/*
> + * This function computes an effective utilization for the given CPU, to be
> + * used for frequency selection given the linear relation: f = u * f_max.
> + *
> + * The scheduler tracks the following metrics:
> + *
> + *   cpu_util_{cfs,rt,dl,irq}()
> + *   cpu_bw_dl()
> + *
> + * Where the cfs,rt and dl util numbers are tracked with the same metric and
> + * synchronized windows and are thus directly comparable.
> + *
> + * The cfs,rt,dl utilization are the running times measured with 
> rq->clock_task
> + * which excludes things like IRQ and steal-time. These latter are then 
> accrued
> + * in the irq utilization.
> + *
> + * The DL bandwidth number otoh is not a measured metric but a value computed
> + * based on the task model parameters and gives the minimal utilization
> + * required to meet deadlines.
> + */
> +unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
> +unsigned long max, enum cpu_util_type type,
> +struct task_struct *p)
> +{
> +   unsigned long dl_util, util, irq;
> +   struct rq *rq = cpu_rq(cpu);
> +
> +   if (!uclamp_is_used() &&
> +   type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
> +   return max;
> +   }
> +
> +   /*
> +* Early check to see if IRQ/steal time saturates the CPU, can be
> +* because of inaccuracies in how we track these -- see
> +* update_irq_load_avg().
> +*/
> +   irq = cpu_util_irq(rq);
> +   if (unlikely(irq >= max))
> +   return max;
> +
> +   /*
> +* Because the time spend on RT/DL tasks is visible as 'lost' time to
> +* CFS tasks and we use the same metric to track the effective
> +* utilization (PELT windows are synchronized) we can directly add 
> them
> +* to obtain the CPU's actual utilization.
> +*
> +* CFS and RT utilization can be boosted or capped, depending on
> +* utilization clamp constraints requested by currently RUNNABLE
> +* tasks.
> +* When there are no CFS RUNNABLE tasks, clamps are released and
> +* frequency will be gracefully reduced with the utilization decay.
> +*/
> +   util = util_cfs + cpu_util_rt(rq);
> +   if (type == FREQUENCY_UTIL)
> +   util = uclamp_rq_util_with(rq, util, p);
> +
> +   dl_util = cpu_util_dl(rq);
> +
> +   /*
> +* For frequency selection we do not make cpu_util_dl() a permanent 
> part
> +* of this sum because we want to use cpu_bw_dl() later on, but we 
> need
> +* to check if the CFS+RT+DL sum is saturated (ie. no idle ti

[PATCH V3 1/2] sched/core: Rename and move schedutil_cpu_util() to core.c

2020-11-18 Thread Viresh Kumar
There is nothing schedutil specific in schedutil_cpu_util(), move it to
core.c and rename it to sched_cpu_util(), so it can be used from other
parts of the kernel as well.

The cpufreq_cooling stuff will make use of this in a later commit.

Signed-off-by: Viresh Kumar 
---
 include/linux/sched.h|  21 ++
 kernel/sched/core.c  | 115 ++
 kernel/sched/cpufreq_schedutil.c | 116 +--
 kernel/sched/fair.c  |   6 +-
 kernel/sched/sched.h |  31 +
 5 files changed, 145 insertions(+), 144 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 063cd120b459..926b944dae5e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1926,6 +1926,27 @@ extern long sched_getaffinity(pid_t pid, struct cpumask 
*mask);
 #define TASK_SIZE_OF(tsk)  TASK_SIZE
 #endif
 
+#ifdef CONFIG_SMP
+/**
+ * enum cpu_util_type - CPU utilization type
+ * @FREQUENCY_UTIL:Utilization used to select frequency
+ * @ENERGY_UTIL:   Utilization used during energy calculation
+ *
+ * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time
+ * need to be aggregated differently depending on the usage made of them. This
+ * enum is used within sched_cpu_util() to differentiate the types of
+ * utilization expected by the callers, and adjust the aggregation accordingly.
+ */
+enum cpu_util_type {
+   FREQUENCY_UTIL,
+   ENERGY_UTIL,
+};
+
+/* Returns effective CPU utilization, as seen by the scheduler */
+unsigned long sched_cpu_util(int cpu, enum cpu_util_type type,
+unsigned long max);
+#endif /* CONFIG_SMP */
+
 #ifdef CONFIG_RSEQ
 
 /*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index d2003a7d5ab5..845c976ccd53 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5117,6 +5117,121 @@ struct task_struct *idle_task(int cpu)
return cpu_rq(cpu)->idle;
 }
 
+#ifdef CONFIG_SMP
+/*
+ * This function computes an effective utilization for the given CPU, to be
+ * used for frequency selection given the linear relation: f = u * f_max.
+ *
+ * The scheduler tracks the following metrics:
+ *
+ *   cpu_util_{cfs,rt,dl,irq}()
+ *   cpu_bw_dl()
+ *
+ * Where the cfs,rt and dl util numbers are tracked with the same metric and
+ * synchronized windows and are thus directly comparable.
+ *
+ * The cfs,rt,dl utilization are the running times measured with rq->clock_task
+ * which excludes things like IRQ and steal-time. These latter are then accrued
+ * in the irq utilization.
+ *
+ * The DL bandwidth number otoh is not a measured metric but a value computed
+ * based on the task model parameters and gives the minimal utilization
+ * required to meet deadlines.
+ */
+unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
+unsigned long max, enum cpu_util_type type,
+struct task_struct *p)
+{
+   unsigned long dl_util, util, irq;
+   struct rq *rq = cpu_rq(cpu);
+
+   if (!uclamp_is_used() &&
+   type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
+   return max;
+   }
+
+   /*
+* Early check to see if IRQ/steal time saturates the CPU, can be
+* because of inaccuracies in how we track these -- see
+* update_irq_load_avg().
+*/
+   irq = cpu_util_irq(rq);
+   if (unlikely(irq >= max))
+   return max;
+
+   /*
+* Because the time spend on RT/DL tasks is visible as 'lost' time to
+* CFS tasks and we use the same metric to track the effective
+* utilization (PELT windows are synchronized) we can directly add them
+* to obtain the CPU's actual utilization.
+*
+* CFS and RT utilization can be boosted or capped, depending on
+* utilization clamp constraints requested by currently RUNNABLE
+* tasks.
+* When there are no CFS RUNNABLE tasks, clamps are released and
+* frequency will be gracefully reduced with the utilization decay.
+*/
+   util = util_cfs + cpu_util_rt(rq);
+   if (type == FREQUENCY_UTIL)
+   util = uclamp_rq_util_with(rq, util, p);
+
+   dl_util = cpu_util_dl(rq);
+
+   /*
+* For frequency selection we do not make cpu_util_dl() a permanent part
+* of this sum because we want to use cpu_bw_dl() later on, but we need
+* to check if the CFS+RT+DL sum is saturated (ie. no idle time) such
+* that we select f_max when there is no idle time.
+*
+* NOTE: numerical errors or stop class might cause us to not quite hit
+* saturation when we should -- something for later.
+*/
+   if (util + dl_util >= max)
+   return max;
+
+   /*
+* OTOH, for energy computation we need the estimated running time, so
+* include util_dl and ignore dl_bw.
+*/
+