1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/cgroup.h> 3 #include <linux/slab.h> 4 #include <linux/percpu.h> 5 #include <linux/spinlock.h> 6 #include <linux/cpumask.h> 7 #include <linux/seq_file.h> 8 #include <linux/rcupdate.h> 9 #include <linux/kernel_stat.h> 10 #include <linux/err.h> 11 12 #include "sched.h" 13 14 /* 15 * CPU accounting code for task groups. 16 * 17 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh 18 * (balbir@in.ibm.com). 19 */ 20 21 /* Time spent by the tasks of the cpu accounting group executing in ... */ 22 enum cpuacct_stat_index { 23 CPUACCT_STAT_USER, /* ... user mode */ 24 CPUACCT_STAT_SYSTEM, /* ... kernel mode */ 25 26 CPUACCT_STAT_NSTATS, 27 }; 28 29 static const char * const cpuacct_stat_desc[] = { 30 [CPUACCT_STAT_USER] = "user", 31 [CPUACCT_STAT_SYSTEM] = "system", 32 }; 33 34 struct cpuacct_usage { 35 u64 usages[CPUACCT_STAT_NSTATS]; 36 }; 37 38 /* track cpu usage of a group of tasks and its child groups */ 39 struct cpuacct { 40 struct cgroup_subsys_state css; 41 /* cpuusage holds pointer to a u64-type object on every cpu */ 42 struct cpuacct_usage __percpu *cpuusage; 43 struct kernel_cpustat __percpu *cpustat; 44 }; 45 46 static inline struct cpuacct *css_ca(struct cgroup_subsys_state *css) 47 { 48 return css ? container_of(css, struct cpuacct, css) : NULL; 49 } 50 51 /* return cpu accounting group to which this task belongs */ 52 static inline struct cpuacct *task_ca(struct task_struct *tsk) 53 { 54 return css_ca(task_css(tsk, cpuacct_cgrp_id)); 55 } 56 57 static inline struct cpuacct *parent_ca(struct cpuacct *ca) 58 { 59 return css_ca(ca->css.parent); 60 } 61 62 static DEFINE_PER_CPU(struct cpuacct_usage, root_cpuacct_cpuusage); 63 static struct cpuacct root_cpuacct = { 64 .cpustat = &kernel_cpustat, 65 .cpuusage = &root_cpuacct_cpuusage, 66 }; 67 68 /* create a new cpu accounting group */ 69 static struct cgroup_subsys_state * 70 cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) 71 { 72 struct cpuacct *ca; 73 74 if (!parent_css) 75 return &root_cpuacct.css; 76 77 ca = kzalloc(sizeof(*ca), GFP_KERNEL); 78 if (!ca) 79 goto out; 80 81 ca->cpuusage = alloc_percpu(struct cpuacct_usage); 82 if (!ca->cpuusage) 83 goto out_free_ca; 84 85 ca->cpustat = alloc_percpu(struct kernel_cpustat); 86 if (!ca->cpustat) 87 goto out_free_cpuusage; 88 89 return &ca->css; 90 91 out_free_cpuusage: 92 free_percpu(ca->cpuusage); 93 out_free_ca: 94 kfree(ca); 95 out: 96 return ERR_PTR(-ENOMEM); 97 } 98 99 /* destroy an existing cpu accounting group */ 100 static void cpuacct_css_free(struct cgroup_subsys_state *css) 101 { 102 struct cpuacct *ca = css_ca(css); 103 104 free_percpu(ca->cpustat); 105 free_percpu(ca->cpuusage); 106 kfree(ca); 107 } 108 109 static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu, 110 enum cpuacct_stat_index index) 111 { 112 struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 113 u64 data; 114 115 /* 116 * We allow index == CPUACCT_STAT_NSTATS here to read 117 * the sum of suages. 118 */ 119 BUG_ON(index > CPUACCT_STAT_NSTATS); 120 121 #ifndef CONFIG_64BIT 122 /* 123 * Take rq->lock to make 64-bit read safe on 32-bit platforms. 124 */ 125 raw_spin_lock_irq(&cpu_rq(cpu)->lock); 126 #endif 127 128 if (index == CPUACCT_STAT_NSTATS) { 129 int i = 0; 130 131 data = 0; 132 for (i = 0; i < CPUACCT_STAT_NSTATS; i++) 133 data += cpuusage->usages[i]; 134 } else { 135 data = cpuusage->usages[index]; 136 } 137 138 #ifndef CONFIG_64BIT 139 raw_spin_unlock_irq(&cpu_rq(cpu)->lock); 140 #endif 141 142 return data; 143 } 144 145 static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) 146 { 147 struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 148 int i; 149 150 #ifndef CONFIG_64BIT 151 /* 152 * Take rq->lock to make 64-bit write safe on 32-bit platforms. 153 */ 154 raw_spin_lock_irq(&cpu_rq(cpu)->lock); 155 #endif 156 157 for (i = 0; i < CPUACCT_STAT_NSTATS; i++) 158 cpuusage->usages[i] = val; 159 160 #ifndef CONFIG_64BIT 161 raw_spin_unlock_irq(&cpu_rq(cpu)->lock); 162 #endif 163 } 164 165 /* return total cpu usage (in nanoseconds) of a group */ 166 static u64 __cpuusage_read(struct cgroup_subsys_state *css, 167 enum cpuacct_stat_index index) 168 { 169 struct cpuacct *ca = css_ca(css); 170 u64 totalcpuusage = 0; 171 int i; 172 173 for_each_possible_cpu(i) 174 totalcpuusage += cpuacct_cpuusage_read(ca, i, index); 175 176 return totalcpuusage; 177 } 178 179 static u64 cpuusage_user_read(struct cgroup_subsys_state *css, 180 struct cftype *cft) 181 { 182 return __cpuusage_read(css, CPUACCT_STAT_USER); 183 } 184 185 static u64 cpuusage_sys_read(struct cgroup_subsys_state *css, 186 struct cftype *cft) 187 { 188 return __cpuusage_read(css, CPUACCT_STAT_SYSTEM); 189 } 190 191 static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft) 192 { 193 return __cpuusage_read(css, CPUACCT_STAT_NSTATS); 194 } 195 196 static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft, 197 u64 val) 198 { 199 struct cpuacct *ca = css_ca(css); 200 int cpu; 201 202 /* 203 * Only allow '0' here to do a reset. 204 */ 205 if (val) 206 return -EINVAL; 207 208 for_each_possible_cpu(cpu) 209 cpuacct_cpuusage_write(ca, cpu, 0); 210 211 return 0; 212 } 213 214 static int __cpuacct_percpu_seq_show(struct seq_file *m, 215 enum cpuacct_stat_index index) 216 { 217 struct cpuacct *ca = css_ca(seq_css(m)); 218 u64 percpu; 219 int i; 220 221 for_each_possible_cpu(i) { 222 percpu = cpuacct_cpuusage_read(ca, i, index); 223 seq_printf(m, "%llu ", (unsigned long long) percpu); 224 } 225 seq_printf(m, "\n"); 226 return 0; 227 } 228 229 static int cpuacct_percpu_user_seq_show(struct seq_file *m, void *V) 230 { 231 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_USER); 232 } 233 234 static int cpuacct_percpu_sys_seq_show(struct seq_file *m, void *V) 235 { 236 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_SYSTEM); 237 } 238 239 static int cpuacct_percpu_seq_show(struct seq_file *m, void *V) 240 { 241 return __cpuacct_percpu_seq_show(m, CPUACCT_STAT_NSTATS); 242 } 243 244 static int cpuacct_all_seq_show(struct seq_file *m, void *V) 245 { 246 struct cpuacct *ca = css_ca(seq_css(m)); 247 int index; 248 int cpu; 249 250 seq_puts(m, "cpu"); 251 for (index = 0; index < CPUACCT_STAT_NSTATS; index++) 252 seq_printf(m, " %s", cpuacct_stat_desc[index]); 253 seq_puts(m, "\n"); 254 255 for_each_possible_cpu(cpu) { 256 struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 257 258 seq_printf(m, "%d", cpu); 259 260 for (index = 0; index < CPUACCT_STAT_NSTATS; index++) { 261 #ifndef CONFIG_64BIT 262 /* 263 * Take rq->lock to make 64-bit read safe on 32-bit 264 * platforms. 265 */ 266 raw_spin_lock_irq(&cpu_rq(cpu)->lock); 267 #endif 268 269 seq_printf(m, " %llu", cpuusage->usages[index]); 270 271 #ifndef CONFIG_64BIT 272 raw_spin_unlock_irq(&cpu_rq(cpu)->lock); 273 #endif 274 } 275 seq_puts(m, "\n"); 276 } 277 return 0; 278 } 279 280 static int cpuacct_stats_show(struct seq_file *sf, void *v) 281 { 282 struct cpuacct *ca = css_ca(seq_css(sf)); 283 s64 val[CPUACCT_STAT_NSTATS]; 284 int cpu; 285 int stat; 286 287 memset(val, 0, sizeof(val)); 288 for_each_possible_cpu(cpu) { 289 u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat; 290 291 val[CPUACCT_STAT_USER] += cpustat[CPUTIME_USER]; 292 val[CPUACCT_STAT_USER] += cpustat[CPUTIME_NICE]; 293 val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SYSTEM]; 294 val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_IRQ]; 295 val[CPUACCT_STAT_SYSTEM] += cpustat[CPUTIME_SOFTIRQ]; 296 } 297 298 for (stat = 0; stat < CPUACCT_STAT_NSTATS; stat++) { 299 seq_printf(sf, "%s %lld\n", 300 cpuacct_stat_desc[stat], 301 (long long)nsec_to_clock_t(val[stat])); 302 } 303 304 return 0; 305 } 306 307 static struct cftype files[] = { 308 { 309 .name = "usage", 310 .read_u64 = cpuusage_read, 311 .write_u64 = cpuusage_write, 312 }, 313 { 314 .name = "usage_user", 315 .read_u64 = cpuusage_user_read, 316 }, 317 { 318 .name = "usage_sys", 319 .read_u64 = cpuusage_sys_read, 320 }, 321 { 322 .name = "usage_percpu", 323 .seq_show = cpuacct_percpu_seq_show, 324 }, 325 { 326 .name = "usage_percpu_user", 327 .seq_show = cpuacct_percpu_user_seq_show, 328 }, 329 { 330 .name = "usage_percpu_sys", 331 .seq_show = cpuacct_percpu_sys_seq_show, 332 }, 333 { 334 .name = "usage_all", 335 .seq_show = cpuacct_all_seq_show, 336 }, 337 { 338 .name = "stat", 339 .seq_show = cpuacct_stats_show, 340 }, 341 { } /* terminate */ 342 }; 343 344 /* 345 * charge this task's execution time to its accounting group. 346 * 347 * called with rq->lock held. 348 */ 349 void cpuacct_charge(struct task_struct *tsk, u64 cputime) 350 { 351 struct cpuacct *ca; 352 int index = CPUACCT_STAT_SYSTEM; 353 struct pt_regs *regs = task_pt_regs(tsk); 354 355 if (regs && user_mode(regs)) 356 index = CPUACCT_STAT_USER; 357 358 rcu_read_lock(); 359 360 for (ca = task_ca(tsk); ca; ca = parent_ca(ca)) 361 this_cpu_ptr(ca->cpuusage)->usages[index] += cputime; 362 363 rcu_read_unlock(); 364 } 365 366 /* 367 * Add user/system time to cpuacct. 368 * 369 * Note: it's the caller that updates the account of the root cgroup. 370 */ 371 void cpuacct_account_field(struct task_struct *tsk, int index, u64 val) 372 { 373 struct cpuacct *ca; 374 375 rcu_read_lock(); 376 for (ca = task_ca(tsk); ca != &root_cpuacct; ca = parent_ca(ca)) 377 this_cpu_ptr(ca->cpustat)->cpustat[index] += val; 378 rcu_read_unlock(); 379 } 380 381 struct cgroup_subsys cpuacct_cgrp_subsys = { 382 .css_alloc = cpuacct_css_alloc, 383 .css_free = cpuacct_css_free, 384 .legacy_cftypes = files, 385 .early_init = true, 386 }; 387