aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Kconfig.instrumentation4
-rw-r--r--kernel/sched.c155
-rw-r--r--kernel/sched_fair.c6
-rw-r--r--kernel/sched_rt.c1
4 files changed, 138 insertions, 28 deletions
diff --git a/kernel/Kconfig.instrumentation b/kernel/Kconfig.instrumentation
index f5f2c769d95e..2ea1e347df45 100644
--- a/kernel/Kconfig.instrumentation
+++ b/kernel/Kconfig.instrumentation
@@ -21,7 +21,7 @@ config PROFILING
21config OPROFILE 21config OPROFILE
22 tristate "OProfile system profiling (EXPERIMENTAL)" 22 tristate "OProfile system profiling (EXPERIMENTAL)"
23 depends on PROFILING 23 depends on PROFILING
24 depends on ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64 24 depends on (ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64) && !UML
25 help 25 help
26 OProfile is a profiling system capable of profiling the 26 OProfile is a profiling system capable of profiling the
27 whole system, include the kernel, kernel modules, libraries, 27 whole system, include the kernel, kernel modules, libraries,
@@ -32,7 +32,7 @@ config OPROFILE
32config KPROBES 32config KPROBES
33 bool "Kprobes" 33 bool "Kprobes"
34 depends on KALLSYMS && MODULES 34 depends on KALLSYMS && MODULES
35 depends on X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32 35 depends on (X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32) && !UML
36 help 36 help
37 Kprobes allows you to trap at almost any kernel address and 37 Kprobes allows you to trap at almost any kernel address and
38 execute a callback function. register_kprobe() establishes 38 execute a callback function. register_kprobe() establishes
diff --git a/kernel/sched.c b/kernel/sched.c
index 98dcdf272db3..59ff6b140edb 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -854,6 +854,12 @@ iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
854 struct rq_iterator *iterator); 854 struct rq_iterator *iterator);
855#endif 855#endif
856 856
857#ifdef CONFIG_CGROUP_CPUACCT
858static void cpuacct_charge(struct task_struct *tsk, u64 cputime);
859#else
860static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {}
861#endif
862
857#include "sched_stats.h" 863#include "sched_stats.h"
858#include "sched_idletask.c" 864#include "sched_idletask.c"
859#include "sched_fair.c" 865#include "sched_fair.c"
@@ -7221,38 +7227,12 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
7221 return (u64) tg->shares; 7227 return (u64) tg->shares;
7222} 7228}
7223 7229
7224static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft)
7225{
7226 struct task_group *tg = cgroup_tg(cgrp);
7227 unsigned long flags;
7228 u64 res = 0;
7229 int i;
7230
7231 for_each_possible_cpu(i) {
7232 /*
7233 * Lock to prevent races with updating 64-bit counters
7234 * on 32-bit arches.
7235 */
7236 spin_lock_irqsave(&cpu_rq(i)->lock, flags);
7237 res += tg->se[i]->sum_exec_runtime;
7238 spin_unlock_irqrestore(&cpu_rq(i)->lock, flags);
7239 }
7240 /* Convert from ns to ms */
7241 do_div(res, NSEC_PER_MSEC);
7242
7243 return res;
7244}
7245
7246static struct cftype cpu_files[] = { 7230static struct cftype cpu_files[] = {
7247 { 7231 {
7248 .name = "shares", 7232 .name = "shares",
7249 .read_uint = cpu_shares_read_uint, 7233 .read_uint = cpu_shares_read_uint,
7250 .write_uint = cpu_shares_write_uint, 7234 .write_uint = cpu_shares_write_uint,
7251 }, 7235 },
7252 {
7253 .name = "usage",
7254 .read_uint = cpu_usage_read,
7255 },
7256}; 7236};
7257 7237
7258static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont) 7238static int cpu_cgroup_populate(struct cgroup_subsys *ss, struct cgroup *cont)
@@ -7272,3 +7252,126 @@ struct cgroup_subsys cpu_cgroup_subsys = {
7272}; 7252};
7273 7253
7274#endif /* CONFIG_FAIR_CGROUP_SCHED */ 7254#endif /* CONFIG_FAIR_CGROUP_SCHED */
7255
7256#ifdef CONFIG_CGROUP_CPUACCT
7257
7258/*
7259 * CPU accounting code for task groups.
7260 *
7261 * Based on the work by Paul Menage (menage@google.com) and Balbir Singh
7262 * (balbir@in.ibm.com).
7263 */
7264
7265/* track cpu usage of a group of tasks */
7266struct cpuacct {
7267 struct cgroup_subsys_state css;
7268 /* cpuusage holds pointer to a u64-type object on every cpu */
7269 u64 *cpuusage;
7270};
7271
7272struct cgroup_subsys cpuacct_subsys;
7273
7274/* return cpu accounting group corresponding to this container */
7275static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
7276{
7277 return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
7278 struct cpuacct, css);
7279}
7280
7281/* return cpu accounting group to which this task belongs */
7282static inline struct cpuacct *task_ca(struct task_struct *tsk)
7283{
7284 return container_of(task_subsys_state(tsk, cpuacct_subsys_id),
7285 struct cpuacct, css);
7286}
7287
7288/* create a new cpu accounting group */
7289static struct cgroup_subsys_state *cpuacct_create(
7290 struct cgroup_subsys *ss, struct cgroup *cont)
7291{
7292 struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
7293
7294 if (!ca)
7295 return ERR_PTR(-ENOMEM);
7296
7297 ca->cpuusage = alloc_percpu(u64);
7298 if (!ca->cpuusage) {
7299 kfree(ca);
7300 return ERR_PTR(-ENOMEM);
7301 }
7302
7303 return &ca->css;
7304}
7305
7306/* destroy an existing cpu accounting group */
7307static void cpuacct_destroy(struct cgroup_subsys *ss,
7308 struct cgroup *cont)
7309{
7310 struct cpuacct *ca = cgroup_ca(cont);
7311
7312 free_percpu(ca->cpuusage);
7313 kfree(ca);
7314}
7315
7316/* return total cpu usage (in nanoseconds) of a group */
7317static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
7318{
7319 struct cpuacct *ca = cgroup_ca(cont);
7320 u64 totalcpuusage = 0;
7321 int i;
7322
7323 for_each_possible_cpu(i) {
7324 u64 *cpuusage = percpu_ptr(ca->cpuusage, i);
7325
7326 /*
7327 * Take rq->lock to make 64-bit addition safe on 32-bit
7328 * platforms.
7329 */
7330 spin_lock_irq(&cpu_rq(i)->lock);
7331 totalcpuusage += *cpuusage;
7332 spin_unlock_irq(&cpu_rq(i)->lock);
7333 }
7334
7335 return totalcpuusage;
7336}
7337
7338static struct cftype files[] = {
7339 {
7340 .name = "usage",
7341 .read_uint = cpuusage_read,
7342 },
7343};
7344
7345static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
7346{
7347 return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
7348}
7349
7350/*
7351 * charge this task's execution time to its accounting group.
7352 *
7353 * called with rq->lock held.
7354 */
7355static void cpuacct_charge(struct task_struct *tsk, u64 cputime)
7356{
7357 struct cpuacct *ca;
7358
7359 if (!cpuacct_subsys.active)
7360 return;
7361
7362 ca = task_ca(tsk);
7363 if (ca) {
7364 u64 *cpuusage = percpu_ptr(ca->cpuusage, task_cpu(tsk));
7365
7366 *cpuusage += cputime;
7367 }
7368}
7369
7370struct cgroup_subsys cpuacct_subsys = {
7371 .name = "cpuacct",
7372 .create = cpuacct_create,
7373 .destroy = cpuacct_destroy,
7374 .populate = cpuacct_populate,
7375 .subsys_id = cpuacct_subsys_id,
7376};
7377#endif /* CONFIG_CGROUP_CPUACCT */
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 2f16e15c022c..37bb265598db 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -351,6 +351,12 @@ static void update_curr(struct cfs_rq *cfs_rq)
351 351
352 __update_curr(cfs_rq, curr, delta_exec); 352 __update_curr(cfs_rq, curr, delta_exec);
353 curr->exec_start = now; 353 curr->exec_start = now;
354
355 if (entity_is_task(curr)) {
356 struct task_struct *curtask = task_of(curr);
357
358 cpuacct_charge(curtask, delta_exec);
359 }
354} 360}
355 361
356static inline void 362static inline void
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 8abd752a0ebd..ee9c8b6529e9 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -23,6 +23,7 @@ static void update_curr_rt(struct rq *rq)
23 23
24 curr->se.sum_exec_runtime += delta_exec; 24 curr->se.sum_exec_runtime += delta_exec;
25 curr->se.exec_start = rq->clock; 25 curr->se.exec_start = rq->clock;
26 cpuacct_charge(curr, delta_exec);
26} 27}
27 28
28static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup) 29static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)