
From: Tengda Wu <wutengda2@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICAOAT -------------------------------- Reuse the 'sum_sleep_runtime' in /proc/schedstats to accounting task 'sleep' interference, which indicates how much time the cgroup tasks are dequeued and wait for enqueuing. Signed-off-by: Tengda Wu <wutengda2@huawei.com> Signed-off-by: Pu Lehui <pulehui@huawei.com> --- include/linux/cgroup.h | 26 ++++++++++++++++++++++++++ kernel/cgroup/ifs.c | 35 +++++++++++++++++++++++++++++++++-- kernel/sched/core.c | 1 + kernel/sched/stats.c | 2 ++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 522f775e5139..84273989b573 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -865,6 +865,9 @@ void cgroup_move_task_to_root(struct task_struct *tsk); enum ifs_types { IFS_SMT, IFS_RUNDELAY, +#ifdef CONFIG_SCHEDSTATS + IFS_SLEEP, +#endif NR_IFS_TYPES, }; @@ -934,12 +937,35 @@ static inline void cgroup_ifs_account_rundelay(struct task_struct *task, cgroup_ifs_account_delta(this_cpu_ptr(ifs->pcpu), IFS_RUNDELAY, delta); } +#ifdef CONFIG_SCHEDSTATS +static inline void cgroup_ifs_account_sleep(struct task_struct *task, + u64 delta) +{ + struct cgroup_ifs *ifs; + + if (!cgroup_ifs_enabled()) + return; + + ifs = task_ifs(task); + if (!ifs) + return; + + cgroup_ifs_account_delta(this_cpu_ptr(ifs->pcpu), IFS_SLEEP, delta); +} + +void cgroup_ifs_enable_sleep_account(void); +#endif + #else /* !CONFIG_CGROUP_IFS */ static inline void cgroup_ifs_account_smttime(struct task_struct *prev, struct task_struct *next, struct task_struct *idle) {} static inline void cgroup_ifs_set_smt(cpumask_t *sibling) {} static inline void cgroup_ifs_account_rundelay(struct task_struct *task, u64 delta) {} +#ifdef CONFIG_SCHEDSTATS +static inline void cgroup_ifs_account_sleep(struct task_struct *task, u64 delta) {} +static inline void cgroup_ifs_enable_sleep_account(void) {} +#endif #endif /* CONFIG_CGROUP_IFS */ #endif /* _LINUX_CGROUP_H */ diff --git a/kernel/cgroup/ifs.c b/kernel/cgroup/ifs.c index 7bc11c82fce4..c2de386315c2 100644 --- a/kernel/cgroup/ifs.c +++ b/kernel/cgroup/ifs.c @@ -32,6 +32,10 @@ static bool ifs_enable = true; static bool ifs_enable; #endif +#ifdef CONFIG_SCHEDSTATS +static bool ifs_sleep_enable; +#endif + static int __init setup_ifs(char *str) { return kstrtobool(str, &ifs_enable) == 0; @@ -158,6 +162,11 @@ static const char *ifs_type_name(int type) case IFS_RUNDELAY: name = "rundelay"; break; +#ifdef CONFIG_SCHEDSTATS + case IFS_SLEEP: + name = "sleep"; + break; +#endif default: break; } @@ -165,6 +174,15 @@ static const char *ifs_type_name(int type) return name; } +static bool should_print(int type) +{ +#ifdef CONFIG_SCHEDSTATS + if (type == IFS_SLEEP) + return ifs_sleep_enable; +#endif + return true; +} + static int print_sum_time(struct cgroup_ifs *ifs, struct seq_file *seq) { u64 time[NR_IFS_TYPES] = { 0 }; @@ -172,14 +190,20 @@ static int print_sum_time(struct cgroup_ifs *ifs, struct seq_file *seq) int i; for_each_possible_cpu(cpu) { - for (i = 0; i < NR_IFS_TYPES; i++) + for (i = 0; i < NR_IFS_TYPES; i++) { + if (!should_print(i)) + continue; time[i] += per_cpu_ptr(ifs->pcpu, cpu)->time[i]; + } } seq_printf(seq, "%-18s%s\n", "Interference", "Total Time (ns)"); - for (i = 0; i < NR_IFS_TYPES; i++) + for (i = 0; i < NR_IFS_TYPES; i++) { + if (!should_print(i)) + continue; seq_printf(seq, "%-18s%llu\n", ifs_type_name(i), time[i]); + } return 0; } @@ -267,3 +291,10 @@ void cgroup_ifs_rm_files(struct cgroup_subsys_state *css, struct cgroup *cgrp) if (cgroup_ifs_enabled()) cgroup_addrm_files(css, cgrp, cgroup_ifs_files, false); } + +#ifdef CONFIG_SCHEDSTATS +void cgroup_ifs_enable_sleep_account(void) +{ + ifs_sleep_enable = true; +} +#endif diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 17ca1d72b03e..7b77fa528c3c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4667,6 +4667,7 @@ static void set_schedstats(bool enabled) { if (enabled) { compute_skid(); + cgroup_ifs_enable_sleep_account(); static_branch_enable(&sched_schedstats); } else { static_branch_disable(&sched_schedstats); diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c index 306f26fde69a..e3f1026ba5e8 100644 --- a/kernel/sched/stats.c +++ b/kernel/sched/stats.c @@ -67,6 +67,7 @@ void __update_stats_enqueue_sleeper(struct rq *rq, struct task_struct *p, if (p) { account_scheduler_latency(p, delta >> 10, 1); trace_sched_stat_sleep(p, delta); + cgroup_ifs_account_sleep(p, delta); } } @@ -91,6 +92,7 @@ void __update_stats_enqueue_sleeper(struct rq *rq, struct task_struct *p, } trace_sched_stat_blocked(p, delta); + cgroup_ifs_account_sleep(p, delta); /* * Blocking time is in units of nanosecs, so shift by -- 2.34.1