sched/core: add forced idle accounting for cgroups
4feee7d126 previously added per-task forced idle accounting. This patch
extends this to also include cgroups.
rstat is used for cgroup accounting, except for the root, which uses
kcpustat in order to bypass the need for doing an rstat flush when
reading root stats.
Only cgroup v2 is supported. Similar to the task accounting, the cgroup
accounting requires that schedstats is enabled.
Signed-off-by: Josh Don <joshdon@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Link: https://lkml.kernel.org/r/20220629211426.3329954-1-joshdon@google.com
This commit is contained in:
+38
-6
@@ -310,6 +310,9 @@ static void cgroup_base_stat_add(struct cgroup_base_stat *dst_bstat,
|
||||
dst_bstat->cputime.utime += src_bstat->cputime.utime;
|
||||
dst_bstat->cputime.stime += src_bstat->cputime.stime;
|
||||
dst_bstat->cputime.sum_exec_runtime += src_bstat->cputime.sum_exec_runtime;
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
dst_bstat->forceidle_sum += src_bstat->forceidle_sum;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cgroup_base_stat_sub(struct cgroup_base_stat *dst_bstat,
|
||||
@@ -318,6 +321,9 @@ static void cgroup_base_stat_sub(struct cgroup_base_stat *dst_bstat,
|
||||
dst_bstat->cputime.utime -= src_bstat->cputime.utime;
|
||||
dst_bstat->cputime.stime -= src_bstat->cputime.stime;
|
||||
dst_bstat->cputime.sum_exec_runtime -= src_bstat->cputime.sum_exec_runtime;
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
dst_bstat->forceidle_sum -= src_bstat->forceidle_sum;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
|
||||
@@ -398,6 +404,11 @@ void __cgroup_account_cputime_field(struct cgroup *cgrp,
|
||||
case CPUTIME_SOFTIRQ:
|
||||
rstatc->bstat.cputime.stime += delta_exec;
|
||||
break;
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
case CPUTIME_FORCEIDLE:
|
||||
rstatc->bstat.forceidle_sum += delta_exec;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -411,8 +422,9 @@ void __cgroup_account_cputime_field(struct cgroup *cgrp,
|
||||
* with how it is done by __cgroup_account_cputime_field for each bit of
|
||||
* cpu time attributed to a cgroup.
|
||||
*/
|
||||
static void root_cgroup_cputime(struct task_cputime *cputime)
|
||||
static void root_cgroup_cputime(struct cgroup_base_stat *bstat)
|
||||
{
|
||||
struct task_cputime *cputime = &bstat->cputime;
|
||||
int i;
|
||||
|
||||
cputime->stime = 0;
|
||||
@@ -438,6 +450,10 @@ static void root_cgroup_cputime(struct task_cputime *cputime)
|
||||
cputime->sum_exec_runtime += user;
|
||||
cputime->sum_exec_runtime += sys;
|
||||
cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL];
|
||||
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
bstat->forceidle_sum += cpustat[CPUTIME_FORCEIDLE];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,27 +461,43 @@ void cgroup_base_stat_cputime_show(struct seq_file *seq)
|
||||
{
|
||||
struct cgroup *cgrp = seq_css(seq)->cgroup;
|
||||
u64 usage, utime, stime;
|
||||
struct task_cputime cputime;
|
||||
struct cgroup_base_stat bstat;
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
u64 forceidle_time;
|
||||
#endif
|
||||
|
||||
if (cgroup_parent(cgrp)) {
|
||||
cgroup_rstat_flush_hold(cgrp);
|
||||
usage = cgrp->bstat.cputime.sum_exec_runtime;
|
||||
cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime,
|
||||
&utime, &stime);
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
forceidle_time = cgrp->bstat.forceidle_sum;
|
||||
#endif
|
||||
cgroup_rstat_flush_release();
|
||||
} else {
|
||||
root_cgroup_cputime(&cputime);
|
||||
usage = cputime.sum_exec_runtime;
|
||||
utime = cputime.utime;
|
||||
stime = cputime.stime;
|
||||
root_cgroup_cputime(&bstat);
|
||||
usage = bstat.cputime.sum_exec_runtime;
|
||||
utime = bstat.cputime.utime;
|
||||
stime = bstat.cputime.stime;
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
forceidle_time = bstat.forceidle_sum;
|
||||
#endif
|
||||
}
|
||||
|
||||
do_div(usage, NSEC_PER_USEC);
|
||||
do_div(utime, NSEC_PER_USEC);
|
||||
do_div(stime, NSEC_PER_USEC);
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
do_div(forceidle_time, NSEC_PER_USEC);
|
||||
#endif
|
||||
|
||||
seq_printf(seq, "usage_usec %llu\n"
|
||||
"user_usec %llu\n"
|
||||
"system_usec %llu\n",
|
||||
usage, utime, stime);
|
||||
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
seq_printf(seq, "core_sched.force_idle_usec %llu\n", forceidle_time);
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user