提交 9be0ac2b 编写于 作者: X Xunlei Pang 提交者: Yihao Wu

alinux: cpuacct: export cpuacct.proc_stat interface

to #26424323

Add the cgroup file "cpuacct.proc_stat", we'll export per-cgroup
cpu usages and some other scheduler statistics in this interface.
Reviewed-by: NMichael Wang <yun.wang@linux.alibaba.com>
Signed-off-by: NXunlei Pang <xlpang@linux.alibaba.com>
Signed-off-by: NYihao Wu <wuyihao@linux.alibaba.com>
上级 36da4fe9
...@@ -45,7 +45,7 @@ static u64 get_iowait_time(int cpu) ...@@ -45,7 +45,7 @@ static u64 get_iowait_time(int cpu)
#else #else
static u64 get_idle_time(int cpu) u64 get_idle_time(int cpu)
{ {
u64 idle, idle_usecs = -1ULL; u64 idle, idle_usecs = -1ULL;
...@@ -61,7 +61,7 @@ static u64 get_idle_time(int cpu) ...@@ -61,7 +61,7 @@ static u64 get_idle_time(int cpu)
return idle; return idle;
} }
static u64 get_iowait_time(int cpu) u64 get_iowait_time(int cpu)
{ {
u64 iowait, iowait_usecs = -1ULL; u64 iowait, iowait_usecs = -1ULL;
......
...@@ -1969,4 +1969,9 @@ static inline void rseq_syscall(struct pt_regs *regs) ...@@ -1969,4 +1969,9 @@ static inline void rseq_syscall(struct pt_regs *regs)
#endif #endif
struct cpuacct_usage_result {
u64 user, nice, system, irq, softirq;
u64 steal, iowait, idle, guest, guest_nice;
};
#endif #endif
...@@ -22,7 +22,9 @@ static const char * const cpuacct_stat_desc[] = { ...@@ -22,7 +22,9 @@ static const char * const cpuacct_stat_desc[] = {
struct cpuacct_usage { struct cpuacct_usage {
u64 usages[CPUACCT_STAT_NSTATS]; u64 usages[CPUACCT_STAT_NSTATS];
}; struct prev_cputime prev_cputime1; /* utime and stime */
struct prev_cputime prev_cputime2; /* user and nice */
} ____cacheline_aligned;
/* track CPU usage of a group of tasks and its child groups */ /* track CPU usage of a group of tasks and its child groups */
struct cpuacct { struct cpuacct {
...@@ -64,6 +66,7 @@ static struct cgroup_subsys_state * ...@@ -64,6 +66,7 @@ static struct cgroup_subsys_state *
cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)
{ {
struct cpuacct *ca; struct cpuacct *ca;
int i;
if (!parent_css) if (!parent_css)
return &root_cpuacct.css; return &root_cpuacct.css;
...@@ -80,6 +83,11 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) ...@@ -80,6 +83,11 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)
if (!ca->cpustat) if (!ca->cpustat)
goto out_free_cpuusage; goto out_free_cpuusage;
for_each_possible_cpu(i) {
prev_cputime_init(&per_cpu_ptr(ca->cpuusage, i)->prev_cputime1);
prev_cputime_init(&per_cpu_ptr(ca->cpuusage, i)->prev_cputime2);
}
return &ca->css; return &ca->css;
out_free_cpuusage: out_free_cpuusage:
...@@ -298,6 +306,123 @@ static int cpuacct_stats_show(struct seq_file *sf, void *v) ...@@ -298,6 +306,123 @@ static int cpuacct_stats_show(struct seq_file *sf, void *v)
return 0; return 0;
} }
#ifdef CONFIG_SCHED_SLI
#ifndef arch_idle_time
#define arch_idle_time(cpu) 0
#endif
static inline struct task_group *cgroup_tg(struct cgroup *cgrp)
{
return container_of(global_cgroup_css(cgrp, cpu_cgrp_id),
struct task_group, css);
}
static void __cpuacct_get_usage_result(struct cpuacct *ca, int cpu,
struct task_group *tg, struct cpuacct_usage_result *res)
{
struct kernel_cpustat *kcpustat;
struct cpuacct_usage *cpuusage;
struct task_cputime cputime;
u64 tick_user, tick_nice, tick_sys, left, right;
struct sched_entity *se;
kcpustat = per_cpu_ptr(ca->cpustat, cpu);
if (unlikely(!tg)) {
memset(res, 0, sizeof(*res));
return;
}
se = tg->se[cpu];
cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
tick_user = kcpustat->cpustat[CPUTIME_USER];
tick_nice = kcpustat->cpustat[CPUTIME_NICE];
tick_sys = kcpustat->cpustat[CPUTIME_SYSTEM];
/* Calculate system run time */
cputime.sum_exec_runtime = cpuusage->usages[CPUACCT_STAT_USER] +
cpuusage->usages[CPUACCT_STAT_SYSTEM];
cputime.utime = tick_user + tick_nice;
cputime.stime = tick_sys;
cputime_adjust(&cputime, &cpuusage->prev_cputime1, &left, &right);
res->system = right;
/* Calculate user and nice run time */
cputime.sum_exec_runtime = left; /* user + nice */
cputime.utime = tick_user;
cputime.stime = tick_nice;
cputime_adjust(&cputime, &cpuusage->prev_cputime2, &left, &right);
res->user = left;
res->nice = right;
res->irq = kcpustat->cpustat[CPUTIME_IRQ];
res->softirq = kcpustat->cpustat[CPUTIME_SOFTIRQ];
if (se)
res->steal = se->statistics.wait_sum;
else
res->steal = 0;
res->guest = res->guest_nice = 0; /* currently always 0 */
}
static int cpuacct_proc_stats_show(struct seq_file *sf, void *v)
{
struct cpuacct *ca = css_ca(seq_css(sf));
struct cgroup *cgrp = seq_css(sf)->cgroup;
u64 user, nice, system, idle, iowait, irq, softirq, steal, guest;
int cpu;
user = nice = system = idle = iowait =
irq = softirq = steal = guest = 0;
if (ca != &root_cpuacct) {
struct cpuacct_usage_result res;
for_each_possible_cpu(cpu) {
rcu_read_lock();
__cpuacct_get_usage_result(ca, cpu,
cgroup_tg(cgrp), &res);
rcu_read_unlock();
user += res.user;
nice += res.nice;
system += res.system;
irq += res.irq;
softirq += res.softirq;
steal += res.steal;
guest += res.guest;
iowait += res.iowait;
idle += res.idle;
}
} else {
struct kernel_cpustat *kcpustat;
for_each_possible_cpu(cpu) {
kcpustat = per_cpu_ptr(ca->cpustat, cpu);
user += kcpustat->cpustat[CPUTIME_USER];
nice += kcpustat->cpustat[CPUTIME_NICE];
system += kcpustat->cpustat[CPUTIME_SYSTEM];
irq += kcpustat->cpustat[CPUTIME_IRQ];
softirq += kcpustat->cpustat[CPUTIME_SOFTIRQ];
guest += kcpustat->cpustat[CPUTIME_GUEST];
idle += get_idle_time(cpu);
iowait += get_iowait_time(cpu);
steal += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
}
}
seq_printf(sf, "user %lld\n", nsec_to_clock_t(user));
seq_printf(sf, "nice %lld\n", nsec_to_clock_t(nice));
seq_printf(sf, "system %lld\n", nsec_to_clock_t(system));
seq_printf(sf, "idle %lld\n", nsec_to_clock_t(idle));
seq_printf(sf, "iowait %lld\n", nsec_to_clock_t(iowait));
seq_printf(sf, "irq %lld\n", nsec_to_clock_t(irq));
seq_printf(sf, "softirq %lld\n", nsec_to_clock_t(softirq));
seq_printf(sf, "steal %lld\n", nsec_to_clock_t(steal));
seq_printf(sf, "guest %lld\n", nsec_to_clock_t(guest));
return 0;
}
#endif
static struct cftype files[] = { static struct cftype files[] = {
{ {
.name = "usage", .name = "usage",
...@@ -332,6 +457,12 @@ static struct cftype files[] = { ...@@ -332,6 +457,12 @@ static struct cftype files[] = {
.name = "stat", .name = "stat",
.seq_show = cpuacct_stats_show, .seq_show = cpuacct_stats_show,
}, },
#ifdef CONFIG_SCHED_SLI
{
.name = "proc_stat",
.seq_show = cpuacct_proc_stats_show,
},
#endif
{ } /* terminate */ { } /* terminate */
}; };
......
...@@ -2277,6 +2277,11 @@ unsigned long scale_irq_capacity(unsigned long util, unsigned long irq, unsigned ...@@ -2277,6 +2277,11 @@ unsigned long scale_irq_capacity(unsigned long util, unsigned long irq, unsigned
} }
#endif #endif
#ifdef CONFIG_SCHED_SLI
extern u64 get_idle_time(int cpu);
extern u64 get_iowait_time(int cpu);
#endif
#ifdef CONFIG_PSI #ifdef CONFIG_PSI
extern struct cftype cgroup_v1_psi_files[]; extern struct cftype cgroup_v1_psi_files[];
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册