From: Glauber Costa <glommer@parallels.com>
To: linux-kernel@vger.kernel.org
Cc: paul@paulmenage.org, lizf@cn.fujitsu.com, daniel.lezcano@free.fr,
a.p.zijlstra@chello.nl, jbottomley@parallels.com,
Glauber Costa <glommer@parallels.com>,
Balbir Singh <bsingharora@gmail.com>
Subject: [RFD 8/9] provide a version of cpuusage statistics inside cpu cgroup
Date: Fri, 23 Sep 2011 19:20:31 -0300 [thread overview]
Message-ID: <1316816432-9237-9-git-send-email-glommer@parallels.com> (raw)
In-Reply-To: <1316816432-9237-1-git-send-email-glommer@parallels.com>
For users interested in using the information currently displayed
at cpuacct.usage and cpuaact.usage_per_cpu, we provide them inside
the cpu cgroup.
Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Balbir Singh <bsingharora@gmail.com>
---
kernel/sched.c | 220 +++++++++++++++++++++++++++++++++++----------------
kernel/sched_fair.c | 2 +-
kernel/sched_rt.c | 2 +-
3 files changed, 155 insertions(+), 69 deletions(-)
diff --git a/kernel/sched.c b/kernel/sched.c
index b687441..fc873c9 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -280,6 +280,7 @@ struct task_group {
#endif
unsigned long total_forks;
struct kernel_stat __percpu *cpustat;
+ u64 __percpu *cpuusage;
struct timespec start_time;
};
@@ -2083,6 +2084,8 @@ static int irqtime_account_si_update(void)
#endif
+static void cpuusage_charge(struct task_struct *tsk, u64 cputime);
+
#include "sched_idletask.c"
#include "sched_fair.c"
#include "sched_rt.c"
@@ -8144,8 +8147,10 @@ void __init sched_init(void)
root_task_group.start_time = (struct timespec){0, 0};
root_task_group.cpustat = alloc_percpu(struct kernel_stat);
+ root_task_group.cpuusage = alloc_percpu(u64);
/* Failing that early an allocation means we're screwed anyway */
BUG_ON(!root_task_group.cpustat);
+ BUG_ON(!root_task_group.cpuusage);
for_each_possible_cpu(i) {
kstat = per_cpu_ptr(root_task_group.cpustat, i);
kstat->cpustat[IDLE] = 0;
@@ -8587,7 +8592,10 @@ static void free_sched_group(struct task_group *tg)
free_fair_sched_group(tg);
free_rt_sched_group(tg);
autogroup_free(tg);
- free_percpu(tg->cpustat);
+ if (tg->cpustat)
+ free_percpu(tg->cpustat);
+ if (tg->cpuusage)
+ free_percpu(tg->cpuusage);
kfree(tg);
}
@@ -8608,6 +8616,10 @@ struct task_group *sched_create_group(struct task_group *parent)
if (!alloc_rt_sched_group(tg, parent))
goto err;
+ tg->cpuusage = alloc_percpu(u64);
+ if (!tg->cpuusage)
+ goto err;
+
tg->cpustat = alloc_percpu(struct kernel_stat);
if (!tg->cpustat)
goto err;
@@ -9296,6 +9308,87 @@ int cpu_cgroup_proc_stat(struct cgroup *cgrp, struct cftype *cft, struct seq_fil
+static u64 cpuacct_cpuusage_read(u64 *cpuusage, int cpu)
+{
+ u64 data;
+
+#ifndef CONFIG_64BIT
+ /*
+ * Take rq->lock to make 64-bit read safe on 32-bit platforms.
+ */
+ raw_spin_lock_irq(&cpu_rq(cpu)->lock);
+ data = *cpuusage;
+ raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
+#else
+ data = *cpuusage;
+#endif
+
+ return data;
+}
+
+static void cpuacct_cpuusage_write(u64 *cpuusage, int cpu, u64 val)
+{
+#ifndef CONFIG_64BIT
+ /*
+ * Take rq->lock to make 64-bit write safe on 32-bit platforms.
+ */
+ raw_spin_lock_irq(&cpu_rq(cpu)->lock);
+ *cpuusage = val;
+ raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
+#else
+ *cpuusage = val;
+#endif
+}
+
+static u64 cpu_cgroup_cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
+{
+ struct task_group *tg = cgroup_tg(cgrp);
+ u64 totalcpuusage = 0;
+ int i;
+
+ for_each_present_cpu(i) {
+ u64 *cpuusage = per_cpu_ptr(tg->cpuusage, i);
+ totalcpuusage += cpuacct_cpuusage_read(cpuusage, i);
+ }
+
+ return totalcpuusage;
+}
+
+static int cpu_cgroup_cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
+ u64 reset)
+{
+ struct task_group *tg = cgroup_tg(cgrp);
+ int err = 0;
+ int i;
+
+ if (reset) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ for_each_present_cpu(i) {
+ u64 *cpuusage = per_cpu_ptr(tg->cpuusage, i);
+ cpuacct_cpuusage_write(cpuusage, i, 0);
+ }
+
+out:
+ return err;
+}
+
+static int cpu_cgroup_percpu_seq_read(struct cgroup *cgroup, struct cftype *cft,
+ struct seq_file *m)
+{
+ u64 percpu;
+ int i;
+
+ for_each_present_cpu(i) {
+ percpu = cpu_cgroup_cpuusage_read(cgroup, cft);
+ seq_printf(m, "%llu ", (unsigned long long) percpu);
+ }
+ seq_printf(m, "\n");
+ return 0;
+}
+
static const char *cpuacct_stat_desc[] = {
[CPUACCT_STAT_USER] = "user",
[CPUACCT_STAT_SYSTEM] = "system",
@@ -9357,6 +9450,15 @@ static struct cftype cpu_files[] = {
.name = "stat",
.read_map = cpu_cgroup_stats_show,
},
+ {
+ .name = "usage",
+ .read_u64 = cpu_cgroup_cpuusage_read,
+ .write_u64 = cpu_cgroup_cpuusage_write,
+ },
+ {
+ .name = "usage_percpu",
+ .read_seq_string = cpu_cgroup_percpu_seq_read,
+ },
};
static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont)
@@ -9458,41 +9560,6 @@ cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp)
kfree(ca);
}
-static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu)
-{
- u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
- u64 data;
-
-#ifndef CONFIG_64BIT
- /*
- * Take rq->lock to make 64-bit read safe on 32-bit platforms.
- */
- raw_spin_lock_irq(&cpu_rq(cpu)->lock);
- data = *cpuusage;
- raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
-#else
- data = *cpuusage;
-#endif
-
- return data;
-}
-
-static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val)
-{
- u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
-
-#ifndef CONFIG_64BIT
- /*
- * Take rq->lock to make 64-bit write safe on 32-bit platforms.
- */
- raw_spin_lock_irq(&cpu_rq(cpu)->lock);
- *cpuusage = val;
- raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
-#else
- *cpuusage = val;
-#endif
-}
-
/* return total cpu usage (in nanoseconds) of a group */
static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
{
@@ -9500,8 +9567,10 @@ static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
u64 totalcpuusage = 0;
int i;
- for_each_present_cpu(i)
- totalcpuusage += cpuacct_cpuusage_read(ca, i);
+ for_each_present_cpu(i) {
+ u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
+ totalcpuusage += cpuacct_cpuusage_read(cpuusage, i);
+ }
return totalcpuusage;
}
@@ -9518,8 +9587,10 @@ static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
goto out;
}
- for_each_present_cpu(i)
- cpuacct_cpuusage_write(ca, i, 0);
+ for_each_present_cpu(i) {
+ u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
+ cpuacct_cpuusage_write(cpuusage, i, 0);
+ }
out:
return err;
@@ -9576,33 +9647,6 @@ static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
}
/*
- * charge this task's execution time to its accounting group.
- *
- * called with rq->lock held.
- */
-static void cpuacct_charge(struct task_struct *tsk, u64 cputime)
-{
- struct cpuacct *ca;
- int cpu;
-
- if (unlikely(!cpuacct_subsys.active))
- return;
-
- cpu = task_cpu(tsk);
-
- rcu_read_lock();
-
- ca = task_ca(tsk);
-
- for (; ca; ca = ca->parent) {
- u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
- *cpuusage += cputime;
- }
-
- rcu_read_unlock();
-}
-
-/*
* When CONFIG_VIRT_CPU_ACCOUNTING is enabled one jiffy can be very large
* in cputime_t units. As a result, cpuacct_update_stats calls
* percpu_counter_add with values large enough to always overflow the
@@ -9650,3 +9694,45 @@ struct cgroup_subsys cpuacct_subsys = {
};
#endif /* CONFIG_CGROUP_CPUACCT */
+/*
+ * charge this task's execution time to its accounting group.
+ *
+ * called with rq->lock held.
+ */
+static void cpuusage_charge(struct task_struct *tsk, u64 cputime)
+{
+ int cpu;
+
+#ifdef CONFIG_CGROUP_CPUACCT
+ struct cpuacct *ca;
+#endif
+#ifdef CONFIG_CGROUP_SCHED
+ struct task_group *tg;
+#endif
+ cpu = task_cpu(tsk);
+
+ rcu_read_lock();
+
+#ifdef CONFIG_CGROUP_CPUACCT
+ ca = task_ca(tsk);
+
+ if (unlikely(!cpuacct_subsys.active))
+ goto no_cpuacct;
+
+ for (; ca; ca = ca->parent) {
+ u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
+ *cpuusage += cputime;
+ }
+no_cpuacct:
+#endif
+
+#ifdef CONFIG_CGROUP_SCHED
+ tg = task_group(tsk);
+ for (; tg; tg = tg->parent) {
+ u64 *cpuusage = per_cpu_ptr(tg->cpuusage, cpu);
+ *cpuusage += cputime;
+ }
+#endif
+ rcu_read_unlock();
+}
+
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index bc8ee99..38b4549 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -580,7 +580,7 @@ static void update_curr(struct cfs_rq *cfs_rq)
struct task_struct *curtask = task_of(curr);
trace_sched_stat_runtime(curtask, delta_exec, curr->vruntime);
- cpuacct_charge(curtask, delta_exec);
+ cpuusage_charge(curtask, delta_exec);
account_group_exec_runtime(curtask, delta_exec);
}
}
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 97540f0..a21b58e 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -676,7 +676,7 @@ static void update_curr_rt(struct rq *rq)
account_group_exec_runtime(curr, delta_exec);
curr->se.exec_start = rq->clock_task;
- cpuacct_charge(curr, delta_exec);
+ cpuusage_charge(curr, delta_exec);
sched_rt_avg_update(rq, delta_exec);
--
1.7.6
next prev parent reply other threads:[~2011-09-23 22:26 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-23 22:20 [RFD 0/9] per-cgroup /proc/stat statistics Glauber Costa
2011-09-23 22:20 ` [RFD 1/9] Change cpustat fields to an array Glauber Costa
2011-09-27 21:00 ` Peter Zijlstra
2011-09-28 15:13 ` Glauber Costa
2011-09-28 15:23 ` Peter Zijlstra
2011-09-28 18:19 ` Glauber Costa
2011-09-28 19:09 ` Peter Zijlstra
2011-09-28 20:04 ` Glauber Costa
2011-10-01 17:47 ` Glauber Costa
2011-09-27 21:03 ` Peter Zijlstra
2011-09-28 15:14 ` Glauber Costa
2011-09-23 22:20 ` [RFD 2/9] Move /proc/stat logic inside sched.c Glauber Costa
2011-09-23 22:20 ` [RFD 3/9] Display /proc/stat information per cgroup Glauber Costa
2011-09-27 17:01 ` Balbir Singh
2011-09-27 18:42 ` Glauber Costa
2011-09-27 22:21 ` Peter Zijlstra
2011-09-28 15:22 ` Glauber Costa
2011-09-28 15:23 ` Glauber Costa
2011-09-27 21:48 ` Peter Zijlstra
2011-09-28 15:14 ` Glauber Costa
2011-09-27 21:52 ` Peter Zijlstra
2011-09-28 15:15 ` Glauber Costa
2011-09-23 22:20 ` [RFD 4/9] Make total_forks per-cgroup Glauber Costa
2011-09-27 22:00 ` Peter Zijlstra
2011-09-28 8:13 ` Martin Schwidefsky
2011-09-28 10:35 ` Peter Zijlstra
2011-09-28 12:42 ` Martin Schwidefsky
2011-09-28 12:53 ` Peter Zijlstra
2011-09-28 15:29 ` Glauber Costa
2011-09-28 15:33 ` Peter Zijlstra
2011-09-28 15:35 ` Glauber Costa
2011-09-28 15:37 ` Peter Zijlstra
2011-09-28 15:39 ` Glauber Costa
2011-09-28 15:28 ` Glauber Costa
2011-09-28 15:27 ` Glauber Costa
2011-09-28 15:26 ` Glauber Costa
2011-09-23 22:20 ` [RFD 5/9] per-cgroup boot time Glauber Costa
2011-09-23 22:20 ` [RFD 6/9] Report steal time for cgroup Glauber Costa
2011-09-23 22:20 ` [RFD 7/9] provide a version of cpuacct statistics inside cpu cgroup Glauber Costa
2011-09-23 22:20 ` Glauber Costa [this message]
2011-09-23 22:20 ` [RFD 9/9] Change CPUACCT to default n Glauber Costa
2011-09-27 22:11 ` [RFD 0/9] per-cgroup /proc/stat statistics Peter Zijlstra
2011-09-28 15:21 ` Glauber Costa
2011-09-28 15:27 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1316816432-9237-9-git-send-email-glommer@parallels.com \
--to=glommer@parallels.com \
--cc=a.p.zijlstra@chello.nl \
--cc=bsingharora@gmail.com \
--cc=daniel.lezcano@free.fr \
--cc=jbottomley@parallels.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lizf@cn.fujitsu.com \
--cc=paul@paulmenage.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome