From db83ac46e3f5a3f951fe385aada885a484c31047 Mon Sep 17 00:00:00 2001 From: Yihao Wu Date: Fri, 17 Jan 2020 01:03:44 +0800 Subject: [PATCH 2217/2944] alinux: cpuacct: Export nr_running & nr_uninterruptible to #28143103 cpu cgroup's nr_running and nr_uninterruptible are useful for troubleshooting. Export them in cpuacct.proc_stat. Signed-off-by: Yihao Wu Acked-by: Shanpei Chen --- kernel/sched/cpuacct.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index 4936863..a2e1f7b 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -669,6 +669,95 @@ void cpuacct_cpuset_changed(struct cgroup *cgrp, struct cpumask *deleted, rcu_read_unlock(); } +static inline unsigned long nr_uninterruptible(void) +{ + unsigned long i, sum = 0; + + for_each_possible_cpu(i) + sum += cpu_rq(i)->nr_uninterruptible; + + /* + * Since we read the counters lockless, it might be slightly + * inaccurate. Do not allow it to go below zero though: + */ + if (unlikely((long)sum < 0)) + sum = 0; + + return sum; +} + +#ifdef CONFIG_CFS_BANDWIDTH +static inline bool tg_cfs_throttled(struct task_group *tg, int cpu) +{ + return tg->cfs_rq[cpu]->throttle_count; +} +#else +static inline bool tg_cfs_throttled(struct task_group *tg, int cpu) +{ + return false; +} +#endif + +#ifdef CONFIG_RT_GROUP_SCHED +static inline bool tg_rt_throttled(struct task_group *tg, int cpu) +{ + return tg->rt_rq[cpu]->rt_throttled && !tg->rt_rq[cpu]->rt_nr_boosted; +} +#endif + +static unsigned long ca_running(struct cpuacct *ca, int cpu) +{ + unsigned long nr_running = 0; + struct cgroup *cgrp = ca->css.cgroup; + struct task_group *tg; + + /* Make sure it is only called for non-root cpuacct */ + if (ca == &root_cpuacct) + return 0; + + rcu_read_lock(); + tg = cgroup_tg(cgrp); + if (unlikely(!tg)) + goto out; + + if (!tg_cfs_throttled(tg, cpu)) + nr_running += tg->cfs_rq[cpu]->h_nr_running; +#ifdef CONFIG_RT_GROUP_SCHED + if (!tg_rt_throttled(tg, cpu)) + nr_running += tg->rt_rq[cpu]->rt_nr_running; +#endif + /* SCHED_DEADLINE doesn't support cgroup yet */ + +out: + rcu_read_unlock(); + return nr_running; +} + +static unsigned long ca_uninterruptible(struct cpuacct *ca, int cpu) +{ + unsigned long nr = 0; + struct cgroup *cgrp = ca->css.cgroup; + struct task_group *tg; + + /* Make sure it is only called for non-root cpuacct */ + if (ca == &root_cpuacct) + return nr; + + rcu_read_lock(); + tg = cgroup_tg(cgrp); + if (unlikely(!tg)) + goto out_rcu_unlock; + + nr = tg->cfs_rq[cpu]->nr_uninterruptible; +#ifdef CONFIG_RT_GROUP_SCHED + nr += tg->rt_rq[cpu]->nr_uninterruptible; +#endif + +out_rcu_unlock: + rcu_read_unlock(); + return nr; +} + static void __cpuacct_get_usage_result(struct cpuacct *ca, int cpu, struct task_group *tg, struct cpuacct_usage_result *res) { @@ -757,6 +846,7 @@ static int cpuacct_proc_stats_show(struct seq_file *sf, void *v) u64 user, nice, system, idle, iowait, irq, softirq, steal, guest; u64 nr_migrations = 0; struct cpuacct_alistats *alistats; + unsigned long nr_run = 0, nr_uninter = 0; int cpu; user = nice = system = idle = iowait = @@ -787,6 +877,8 @@ static int cpuacct_proc_stats_show(struct seq_file *sf, void *v) alistats = per_cpu_ptr(ca->alistats, cpu); nr_migrations += alistats->nr_migrations; + nr_run += ca_running(ca, cpu); + nr_uninter += ca_uninterruptible(ca, cpu); } } else { struct kernel_cpustat *kcpustat; @@ -806,6 +898,9 @@ static int cpuacct_proc_stats_show(struct seq_file *sf, void *v) alistats = per_cpu_ptr(ca->alistats, cpu); nr_migrations += alistats->nr_migrations; } + + nr_run = nr_running(); + nr_uninter = nr_uninterruptible(); } seq_printf(sf, "user %lld\n", nsec_to_clock_t(user)); @@ -819,6 +914,10 @@ static int cpuacct_proc_stats_show(struct seq_file *sf, void *v) seq_printf(sf, "guest %lld\n", nsec_to_clock_t(guest)); seq_printf(sf, "nr_migrations %lld\n", (u64)nr_migrations); + seq_printf(sf, "nr_running %lld\n", (u64)nr_run); + if ((long) nr_uninter < 0) + nr_uninter = 0; + seq_printf(sf, "nr_uninterruptible %lld\n", (u64)nr_uninter); return 0; } -- 1.8.3.1