Commit 934352f2 authored by Bharata B Rao's avatar Bharata B Rao Committed by Ingo Molnar

sched: add hierarchical accounting to cpu accounting controller

Impact: improve CPU time accounting of tasks under the cpu accounting controller

Add hierarchical accounting to cpu accounting controller and include
cpuacct documentation.

Currently, while charging the task's cputime to its accounting group,
the accounting group hierarchy isn't updated. This patch charges the cputime
of a task to its accounting group and all its parent accounting groups.
Reported-by: default avatarSrivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: default avatarBharata B Rao <bharata@linux.vnet.ibm.com>
Reviewed-by: default avatarPaul Menage <menage@google.com>
Acked-by: default avatarBalbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ff9b48c3
CPU Accounting Controller
-------------------------
The CPU accounting controller is used to group tasks using cgroups and
account the CPU usage of these groups of tasks.
The CPU accounting controller supports multi-hierarchy groups. An accounting
group accumulates the CPU usage of all of its child groups and the tasks
directly present in its group.
Accounting groups can be created by first mounting the cgroup filesystem.
# mkdir /cgroups
# mount -t cgroup -ocpuacct none /cgroups
With the above step, the initial or the parent accounting group
becomes visible at /cgroups. At bootup, this group includes all the
tasks in the system. /cgroups/tasks lists the tasks in this cgroup.
/cgroups/cpuacct.usage gives the CPU time (in nanoseconds) obtained by
this group which is essentially the CPU time obtained by all the tasks
in the system.
New accounting groups can be created under the parent group /cgroups.
# cd /cgroups
# mkdir g1
# echo $$ > g1
The above steps create a new group g1 and move the current shell
process (bash) into it. CPU time consumed by this bash and its children
can be obtained from g1/cpuacct.usage and the same is accumulated in
/cgroups/cpuacct.usage also.
...@@ -9196,11 +9196,12 @@ struct cgroup_subsys cpu_cgroup_subsys = { ...@@ -9196,11 +9196,12 @@ struct cgroup_subsys cpu_cgroup_subsys = {
* (balbir@in.ibm.com). * (balbir@in.ibm.com).
*/ */
/* track cpu usage of a group of tasks */ /* track cpu usage of a group of tasks and its child groups */
struct cpuacct { struct cpuacct {
struct cgroup_subsys_state css; struct cgroup_subsys_state css;
/* cpuusage holds pointer to a u64-type object on every cpu */ /* cpuusage holds pointer to a u64-type object on every cpu */
u64 *cpuusage; u64 *cpuusage;
struct cpuacct *parent;
}; };
struct cgroup_subsys cpuacct_subsys; struct cgroup_subsys cpuacct_subsys;
...@@ -9234,6 +9235,9 @@ static struct cgroup_subsys_state *cpuacct_create( ...@@ -9234,6 +9235,9 @@ static struct cgroup_subsys_state *cpuacct_create(
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
if (cgrp->parent)
ca->parent = cgroup_ca(cgrp->parent);
return &ca->css; return &ca->css;
} }
...@@ -9313,14 +9317,16 @@ static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp) ...@@ -9313,14 +9317,16 @@ static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
static void cpuacct_charge(struct task_struct *tsk, u64 cputime) static void cpuacct_charge(struct task_struct *tsk, u64 cputime)
{ {
struct cpuacct *ca; struct cpuacct *ca;
int cpu;
if (!cpuacct_subsys.active) if (!cpuacct_subsys.active)
return; return;
cpu = task_cpu(tsk);
ca = task_ca(tsk); ca = task_ca(tsk);
if (ca) {
u64 *cpuusage = percpu_ptr(ca->cpuusage, task_cpu(tsk));
for (; ca; ca = ca->parent) {
u64 *cpuusage = percpu_ptr(ca->cpuusage, cpu);
*cpuusage += cputime; *cpuusage += cputime;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment