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 ... */ 21 enum 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 */ 29 struct 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 36 static 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 */ 42 static inline struct cpuacct *task_ca(struct task_struct *tsk) 43 { 44 return css_ca(task_css(tsk, cpuacct_cgrp_id)); 45 } 46 47 static inline struct cpuacct *parent_ca(struct cpuacct *ca) 48 { 49 return css_ca(css_parent(&ca->css)); 50 } 51 52 static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage); 53 static struct cpuacct root_cpuacct = { 54 .cpustat = &kernel_cpustat, 55 .cpuusage = &root_cpuacct_cpuusage, 56 }; 57 58 /* create a new cpu accounting group */ 59 static struct cgroup_subsys_state * 60 cpuacct_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 81 out_free_cpuusage: 82 free_percpu(ca->cpuusage); 83 out_free_ca: 84 kfree(ca); 85 out: 86 return ERR_PTR(-ENOMEM); 87 } 88 89 /* destroy an existing cpu accounting group */ 90 static 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 99 static 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 118 static 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 */ 135 static 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 147 static 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 162 out: 163 return err; 164 } 165 166 static 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 180 static const char * const cpuacct_stat_desc[] = { 181 [CPUACCT_STAT_USER] = "user", 182 [CPUACCT_STAT_SYSTEM] = "system", 183 }; 184 185 static 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 213 static 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 */ 235 void 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 */ 263 void 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 278 struct cgroup_subsys cpuacct_cgrp_subsys = { 279 .css_alloc = cpuacct_css_alloc, 280 .css_free = cpuacct_css_free, 281 .base_cftypes = files, 282 .early_init = 1, 283 }; 284