diff options
| author | Li Zefan <lizefan@huawei.com> | 2013-03-29 02:36:31 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-04-10 07:54:15 -0400 |
| commit | 2e76c24d72372db35f226a49c2b99d0fd8cfd400 (patch) | |
| tree | c611ddffa64a2a2fef615f43fcd7a14fa7553a0e | |
| parent | b9b0853a4b377f84a5e6ed091816a9a2d6b10918 (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>
| -rw-r--r-- | kernel/sched/Makefile | 1 | ||||
| -rw-r--r-- | kernel/sched/core.c | 220 | ||||
| -rw-r--r-- | kernel/sched/cpuacct.c | 227 |
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 | |||
| 16 | obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o | 16 | obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o |
| 17 | obj-$(CONFIG_SCHEDSTATS) += stats.o | 17 | obj-$(CONFIG_SCHEDSTATS) += stats.o |
| 18 | obj-$(CONFIG_SCHED_DEBUG) += debug.o | 18 | obj-$(CONFIG_SCHED_DEBUG) += debug.o |
| 19 | obj-$(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 | |||
| 8055 | struct cpuacct root_cpuacct; | ||
| 8056 | |||
| 8057 | /* create a new cpu accounting group */ | ||
| 8058 | static 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 | |||
| 8079 | out_free_cpuusage: | ||
| 8080 | free_percpu(ca->cpuusage); | ||
| 8081 | out_free_ca: | ||
| 8082 | kfree(ca); | ||
| 8083 | out: | ||
| 8084 | return ERR_PTR(-ENOMEM); | ||
| 8085 | } | ||
| 8086 | |||
| 8087 | /* destroy an existing cpu accounting group */ | ||
| 8088 | static 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 | |||
| 8097 | static 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 | |||
| 8116 | static 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 */ | ||
| 8133 | static 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 | |||
| 8145 | static 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 | |||
| 8160 | out: | ||
| 8161 | return err; | ||
| 8162 | } | ||
| 8163 | |||
| 8164 | static 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 | |||
| 8179 | static const char *cpuacct_stat_desc[] = { | ||
| 8180 | [CPUACCT_STAT_USER] = "user", | ||
| 8181 | [CPUACCT_STAT_SYSTEM] = "system", | ||
| 8182 | }; | ||
| 8183 | |||
| 8184 | static 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 | |||
| 8213 | static 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 | */ | ||
| 8235 | void 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 | |||
| 8257 | struct 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 | |||
| 8266 | void dump_cpu_task(int cpu) | 8046 | void 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 | |||
| 19 | struct cpuacct root_cpuacct; | ||
| 20 | |||
| 21 | /* create a new cpu accounting group */ | ||
| 22 | static 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 | |||
| 43 | out_free_cpuusage: | ||
| 44 | free_percpu(ca->cpuusage); | ||
| 45 | out_free_ca: | ||
| 46 | kfree(ca); | ||
| 47 | out: | ||
| 48 | return ERR_PTR(-ENOMEM); | ||
| 49 | } | ||
| 50 | |||
| 51 | /* destroy an existing cpu accounting group */ | ||
| 52 | static 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 | |||
| 61 | static 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 | |||
| 80 | static 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 */ | ||
| 97 | static 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 | |||
| 109 | static 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 | |||
| 124 | out: | ||
| 125 | return err; | ||
| 126 | } | ||
| 127 | |||
| 128 | static 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 | |||
| 143 | static const char * const cpuacct_stat_desc[] = { | ||
| 144 | [CPUACCT_STAT_USER] = "user", | ||
| 145 | [CPUACCT_STAT_SYSTEM] = "system", | ||
| 146 | }; | ||
| 147 | |||
| 148 | static 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 | |||
| 177 | static 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 | */ | ||
| 199 | void 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 | |||
| 221 | struct 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 | }; | ||
