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#include <linux/err.h> 10 11#include "sched.h" 12 13/* 14 * CPU accounting code for task groups. 15 * 16 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh 17 * (balbir@in.ibm.com). 18 */ 19 20/* Time spent by the tasks of the cpu accounting group executing in ... */ 21enum cpuacct_stat_index { 22 CPUACCT_STAT_USER, /* ... user mode */ 23 CPUACCT_STAT_SYSTEM, /* ... kernel mode */ 24 25 CPUACCT_STAT_NSTATS, 26}; 27 28/* track cpu usage of a group of tasks and its child groups */ 29struct cpuacct { 30 struct cgroup_subsys_state css; 31 /* cpuusage holds pointer to a u64-type object on every cpu */ 32 u64 __percpu *cpuusage; 33 struct kernel_cpustat __percpu *cpustat; 34}; 35 36static inline struct cpuacct *css_ca(struct cgroup_subsys_state *css) 37{ 38 return css ? container_of(css, struct cpuacct, css) : NULL; 39} 40 41/* return cpu accounting group to which this task belongs */ 42static inline struct cpuacct *task_ca(struct task_struct *tsk) 43{ 44 return css_ca(task_css(tsk, cpuacct_cgrp_id)); 45} 46 47static inline struct cpuacct *parent_ca(struct cpuacct *ca) 48{ 49 return css_ca(ca->css.parent); 50} 51 52static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage); 53static struct cpuacct root_cpuacct = { 54 .cpustat = &kernel_cpustat, 55 .cpuusage = &root_cpuacct_cpuusage, 56}; 57 58/* create a new cpu accounting group */ 59static struct cgroup_subsys_state * 60cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) 61{ 62 struct cpuacct *ca; 63 64 if (!parent_css) 65 return &root_cpuacct.css; 66 67 ca = kzalloc(sizeof(*ca), GFP_KERNEL); 68 if (!ca) 69 goto out; 70 71 ca->cpuusage = alloc_percpu(u64); 72 if (!ca->cpuusage) 73 goto out_free_ca; 74 75 ca->cpustat = alloc_percpu(struct kernel_cpustat); 76 if (!ca->cpustat) 77 goto out_free_cpuusage; 78 79 return &ca->css; 80 81out_free_cpuusage: 82 free_percpu(ca->cpuusage); 83out_free_ca: 84 kfree(ca); 85out: 86 return ERR_PTR(-ENOMEM); 87} 88 89/* destroy an existing cpu accounting group */ 90static void cpuacct_css_free(struct cgroup_subsys_state *css) 91{ 92 struct cpuacct *ca = css_ca(css); 93 94 free_percpu(ca->cpustat); 95 free_percpu(ca->cpuusage); 96 kfree(ca); 97} 98 99static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) 100{ 101 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 102 u64 data; 103 104#ifndef CONFIG_64BIT 105 /* 106 * Take rq->lock to make 64-bit read safe on 32-bit platforms. 107 */ 108 raw_spin_lock_irq(&cpu_rq(cpu)->lock); 109 data = *cpuusage; 110 raw_spin_unlock_irq(&cpu_rq(cpu)->lock); 111#else 112 data = *cpuusage; 113#endif 114 115 return data; 116} 117 118static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) 119{ 120 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 121 122#ifndef CONFIG_64BIT 123 /* 124 * Take rq->lock to make 64-bit write safe on 32-bit platforms. 125 */ 126 raw_spin_lock_irq(&cpu_rq(cpu)->lock); 127 *cpuusage = val; 128 raw_spin_unlock_irq(&cpu_rq(cpu)->lock); 129#else 130 *cpuusage = val; 131#endif 132} 133 134/* return total cpu usage (in nanoseconds) of a group */ 135static u64 cpuusage_read(struct cgroup_subsys_state *css, struct cftype *cft) 136{ 137 struct cpuacct *ca = css_ca(css); 138 u64 totalcpuusage = 0; 139 int i; 140 141 for_each_present_cpu(i) 142 totalcpuusage += cpuacct_cpuusage_read(ca, i); 143 144 return totalcpuusage; 145} 146 147static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft, 148 u64 reset) 149{ 150 struct cpuacct *ca = css_ca(css); 151 int err = 0; 152 int i; 153 154 if (reset) { 155 err = -EINVAL; 156 goto out; 157 } 158 159 for_each_present_cpu(i) 160 cpuacct_cpuusage_write(ca, i, 0); 161 162out: 163 return err; 164} 165 166static int cpuacct_percpu_seq_show(struct seq_file *m, void *V) 167{ 168 struct cpuacct *ca = css_ca(seq_css(m)); 169 u64 percpu; 170 int i; 171 172 for_each_present_cpu(i) { 173 percpu = cpuacct_cpuusage_read(ca, i); 174 seq_printf(m, "%llu ", (unsigned long long) percpu); 175 } 176 seq_printf(m, "\n"); 177 return 0; 178} 179 180static const char * const cpuacct_stat_desc[] = { 181 [CPUACCT_STAT_USER] = "user", 182 [CPUACCT_STAT_SYSTEM] = "system", 183}; 184 185static int cpuacct_stats_show(struct seq_file *sf, void *v) 186{ 187 struct cpuacct *ca = css_ca(seq_css(sf)); 188 int cpu; 189 s64 val = 0; 190 191 for_each_online_cpu(cpu) { 192 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu); 193 val += kcpustat->cpustat[CPUTIME_USER]; 194 val += kcpustat->cpustat[CPUTIME_NICE]; 195 } 196 val = cputime64_to_clock_t(val); 197 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val); 198 199 val = 0; 200 for_each_online_cpu(cpu) { 201 struct kernel_cpustat *kcpustat = per_cpu_ptr(ca->cpustat, cpu); 202 val += kcpustat->cpustat[CPUTIME_SYSTEM]; 203 val += kcpustat->cpustat[CPUTIME_IRQ]; 204 val += kcpustat->cpustat[CPUTIME_SOFTIRQ]; 205 } 206 207 val = cputime64_to_clock_t(val); 208 seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val); 209 210 return 0; 211} 212 213static struct cftype files[] = { 214 { 215 .name = "usage", 216 .read_u64 = cpuusage_read, 217 .write_u64 = cpuusage_write, 218 }, 219 { 220 .name = "usage_percpu", 221 .seq_show = cpuacct_percpu_seq_show, 222 }, 223 { 224 .name = "stat", 225 .seq_show = cpuacct_stats_show, 226 }, 227 { } /* terminate */ 228}; 229 230/* 231 * charge this task's execution time to its accounting group. 232 * 233 * called with rq->lock held. 234 */ 235void cpuacct_charge(struct task_struct *tsk, u64 cputime) 236{ 237 struct cpuacct *ca; 238 int cpu; 239 240 cpu = task_cpu(tsk); 241 242 rcu_read_lock(); 243 244 ca = task_ca(tsk); 245 246 while (true) { 247 u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); 248 *cpuusage += cputime; 249 250 ca = parent_ca(ca); 251 if (!ca) 252 break; 253 } 254 255 rcu_read_unlock(); 256} 257 258/* 259 * Add user/system time to cpuacct. 260 * 261 * Note: it's the caller that updates the account of the root cgroup. 262 */ 263void cpuacct_account_field(struct task_struct *p, int index, u64 val) 264{ 265 struct kernel_cpustat *kcpustat; 266 struct cpuacct *ca; 267 268 rcu_read_lock(); 269 ca = task_ca(p); 270 while (ca != &root_cpuacct) { 271 kcpustat = this_cpu_ptr(ca->cpustat); 272 kcpustat->cpustat[index] += val; 273 ca = parent_ca(ca); 274 } 275 rcu_read_unlock(); 276} 277 278struct cgroup_subsys cpuacct_cgrp_subsys = { 279 .css_alloc = cpuacct_css_alloc, 280 .css_free = cpuacct_css_free, 281 .legacy_cftypes = files, 282 .early_init = 1, 283}; 284