0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 enum cpuacct_stat_index {
0012 CPUACCT_STAT_USER,
0013 CPUACCT_STAT_SYSTEM,
0014
0015 CPUACCT_STAT_NSTATS,
0016 };
0017
0018 static const char * const cpuacct_stat_desc[] = {
0019 [CPUACCT_STAT_USER] = "user",
0020 [CPUACCT_STAT_SYSTEM] = "system",
0021 };
0022
0023
0024 struct cpuacct {
0025 struct cgroup_subsys_state css;
0026
0027 u64 __percpu *cpuusage;
0028 struct kernel_cpustat __percpu *cpustat;
0029 };
0030
0031 static inline struct cpuacct *css_ca(struct cgroup_subsys_state *css)
0032 {
0033 return css ? container_of(css, struct cpuacct, css) : NULL;
0034 }
0035
0036
0037 static inline struct cpuacct *task_ca(struct task_struct *tsk)
0038 {
0039 return css_ca(task_css(tsk, cpuacct_cgrp_id));
0040 }
0041
0042 static inline struct cpuacct *parent_ca(struct cpuacct *ca)
0043 {
0044 return css_ca(ca->css.parent);
0045 }
0046
0047 static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage);
0048 static struct cpuacct root_cpuacct = {
0049 .cpustat = &kernel_cpustat,
0050 .cpuusage = &root_cpuacct_cpuusage,
0051 };
0052
0053
0054 static struct cgroup_subsys_state *
0055 cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)
0056 {
0057 struct cpuacct *ca;
0058
0059 if (!parent_css)
0060 return &root_cpuacct.css;
0061
0062 ca = kzalloc(sizeof(*ca), GFP_KERNEL);
0063 if (!ca)
0064 goto out;
0065
0066 ca->cpuusage = alloc_percpu(u64);
0067 if (!ca->cpuusage)
0068 goto out_free_ca;
0069
0070 ca->cpustat = alloc_percpu(struct kernel_cpustat);
0071 if (!ca->cpustat)
0072 goto out_free_cpuusage;
0073
0074 return &ca->css;
0075
0076 out_free_cpuusage:
0077 free_percpu(ca->cpuusage);
0078 out_free_ca:
0079 kfree(ca);
0080 out:
0081 return ERR_PTR(-ENOMEM);
0082 }
0083
0084
0085 static void cpuacct_css_free(struct cgroup_subsys_state *css)
0086 {
0087 struct cpuacct *ca = css_ca(css);
0088
0089 free_percpu(ca->cpustat);
0090 free_percpu(ca->cpuusage);
0091 kfree(ca);
0092 }
0093
0094 static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu,
0095 enum cpuacct_stat_index index)
0096 {
0097 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
0098 u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;
0099 u64 data;
0100
0101
0102
0103
0104
0105 if (WARN_ON_ONCE(index > CPUACCT_STAT_NSTATS))
0106 return 0;
0107
0108 #ifndef CONFIG_64BIT
0109
0110
0111
0112 raw_spin_rq_lock_irq(cpu_rq(cpu));
0113 #endif
0114
0115 switch (index) {
0116 case CPUACCT_STAT_USER:
0117 data = cpustat[CPUTIME_USER] + cpustat[CPUTIME_NICE];
0118 break;
0119 case CPUACCT_STAT_SYSTEM:
0120 data = cpustat[CPUTIME_SYSTEM] + cpustat[CPUTIME_IRQ] +
0121 cpustat[CPUTIME_SOFTIRQ];
0122 break;
0123 case CPUACCT_STAT_NSTATS:
0124 data = *cpuusage;
0125 break;
0126 }
0127
0128 #ifndef CONFIG_64BIT
0129 raw_spin_rq_unlock_irq(cpu_rq(cpu));
0130 #endif
0131
0132 return data;
0133 }
0134
0135 static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu)
0136 {
0137 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
0138 u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;
0139
0140
0141 if (ca == &root_cpuacct)
0142 return;
0143
0144 #ifndef CONFIG_64BIT
0145
0146
0147
0148 raw_spin_rq_lock_irq(cpu_rq(cpu));
0149 #endif
0150 *cpuusage = 0;
0151 cpustat[CPUTIME_USER] = cpustat[CPUTIME_NICE] = 0;
0152 cpustat[CPUTIME_SYSTEM] = cpustat[CPUTIME_IRQ] = 0;
0153 cpustat[CPUTIME_SOFTIRQ] = 0;
0154
0155 #ifndef CONFIG_64BIT
0156 raw_spin_rq_unlock_irq(cpu_rq(cpu));
0157 #endif
0158 }
0159
0160
0161 static u64 __cpuusage_read(struct cgroup_subsys_state *css,
0162 enum cpuacct_stat_index index)
0163 {
0164 struct cpuacct *ca = css_ca(css);
0165 u64 totalcpuusage = 0;
0166 int i;
0167
0168 for_each_possible_cpu(i)
0169 totalcpuusage += cpuacct_cpuusage_read(ca, i, index);
0170
0171 return totalcpuusage;
0172 }
0173
0174 static u64 cpuusage_user_read(struct cgroup_subsys_state *css,
0175 struct cftype *cft)
0176 {
0177 return __cpuusage_read(css, CPUACCT_STAT_USER);
0178 }
0179
0180 static u64 cpuusage_sys_read(struct cgroup_subsys_state *css,
0181 struct cftype *cft)
0182 {
0183 return __cpuusage_read(css, CPUACCT_STAT_SYSTEM);
0184 }
0185
0186 static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft)
0187 {
0188 return __cpuusage_read(css, CPUACCT_STAT_NSTATS);
0189 }
0190
0191 static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft,
0192 u64 val)
0193 {
0194 struct cpuacct *ca = css_ca(css);
0195 int cpu;
0196
0197
0198
0199
0200 if (val)
0201 return -EINVAL;
0202
0203 for_each_possible_cpu(cpu)
0204 cpuacct_cpuusage_write(ca, cpu);
0205
0206 return 0;
0207 }
0208
0209 static int __cpuacct_percpu_seq_show(struct seq_file *m,
0210 enum cpuacct_stat_index index)
0211 {
0212 struct cpuacct *ca = css_ca(seq_css(m));
0213 u64 percpu;
0214 int i;
0215
0216 for_each_possible_cpu(i) {
0217 percpu = cpuacct_cpuusage_read(ca, i, index);
0218 seq_printf(m, "%llu ", (unsigned long long) percpu);
0219 }
0220 seq_printf(m, "\n");
0221 return 0;
0222 }
0223
0224 static int cpuacct_percpu_user_seq_show(struct seq_file *m, void *V)
0225 {
0226 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_USER);
0227 }
0228
0229 static int cpuacct_percpu_sys_seq_show(struct seq_file *m, void *V)
0230 {
0231 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_SYSTEM);
0232 }
0233
0234 static int cpuacct_percpu_seq_show(struct seq_file *m, void *V)
0235 {
0236 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_NSTATS);
0237 }
0238
0239 static int cpuacct_all_seq_show(struct seq_file *m, void *V)
0240 {
0241 struct cpuacct *ca = css_ca(seq_css(m));
0242 int index;
0243 int cpu;
0244
0245 seq_puts(m, "cpu");
0246 for (index = 0; index < CPUACCT_STAT_NSTATS; index++)
0247 seq_printf(m, " %s", cpuacct_stat_desc[index]);
0248 seq_puts(m, "\n");
0249
0250 for_each_possible_cpu(cpu) {
0251 seq_printf(m, "%d", cpu);
0252 for (index = 0; index < CPUACCT_STAT_NSTATS; index++)
0253 seq_printf(m, " %llu",
0254 cpuacct_cpuusage_read(ca, cpu, index));
0255 seq_puts(m, "\n");
0256 }
0257 return 0;
0258 }
0259
0260 static int cpuacct_stats_show(struct seq_file *sf, void *v)
0261 {
0262 struct cpuacct *ca = css_ca(seq_css(sf));
0263 struct task_cputime cputime;
0264 u64 val[CPUACCT_STAT_NSTATS];
0265 int cpu;
0266 int stat;
0267
0268 memset(&cputime, 0, sizeof(cputime));
0269 for_each_possible_cpu(cpu) {
0270 u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat;
0271
0272 cputime.utime += cpustat[CPUTIME_USER];
0273 cputime.utime += cpustat[CPUTIME_NICE];
0274 cputime.stime += cpustat[CPUTIME_SYSTEM];
0275 cputime.stime += cpustat[CPUTIME_IRQ];
0276 cputime.stime += cpustat[CPUTIME_SOFTIRQ];
0277
0278 cputime.sum_exec_runtime += *per_cpu_ptr(ca->cpuusage, cpu);
0279 }
0280
0281 cputime_adjust(&cputime, &seq_css(sf)->cgroup->prev_cputime,
0282 &val[CPUACCT_STAT_USER], &val[CPUACCT_STAT_SYSTEM]);
0283
0284 for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) {
0285 seq_printf(sf, "%s %llu\n", cpuacct_stat_desc[stat],
0286 nsec_to_clock_t(val[stat]));
0287 }
0288
0289 return 0;
0290 }
0291
0292 static struct cftype files[] = {
0293 {
0294 .name = "usage",
0295 .read_u64 = cpuusage_read,
0296 .write_u64 = cpuusage_write,
0297 },
0298 {
0299 .name = "usage_user",
0300 .read_u64 = cpuusage_user_read,
0301 },
0302 {
0303 .name = "usage_sys",
0304 .read_u64 = cpuusage_sys_read,
0305 },
0306 {
0307 .name = "usage_percpu",
0308 .seq_show = cpuacct_percpu_seq_show,
0309 },
0310 {
0311 .name = "usage_percpu_user",
0312 .seq_show = cpuacct_percpu_user_seq_show,
0313 },
0314 {
0315 .name = "usage_percpu_sys",
0316 .seq_show = cpuacct_percpu_sys_seq_show,
0317 },
0318 {
0319 .name = "usage_all",
0320 .seq_show = cpuacct_all_seq_show,
0321 },
0322 {
0323 .name = "stat",
0324 .seq_show = cpuacct_stats_show,
0325 },
0326 { }
0327 };
0328
0329
0330
0331
0332
0333
0334 void cpuacct_charge(struct task_struct *tsk, u64 cputime)
0335 {
0336 unsigned int cpu = task_cpu(tsk);
0337 struct cpuacct *ca;
0338
0339 lockdep_assert_rq_held(cpu_rq(cpu));
0340
0341 for (ca = task_ca(tsk); ca; ca = parent_ca(ca))
0342 *per_cpu_ptr(ca->cpuusage, cpu) += cputime;
0343 }
0344
0345
0346
0347
0348
0349
0350 void cpuacct_account_field(struct task_struct *tsk, int index, u64 val)
0351 {
0352 struct cpuacct *ca;
0353
0354 for (ca = task_ca(tsk); ca != &root_cpuacct; ca = parent_ca(ca))
0355 __this_cpu_add(ca->cpustat->cpustat[index], val);
0356 }
0357
0358 struct cgroup_subsys cpuacct_cgrp_subsys = {
0359 .css_alloc = cpuacct_css_alloc,
0360 .css_free = cpuacct_css_free,
0361 .legacy_cftypes = files,
0362 .early_init = true,
0363 };