aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2013-03-29 02:36:31 -0400
committerIngo Molnar <mingo@kernel.org>2013-04-10 07:54:15 -0400
commit2e76c24d72372db35f226a49c2b99d0fd8cfd400 (patch)
treec611ddffa64a2a2fef615f43fcd7a14fa7553a0e /kernel/sched
parentb9b0853a4b377f84a5e6ed091816a9a2d6b10918 (diff)
sched: Split cpuacct code out of core.c
Signed-off-by: Li Zefan <lizefan@huawei.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/5155366F.5060404@huawei.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched')
-rw-r--r--kernel/sched/Makefile1
-rw-r--r--kernel/sched/core.c220
-rw-r--r--kernel/sched/cpuacct.c227
3 files changed, 228 insertions, 220 deletions
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index f06d249e103b..deaf90e4a1de 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SMP) += cpupri.o
16obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o 16obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
17obj-$(CONFIG_SCHEDSTATS) += stats.o 17obj-$(CONFIG_SCHEDSTATS) += stats.o
18obj-$(CONFIG_SCHED_DEBUG) += debug.o 18obj-$(CONFIG_SCHED_DEBUG) += debug.o
19obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f5e1aa5b2684..c28222f72c80 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8043,226 +8043,6 @@ struct cgroup_subsys cpu_cgroup_subsys = {
8043 8043
8044#endif /* CONFIG_CGROUP_SCHED */ 8044#endif /* CONFIG_CGROUP_SCHED */
8045 8045
8046#ifdef CONFIG_CGROUP_CPUACCT
8047
8048/*
8049 * CPU accounting code for task groups.
8050 *
8051 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh
8052 * (balbir@in.ibm.com).
8053 */
8054
8055struct cpuacct root_cpuacct;
8056
8057/* create a new cpu accounting group */
8058static struct cgroup_subsys_state *cpuacct_css_alloc(struct cgroup *cgrp)
8059{
8060 struct cpuacct *ca;
8061
8062 if (!cgrp->parent)
8063 return &root_cpuacct.css;
8064
8065 ca = kzalloc(sizeof(*ca), GFP_KERNEL);
8066 if (!ca)
8067 goto out;
8068
8069 ca->cpuusage = alloc_percpu(u64);
8070 if (!ca->cpuusage)
8071 goto out_free_ca;
8072
8073 ca->cpustat = alloc_percpu(struct kernel_cpustat);
8074 if (!ca->cpustat)
8075 goto out_free_cpuusage;
8076
8077 return &ca->css;
8078
8079out_free_cpuusage:
8080 free_percpu(ca->cpuusage);
8081out_free_ca:
8082 kfree(ca);
8083out:
8084 return ERR_PTR(-ENOMEM);
8085}
8086
8087/* destroy an existing cpu accounting group */
8088static void cpuacct_css_free(struct cgroup *cgrp)
8089{
8090 struct cpuacct *ca = cgroup_ca(cgrp);
8091
8092 free_percpu(ca->cpustat);
8093 free_percpu(ca->cpuusage);
8094 kfree(ca);
8095}
8096
8097static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu)
8098{
8099 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
8100 u64 data;
8101
8102#ifndef CONFIG_64BIT
8103 /*
8104 * Take rq->lock to make 64-bit read safe on 32-bit platforms.
8105 */
8106 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
8107 data = *cpuusage;
8108 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
8109#else
8110 data = *cpuusage;
8111#endif
8112
8113 return data;
8114}
8115
8116static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val)
8117{
8118 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
8119
8120#ifndef CONFIG_64BIT
8121 /*
8122 * Take rq->lock to make 64-bit write safe on 32-bit platforms.
8123 */
8124 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
8125 *cpuusage = val;
8126 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
8127#else
8128 *cpuusage = val;
8129#endif
8130}
8131
8132/* return total cpu usage (in nanoseconds) of a group */
8133static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
8134{
8135 struct cpuacct *ca = cgroup_ca(cgrp);
8136 u64 totalcpuusage = 0;
8137 int i;
8138
8139 for_each_present_cpu(i)
8140 totalcpuusage += cpuacct_cpuusage_read(ca, i);
8141
8142 return totalcpuusage;
8143}
8144
8145static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
8146 u64 reset)
8147{
8148 struct cpuacct *ca = cgroup_ca(cgrp);
8149 int err = 0;
8150 int i;
8151
8152 if (reset) {
8153 err = -EINVAL;
8154 goto out;
8155 }
8156
8157 for_each_present_cpu(i)
8158 cpuacct_cpuusage_write(ca, i, 0);
8159
8160out:
8161 return err;
8162}
8163
8164static int cpuacct_percpu_seq_read(struct cgroup *cgroup, struct cftype *cft,
8165 struct seq_file *m)
8166{
8167 struct cpuacct *ca = cgroup_ca(cgroup);
8168 u64 percpu;
8169 int i;
8170
8171 for_each_present_cpu(i) {
8172 percpu = cpuacct_cpuusage_read(ca, i);
8173 seq_printf(m, "%llu ", (unsigned long long) percpu);
8174 }
8175 seq_printf(m, "\n");
8176 return 0;
8177}
8178
8179static const char *cpuacct_stat_desc[] = {
8180 [CPUACCT_STAT_USER] = "user",
8181 [CPUACCT_STAT_SYSTEM] = "system",
8182};
8183
8184static int cpuacct_stats_show(struct cgroup *cgrp, struct cftype *cft,
8185 struct cgroup_map_cb *cb)
8186{
8187 struct cpuacct *ca = cgroup_ca(cgrp);
8188 int cpu;
8189 s64 val = 0;
8190
8191 for_each_online_cpu(cpu) {
8192 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
8193 val += kcpustat->cpustat[CPUTIME_USER];
8194 val += kcpustat->cpustat[CPUTIME_NICE];
8195 }
8196 val = cputime64_to_clock_t(val);
8197 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_USER], val);
8198
8199 val = 0;
8200 for_each_online_cpu(cpu) {
8201 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu);
8202 val += kcpustat->cpustat[CPUTIME_SYSTEM];
8203 val += kcpustat->cpustat[CPUTIME_IRQ];
8204 val += kcpustat->cpustat[CPUTIME_SOFTIRQ];
8205 }
8206
8207 val = cputime64_to_clock_t(val);
8208 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
8209
8210 return 0;
8211}
8212
8213static struct cftype files[] = {
8214 {
8215 .name = "usage",
8216 .read_u64 = cpuusage_read,
8217 .write_u64 = cpuusage_write,
8218 },
8219 {
8220 .name = "usage_percpu",
8221 .read_seq_string = cpuacct_percpu_seq_read,
8222 },
8223 {
8224 .name = "stat",
8225 .read_map = cpuacct_stats_show,
8226 },
8227 { } /* terminate */
8228};
8229
8230/*
8231 * charge this task's execution time to its accounting group.
8232 *
8233 * called with rq->lock held.
8234 */
8235void cpuacct_charge(struct task_struct *tsk, u64 cputime)
8236{
8237 struct cpuacct *ca;
8238 int cpu;
8239
8240 if (unlikely(!cpuacct_subsys.active))
8241 return;
8242
8243 cpu = task_cpu(tsk);
8244
8245 rcu_read_lock();
8246
8247 ca = task_ca(tsk);
8248
8249 for (; ca; ca = parent_ca(ca)) {
8250 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
8251 *cpuusage += cputime;
8252 }
8253
8254 rcu_read_unlock();
8255}
8256
8257struct cgroup_subsys cpuacct_subsys = {
8258 .name = "cpuacct",
8259 .css_alloc = cpuacct_css_alloc,
8260 .css_free = cpuacct_css_free,
8261 .subsys_id = cpuacct_subsys_id,
8262 .base_cftypes = files,
8263};
8264#endif /* CONFIG_CGROUP_CPUACCT */
8265
8266void dump_cpu_task(int cpu) 8046void dump_cpu_task(int cpu)
8267{ 8047{
8268 pr_info("Task dump for CPU %d:\n", cpu); 8048 pr_info("Task dump for CPU %d:\n", cpu);
diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
new file mode 100644
index 000000000000..50ec24b6193d
--- /dev/null
+++ b/kernel/sched/cpuacct.c
@@ -0,0 +1,227 @@
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>
9
10#include "sched.h"
11
12/*
13 * CPU accounting code for task groups.
14 *
15 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh
16 * (balbir@in.ibm.com).
17 */
18
19struct cpuacct root_cpuacct;
20
21/* create a new cpu accounting group */
22static struct cgroup_subsys_state *cpuacct_css_alloc(struct cgroup *cgrp)
23{
24 struct cpuacct *ca;
25
26 if (!cgrp->parent)
27 return &root_cpuacct.css;
28
29 ca = kzalloc(sizeof(*ca), GFP_KERNEL);
30 if (!ca)
31 goto out;
32
33 ca->cpuusage = alloc_percpu(u64);
34 if (!ca->cpuusage)
35 goto out_free_ca;
36
37 ca->cpustat = alloc_percpu(struct kernel_cpustat);
38 if (!ca->cpustat)
39 goto out_free_cpuusage;
40
41 return &ca->css;
42
43out_free_cpuusage:
44 free_percpu(ca->cpuusage);
45out_free_ca:
46 kfree(ca);
47out:
48 return ERR_PTR(-ENOMEM);
49}
50
51/* destroy an existing cpu accounting group */
52static void cpuacct_css_free(struct cgroup *cgrp)
53{
54 struct cpuacct *ca = cgroup_ca(cgrp);
55
56 free_percpu(ca->cpustat);
57 free_percpu(ca->cpuusage);
58 kfree(ca);
59}
60
61static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu)
62{
63 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
64 u64 data;
65
66#ifndef CONFIG_64BIT
67 /*
68 * Take rq->lock to make 64-bit read safe on 32-bit platforms.
69 */
70 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
71 data = *cpuusage;
72 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
73#else
74 data = *cpuusage;
75#endif
76
77 return data;
78}
79
80static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val)
81{
82 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
83
84#ifndef CONFIG_64BIT
85 /*
86 * Take rq->lock to make 64-bit write safe on 32-bit platforms.
87 */
88 raw_spin_lock_irq(&cpu_rq(cpu)->lock);
89 *cpuusage = val;
90 raw_spin_unlock_irq(&cpu_rq(cpu)->lock);
91#else
92 *cpuusage = val;
93#endif
94}
95
96/* return total cpu usage (in nanoseconds) of a group */
97static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
98{
99 struct cpuacct *ca = cgroup_ca(cgrp);
100 u64 totalcpuusage = 0;
101 int i;
102
103 for_each_present_cpu(i)
104 totalcpuusage += cpuacct_cpuusage_read(ca, i);
105
106 return totalcpuusage;
107}
108
109static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
110 u64 reset)
111{
112 struct cpuacct *ca = cgroup_ca(cgrp);
113 int err = 0;
114 int i;
115
116 if (reset) {
117 err = -EINVAL;
118 goto out;
119 }
120
121 for_each_present_cpu(i)
122 cpuacct_cpuusage_write(ca, i, 0);
123
124out:
125 return err;
126}
127
128static int cpuacct_percpu_seq_read(struct cgroup *cgroup, struct cftype *cft,
129 struct seq_file *m)
130{
131 struct cpuacct *ca = cgroup_ca(cgroup);
132 u64 percpu;
133 int i;
134
135 for_each_present_cpu(i) {
136 percpu = cpuacct_cpuusage_read(ca, i);
137 seq_printf(m, "%llu ", (unsigned long long) percpu);
138 }
139 seq_printf(m, "\n");
140 return 0;
141}
142
143static const char * const cpuacct_stat_desc[] = {
144 [CPUACCT_STAT_USER] = "user",
145 [CPUACCT_STAT_SYSTEM] = "system",
146};
147
148static int cpuacct_stats_show(struct cgroup *cgrp, struct cftype *cft,
149 struct cgroup_map_cb *cb)
150{
151 struct cpuacct *ca = cgroup_ca(cgrp);
152 int cpu;
153 s64 val = 0;
154
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];
159 }
160 val = cputime64_to_clock_t(val);
161 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_USER], val);
162
163 val = 0;
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];
169 }
170
171 val = cputime64_to_clock_t(val);
172 cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
173
174 return 0;
175}
176
177static struct cftype files[] = {
178 {
179 .name = "usage",
180 .read_u64 = cpuusage_read,
181 .write_u64 = cpuusage_write,
182 },
183 {
184 .name = "usage_percpu",
185 .read_seq_string = cpuacct_percpu_seq_read,
186 },
187 {
188 .name = "stat",
189 .read_map = cpuacct_stats_show,
190 },
191 { } /* terminate */
192};
193
194/*
195 * charge this task's execution time to its accounting group.
196 *
197 * called with rq->lock held.
198 */
199void cpuacct_charge(struct task_struct *tsk, u64 cputime)
200{
201 struct cpuacct *ca;
202 int cpu;
203
204 if (unlikely(!cpuacct_subsys.active))
205 return;
206
207 cpu = task_cpu(tsk);
208
209 rcu_read_lock();
210
211 ca = task_ca(tsk);
212
213 for (; ca; ca = parent_ca(ca)) {
214 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
215 *cpuusage += cputime;
216 }
217
218 rcu_read_unlock();
219}
220
221struct cgroup_subsys cpuacct_subsys = {
222 .name = "cpuacct",
223 .css_alloc = cpuacct_css_alloc,
224 .css_free = cpuacct_css_free,
225 .subsys_id = cpuacct_subsys_id,
226 .base_cftypes = files,
227};