1 #include <linux/cgroup.h>
2 #include <linux/slab.h>
3 #include <linux/percpu.h>
4 #include <linux/spinlock.h>
5 #include <linux/cpumask.h>
6 #include <linux/seq_file.h>
7 #include <linux/rcupdate.h>
8 #include <linux/kernel_stat.h>
13 * CPU accounting code for task groups.
15 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh
16 * (balbir@in.ibm.com).
19 struct cpuacct root_cpuacct;
21 /* create a new cpu accounting group */
22 static struct cgroup_subsys_state *cpuacct_css_alloc(struct cgroup *cgrp)
27 return &root_cpuacct.css;
29 ca = kzalloc(sizeof(*ca), GFP_KERNEL);
33 ca->cpuusage = alloc_percpu(u64);
37 ca->cpustat = alloc_percpu(struct kernel_cpustat);
39 goto out_free_cpuusage;
44 free_percpu(ca->cpuusage);
48 return ERR_PTR(-ENOMEM);
51 /* destroy an existing cpu accounting group */
52 static void cpuacct_css_free(struct cgroup *cgrp)
54 struct cpuacct *ca = cgroup_ca(cgrp);
56 free_percpu(ca->cpustat);
57 free_percpu(ca->cpuusage);
61 static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu)
63 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
68 * Take rq->lock to make 64-bit read safe on 32-bit platforms.
70 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
72 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
80 static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val)
82 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
86 * Take rq->lock to make 64-bit write safe on 32-bit platforms.
88 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
90 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
96 /* return total cpu usage (in nanoseconds) of a group */
97 static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
99 struct cpuacct *ca = cgroup_ca(cgrp);
100 u64 totalcpuusage = 0;
103 for_each_present_cpu(i)
104 totalcpuusage += cpuacct_cpuusage_read(ca, i);
106 return totalcpuusage;
109 static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
112 struct cpuacct *ca = cgroup_ca(cgrp);
121 for_each_present_cpu(i)
122 cpuacct_cpuusage_write(ca, i, 0);
128 static int cpuacct_percpu_seq_read(struct cgroup *cgroup, struct cftype *cft,
131 struct cpuacct *ca = cgroup_ca(cgroup);
135 for_each_present_cpu(i) {
136 percpu = cpuacct_cpuusage_read(ca, i);
137 seq_printf(m, "%llu ", (unsigned long long) percpu);
143 static const char * const cpuacct_stat_desc[] = {
144 [CPUACCT_STAT_USER] = "user",
145 [CPUACCT_STAT_SYSTEM] = "system",
148 static int cpuacct_stats_show(struct cgroup *cgrp, struct cftype *cft,
149 struct cgroup_map_cb *cb)
151 struct cpuacct *ca = cgroup_ca(cgrp);
155 for_each_online_cpu(cpu) {
156 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
157 val += kcpustat->cpustat[CPUTIME_USER];
158 val += kcpustat->cpustat[CPUTIME_NICE];
160 val = cputime64_to_clock_t(val);
161 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_USER], val);
164 for_each_online_cpu(cpu) {
165 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
166 val += kcpustat->cpustat[CPUTIME_SYSTEM];
167 val += kcpustat->cpustat[CPUTIME_IRQ];
168 val += kcpustat->cpustat[CPUTIME_SOFTIRQ];
171 val = cputime64_to_clock_t(val);
172 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
177 static struct cftype files[] = {
180 .read_u64 = cpuusage_read,
181 .write_u64 = cpuusage_write,
184 .name = "usage_percpu",
185 .read_seq_string = cpuacct_percpu_seq_read,
189 .read_map = cpuacct_stats_show,
195 * charge this task's execution time to its accounting group.
197 * called with rq->lock held.
199 void cpuacct_charge(struct task_struct *tsk, u64 cputime)
204 if (unlikely(!cpuacct_subsys.active))
213 for (; ca; ca = parent_ca(ca)) {
214 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
215 *cpuusage += cputime;
222 * Add user/system time to cpuacct.
224 * Note: it's the caller that updates the account of the root cgroup.
226 void cpuacct_account_field(struct task_struct *p, int index, u64 val)
228 struct kernel_cpustat *kcpustat;
231 if (unlikely(!cpuacct_subsys.active))
236 while (ca && (ca != &root_cpuacct)) {
237 kcpustat = this_cpu_ptr(ca->cpustat);
238 kcpustat->cpustat[index] += val;
244 void __init cpuacct_init(void)
246 root_cpuacct.cpustat = &kernel_cpustat;
247 root_cpuacct.cpuusage = alloc_percpu(u64);
248 BUG_ON(!root_cpuacct.cpuusage); /* Too early, not expected to fail */
251 struct cgroup_subsys cpuacct_subsys = {
253 .css_alloc = cpuacct_css_alloc,
254 .css_free = cpuacct_css_free,
255 .subsys_id = cpuacct_subsys_id,
256 .base_cftypes = files,