···354354355355endchoice356356357357+config CGROUP_CPUACCT358358+ bool "Simple CPU accounting cgroup subsystem"359359+ depends on CGROUPS360360+ help361361+ Provides a simple Resource Controller for monitoring the362362+ total CPU consumed by the tasks in a cgroup363363+357364config SYSFS_DEPRECATED358365 bool "Create deprecated sysfs files"359366 default y
+129-26
kernel/sched.c
···854854 struct rq_iterator *iterator);855855#endif856856857857+#ifdef CONFIG_CGROUP_CPUACCT858858+static void cpuacct_charge(struct task_struct *tsk, u64 cputime);859859+#else860860+static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {}861861+#endif862862+857863#include "sched_stats.h"858864#include "sched_idletask.c"859865#include "sched_fair.c"···72277221 return (u64) tg->shares;72287222}7229722372307230-static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft)72317231-{72327232- struct task_group *tg = cgroup_tg(cgrp);72337233- unsigned long flags;72347234- u64 res = 0;72357235- int i;72367236-72377237- for_each_possible_cpu(i) {72387238- /*72397239- * Lock to prevent races with updating 64-bit counters72407240- * on 32-bit arches.72417241- */72427242- spin_lock_irqsave(&cpu_rq(i)->lock, flags);72437243- res += tg->se[i]->sum_exec_runtime;72447244- spin_unlock_irqrestore(&cpu_rq(i)->lock, flags);72457245- }72467246- /* Convert from ns to ms */72477247- do_div(res, NSEC_PER_MSEC);72487248-72497249- return res;72507250-}72517251-72527224static struct cftype cpu_files[] = {72537225 {72547226 .name = "shares",72557227 .read_uint = cpu_shares_read_uint,72567228 .write_uint = cpu_shares_write_uint,72577257- },72587258- {72597259- .name = "usage",72607260- .read_uint = cpu_usage_read,72617229 },72627230};72637231···72527272};7253727372547274#endif /* CONFIG_FAIR_CGROUP_SCHED */72757275+72767276+#ifdef CONFIG_CGROUP_CPUACCT72777277+72787278+/*72797279+ * CPU accounting code for task groups.72807280+ *72817281+ * Based on the work by Paul Menage (menage@google.com) and Balbir Singh72827282+ * (balbir@in.ibm.com).72837283+ */72847284+72857285+/* track cpu usage of a group of tasks */72867286+struct cpuacct {72877287+ struct cgroup_subsys_state css;72887288+ /* cpuusage holds pointer to a u64-type object on every cpu */72897289+ u64 *cpuusage;72907290+};72917291+72927292+struct cgroup_subsys cpuacct_subsys;72937293+72947294+/* return cpu accounting group corresponding to this container */72957295+static inline struct cpuacct *cgroup_ca(struct cgroup *cont)72967296+{72977297+ return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),72987298+ struct cpuacct, css);72997299+}73007300+73017301+/* return cpu accounting group to which this task belongs */73027302+static inline struct cpuacct *task_ca(struct task_struct *tsk)73037303+{73047304+ return container_of(task_subsys_state(tsk, cpuacct_subsys_id),73057305+ struct cpuacct, css);73067306+}73077307+73087308+/* create a new cpu accounting group */73097309+static struct cgroup_subsys_state *cpuacct_create(73107310+ struct cgroup_subsys *ss, struct cgroup *cont)73117311+{73127312+ struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);73137313+73147314+ if (!ca)73157315+ return ERR_PTR(-ENOMEM);73167316+73177317+ ca->cpuusage = alloc_percpu(u64);73187318+ if (!ca->cpuusage) {73197319+ kfree(ca);73207320+ return ERR_PTR(-ENOMEM);73217321+ }73227322+73237323+ return &ca->css;73247324+}73257325+73267326+/* destroy an existing cpu accounting group */73277327+static void cpuacct_destroy(struct cgroup_subsys *ss,73287328+ struct cgroup *cont)73297329+{73307330+ struct cpuacct *ca = cgroup_ca(cont);73317331+73327332+ free_percpu(ca->cpuusage);73337333+ kfree(ca);73347334+}73357335+73367336+/* return total cpu usage (in nanoseconds) of a group */73377337+static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)73387338+{73397339+ struct cpuacct *ca = cgroup_ca(cont);73407340+ u64 totalcpuusage = 0;73417341+ int i;73427342+73437343+ for_each_possible_cpu(i) {73447344+ u64 *cpuusage = percpu_ptr(ca->cpuusage, i);73457345+73467346+ /*73477347+ * Take rq->lock to make 64-bit addition safe on 32-bit73487348+ * platforms.73497349+ */73507350+ spin_lock_irq(&cpu_rq(i)->lock);73517351+ totalcpuusage += *cpuusage;73527352+ spin_unlock_irq(&cpu_rq(i)->lock);73537353+ }73547354+73557355+ return totalcpuusage;73567356+}73577357+73587358+static struct cftype files[] = {73597359+ {73607360+ .name = "usage",73617361+ .read_uint = cpuusage_read,73627362+ },73637363+};73647364+73657365+static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)73667366+{73677367+ return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));73687368+}73697369+73707370+/*73717371+ * charge this task's execution time to its accounting group.73727372+ *73737373+ * called with rq->lock held.73747374+ */73757375+static void cpuacct_charge(struct task_struct *tsk, u64 cputime)73767376+{73777377+ struct cpuacct *ca;73787378+73797379+ if (!cpuacct_subsys.active)73807380+ return;73817381+73827382+ ca = task_ca(tsk);73837383+ if (ca) {73847384+ u64 *cpuusage = percpu_ptr(ca->cpuusage, task_cpu(tsk));73857385+73867386+ *cpuusage += cputime;73877387+ }73887388+}73897389+73907390+struct cgroup_subsys cpuacct_subsys = {73917391+ .name = "cpuacct",73927392+ .create = cpuacct_create,73937393+ .destroy = cpuacct_destroy,73947394+ .populate = cpuacct_populate,73957395+ .subsys_id = cpuacct_subsys_id,73967396+};73977397+#endif /* CONFIG_CGROUP_CPUACCT */