diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-24 04:11:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-24 04:11:23 -0400 |
commit | 416dfdcdb894432547ead4fcb9fa6a36b396059e (patch) | |
tree | 8033fdda07397a59c5fa98c88927040906ce6c1a /kernel/sched.c | |
parent | 56449f437add737a1e5e1cb7e00f63ac8ead1938 (diff) | |
parent | 091069740304c979f957ceacec39c461d0192158 (diff) |
Merge commit 'v2.6.30-rc3' into tracing/hw-branch-tracing
Conflicts:
arch/x86/kernel/ptrace.c
Merge reason: fix the conflict above, and also pick up the CONFIG_BROKEN
dependency change from upstream so that we can remove it
here.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 164 |
1 files changed, 149 insertions, 15 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index f91bc8141dc3..36322e8682c7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1418,10 +1418,22 @@ iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest, | |||
1418 | struct rq_iterator *iterator); | 1418 | struct rq_iterator *iterator); |
1419 | #endif | 1419 | #endif |
1420 | 1420 | ||
1421 | /* Time spent by the tasks of the cpu accounting group executing in ... */ | ||
1422 | enum cpuacct_stat_index { | ||
1423 | CPUACCT_STAT_USER, /* ... user mode */ | ||
1424 | CPUACCT_STAT_SYSTEM, /* ... kernel mode */ | ||
1425 | |||
1426 | CPUACCT_STAT_NSTATS, | ||
1427 | }; | ||
1428 | |||
1421 | #ifdef CONFIG_CGROUP_CPUACCT | 1429 | #ifdef CONFIG_CGROUP_CPUACCT |
1422 | static void cpuacct_charge(struct task_struct *tsk, u64 cputime); | 1430 | static void cpuacct_charge(struct task_struct *tsk, u64 cputime); |
1431 | static void cpuacct_update_stats(struct task_struct *tsk, | ||
1432 | enum cpuacct_stat_index idx, cputime_t val); | ||
1423 | #else | 1433 | #else |
1424 | static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} | 1434 | static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} |
1435 | static inline void cpuacct_update_stats(struct task_struct *tsk, | ||
1436 | enum cpuacct_stat_index idx, cputime_t val) {} | ||
1425 | #endif | 1437 | #endif |
1426 | 1438 | ||
1427 | static inline void inc_cpu_load(struct rq *rq, unsigned long load) | 1439 | static inline void inc_cpu_load(struct rq *rq, unsigned long load) |
@@ -4554,9 +4566,25 @@ DEFINE_PER_CPU(struct kernel_stat, kstat); | |||
4554 | EXPORT_PER_CPU_SYMBOL(kstat); | 4566 | EXPORT_PER_CPU_SYMBOL(kstat); |
4555 | 4567 | ||
4556 | /* | 4568 | /* |
4557 | * Return any ns on the sched_clock that have not yet been banked in | 4569 | * Return any ns on the sched_clock that have not yet been accounted in |
4558 | * @p in case that task is currently running. | 4570 | * @p in case that task is currently running. |
4571 | * | ||
4572 | * Called with task_rq_lock() held on @rq. | ||
4559 | */ | 4573 | */ |
4574 | static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) | ||
4575 | { | ||
4576 | u64 ns = 0; | ||
4577 | |||
4578 | if (task_current(rq, p)) { | ||
4579 | update_rq_clock(rq); | ||
4580 | ns = rq->clock - p->se.exec_start; | ||
4581 | if ((s64)ns < 0) | ||
4582 | ns = 0; | ||
4583 | } | ||
4584 | |||
4585 | return ns; | ||
4586 | } | ||
4587 | |||
4560 | unsigned long long task_delta_exec(struct task_struct *p) | 4588 | unsigned long long task_delta_exec(struct task_struct *p) |
4561 | { | 4589 | { |
4562 | unsigned long flags; | 4590 | unsigned long flags; |
@@ -4564,16 +4592,49 @@ unsigned long long task_delta_exec(struct task_struct *p) | |||
4564 | u64 ns = 0; | 4592 | u64 ns = 0; |
4565 | 4593 | ||
4566 | rq = task_rq_lock(p, &flags); | 4594 | rq = task_rq_lock(p, &flags); |
4595 | ns = do_task_delta_exec(p, rq); | ||
4596 | task_rq_unlock(rq, &flags); | ||
4567 | 4597 | ||
4568 | if (task_current(rq, p)) { | 4598 | return ns; |
4569 | u64 delta_exec; | 4599 | } |
4570 | 4600 | ||
4571 | update_rq_clock(rq); | 4601 | /* |
4572 | delta_exec = rq->clock - p->se.exec_start; | 4602 | * Return accounted runtime for the task. |
4573 | if ((s64)delta_exec > 0) | 4603 | * In case the task is currently running, return the runtime plus current's |
4574 | ns = delta_exec; | 4604 | * pending runtime that have not been accounted yet. |
4575 | } | 4605 | */ |
4606 | unsigned long long task_sched_runtime(struct task_struct *p) | ||
4607 | { | ||
4608 | unsigned long flags; | ||
4609 | struct rq *rq; | ||
4610 | u64 ns = 0; | ||
4611 | |||
4612 | rq = task_rq_lock(p, &flags); | ||
4613 | ns = p->se.sum_exec_runtime + do_task_delta_exec(p, rq); | ||
4614 | task_rq_unlock(rq, &flags); | ||
4615 | |||
4616 | return ns; | ||
4617 | } | ||
4618 | |||
4619 | /* | ||
4620 | * Return sum_exec_runtime for the thread group. | ||
4621 | * In case the task is currently running, return the sum plus current's | ||
4622 | * pending runtime that have not been accounted yet. | ||
4623 | * | ||
4624 | * Note that the thread group might have other running tasks as well, | ||
4625 | * so the return value not includes other pending runtime that other | ||
4626 | * running tasks might have. | ||
4627 | */ | ||
4628 | unsigned long long thread_group_sched_runtime(struct task_struct *p) | ||
4629 | { | ||
4630 | struct task_cputime totals; | ||
4631 | unsigned long flags; | ||
4632 | struct rq *rq; | ||
4633 | u64 ns; | ||
4576 | 4634 | ||
4635 | rq = task_rq_lock(p, &flags); | ||
4636 | thread_group_cputime(p, &totals); | ||
4637 | ns = totals.sum_exec_runtime + do_task_delta_exec(p, rq); | ||
4577 | task_rq_unlock(rq, &flags); | 4638 | task_rq_unlock(rq, &flags); |
4578 | 4639 | ||
4579 | return ns; | 4640 | return ns; |
@@ -4602,6 +4663,8 @@ void account_user_time(struct task_struct *p, cputime_t cputime, | |||
4602 | cpustat->nice = cputime64_add(cpustat->nice, tmp); | 4663 | cpustat->nice = cputime64_add(cpustat->nice, tmp); |
4603 | else | 4664 | else |
4604 | cpustat->user = cputime64_add(cpustat->user, tmp); | 4665 | cpustat->user = cputime64_add(cpustat->user, tmp); |
4666 | |||
4667 | cpuacct_update_stats(p, CPUACCT_STAT_USER, cputime); | ||
4605 | /* Account for user time used */ | 4668 | /* Account for user time used */ |
4606 | acct_update_integrals(p); | 4669 | acct_update_integrals(p); |
4607 | } | 4670 | } |
@@ -4663,6 +4726,8 @@ void account_system_time(struct task_struct *p, int hardirq_offset, | |||
4663 | else | 4726 | else |
4664 | cpustat->system = cputime64_add(cpustat->system, tmp); | 4727 | cpustat->system = cputime64_add(cpustat->system, tmp); |
4665 | 4728 | ||
4729 | cpuacct_update_stats(p, CPUACCT_STAT_SYSTEM, cputime); | ||
4730 | |||
4666 | /* Account for system time used */ | 4731 | /* Account for system time used */ |
4667 | acct_update_integrals(p); | 4732 | acct_update_integrals(p); |
4668 | } | 4733 | } |
@@ -4824,7 +4889,7 @@ void scheduler_tick(void) | |||
4824 | #endif | 4889 | #endif |
4825 | } | 4890 | } |
4826 | 4891 | ||
4827 | unsigned long get_parent_ip(unsigned long addr) | 4892 | notrace unsigned long get_parent_ip(unsigned long addr) |
4828 | { | 4893 | { |
4829 | if (in_lock_functions(addr)) { | 4894 | if (in_lock_functions(addr)) { |
4830 | addr = CALLER_ADDR2; | 4895 | addr = CALLER_ADDR2; |
@@ -7345,7 +7410,12 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, | |||
7345 | cpumask_or(groupmask, groupmask, sched_group_cpus(group)); | 7410 | cpumask_or(groupmask, groupmask, sched_group_cpus(group)); |
7346 | 7411 | ||
7347 | cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group)); | 7412 | cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group)); |
7413 | |||
7348 | printk(KERN_CONT " %s", str); | 7414 | printk(KERN_CONT " %s", str); |
7415 | if (group->__cpu_power != SCHED_LOAD_SCALE) { | ||
7416 | printk(KERN_CONT " (__cpu_power = %d)", | ||
7417 | group->__cpu_power); | ||
7418 | } | ||
7349 | 7419 | ||
7350 | group = group->next; | 7420 | group = group->next; |
7351 | } while (group != sd->groups); | 7421 | } while (group != sd->groups); |
@@ -9968,6 +10038,7 @@ struct cpuacct { | |||
9968 | struct cgroup_subsys_state css; | 10038 | struct cgroup_subsys_state css; |
9969 | /* cpuusage holds pointer to a u64-type object on every cpu */ | 10039 | /* cpuusage holds pointer to a u64-type object on every cpu */ |
9970 | u64 *cpuusage; | 10040 | u64 *cpuusage; |
10041 | struct percpu_counter cpustat[CPUACCT_STAT_NSTATS]; | ||
9971 | struct cpuacct *parent; | 10042 | struct cpuacct *parent; |
9972 | }; | 10043 | }; |
9973 | 10044 | ||
@@ -9992,20 +10063,32 @@ static struct cgroup_subsys_state *cpuacct_create( | |||
9992 | struct cgroup_subsys *ss, struct cgroup *cgrp) | 10063 | struct cgroup_subsys *ss, struct cgroup *cgrp) |
9993 | { | 10064 | { |
9994 | struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL); | 10065 | struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL); |
10066 | int i; | ||
9995 | 10067 | ||
9996 | if (!ca) | 10068 | if (!ca) |
9997 | return ERR_PTR(-ENOMEM); | 10069 | goto out; |
9998 | 10070 | ||
9999 | ca->cpuusage = alloc_percpu(u64); | 10071 | ca->cpuusage = alloc_percpu(u64); |
10000 | if (!ca->cpuusage) { | 10072 | if (!ca->cpuusage) |
10001 | kfree(ca); | 10073 | goto out_free_ca; |
10002 | return ERR_PTR(-ENOMEM); | 10074 | |
10003 | } | 10075 | for (i = 0; i < CPUACCT_STAT_NSTATS; i++) |
10076 | if (percpu_counter_init(&ca->cpustat[i], 0)) | ||
10077 | goto out_free_counters; | ||
10004 | 10078 | ||
10005 | if (cgrp->parent) | 10079 | if (cgrp->parent) |
10006 | ca->parent = cgroup_ca(cgrp->parent); | 10080 | ca->parent = cgroup_ca(cgrp->parent); |
10007 | 10081 | ||
10008 | return &ca->css; | 10082 | return &ca->css; |
10083 | |||
10084 | out_free_counters: | ||
10085 | while (--i >= 0) | ||
10086 | percpu_counter_destroy(&ca->cpustat[i]); | ||
10087 | free_percpu(ca->cpuusage); | ||
10088 | out_free_ca: | ||
10089 | kfree(ca); | ||
10090 | out: | ||
10091 | return ERR_PTR(-ENOMEM); | ||
10009 | } | 10092 | } |
10010 | 10093 | ||
10011 | /* destroy an existing cpu accounting group */ | 10094 | /* destroy an existing cpu accounting group */ |
@@ -10013,7 +10096,10 @@ static void | |||
10013 | cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp) | 10096 | cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp) |
10014 | { | 10097 | { |
10015 | struct cpuacct *ca = cgroup_ca(cgrp); | 10098 | struct cpuacct *ca = cgroup_ca(cgrp); |
10099 | int i; | ||
10016 | 10100 | ||
10101 | for (i = 0; i < CPUACCT_STAT_NSTATS; i++) | ||
10102 | percpu_counter_destroy(&ca->cpustat[i]); | ||
10017 | free_percpu(ca->cpuusage); | 10103 | free_percpu(ca->cpuusage); |
10018 | kfree(ca); | 10104 | kfree(ca); |
10019 | } | 10105 | } |
@@ -10100,6 +10186,25 @@ static int cpuacct_percpu_seq_read(struct cgroup *cgroup, struct cftype *cft, | |||
10100 | return 0; | 10186 | return 0; |
10101 | } | 10187 | } |
10102 | 10188 | ||
10189 | static const char *cpuacct_stat_desc[] = { | ||
10190 | [CPUACCT_STAT_USER] = "user", | ||
10191 | [CPUACCT_STAT_SYSTEM] = "system", | ||
10192 | }; | ||
10193 | |||
10194 | static int cpuacct_stats_show(struct cgroup *cgrp, struct cftype *cft, | ||
10195 | struct cgroup_map_cb *cb) | ||
10196 | { | ||
10197 | struct cpuacct *ca = cgroup_ca(cgrp); | ||
10198 | int i; | ||
10199 | |||
10200 | for (i = 0; i < CPUACCT_STAT_NSTATS; i++) { | ||
10201 | s64 val = percpu_counter_read(&ca->cpustat[i]); | ||
10202 | val = cputime64_to_clock_t(val); | ||
10203 | cb->fill(cb, cpuacct_stat_desc[i], val); | ||
10204 | } | ||
10205 | return 0; | ||
10206 | } | ||
10207 | |||
10103 | static struct cftype files[] = { | 10208 | static struct cftype files[] = { |
10104 | { | 10209 | { |
10105 | .name = "usage", | 10210 | .name = "usage", |
@@ -10110,7 +10215,10 @@ static struct cftype files[] = { | |||
10110 | .name = "usage_percpu", | 10215 | .name = "usage_percpu", |
10111 | .read_seq_string = cpuacct_percpu_seq_read, | 10216 | .read_seq_string = cpuacct_percpu_seq_read, |
10112 | }, | 10217 | }, |
10113 | 10218 | { | |
10219 | .name = "stat", | ||
10220 | .read_map = cpuacct_stats_show, | ||
10221 | }, | ||
10114 | }; | 10222 | }; |
10115 | 10223 | ||
10116 | static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp) | 10224 | static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp) |
@@ -10132,12 +10240,38 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime) | |||
10132 | return; | 10240 | return; |
10133 | 10241 | ||
10134 | cpu = task_cpu(tsk); | 10242 | cpu = task_cpu(tsk); |
10243 | |||
10244 | rcu_read_lock(); | ||
10245 | |||
10135 | ca = task_ca(tsk); | 10246 | ca = task_ca(tsk); |
10136 | 10247 | ||
10137 | for (; ca; ca = ca->parent) { | 10248 | for (; ca; ca = ca->parent) { |
10138 | u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); | 10249 | u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); |
10139 | *cpuusage += cputime; | 10250 | *cpuusage += cputime; |
10140 | } | 10251 | } |
10252 | |||
10253 | rcu_read_unlock(); | ||
10254 | } | ||
10255 | |||
10256 | /* | ||
10257 | * Charge the system/user time to the task's accounting group. | ||
10258 | */ | ||
10259 | static void cpuacct_update_stats(struct task_struct *tsk, | ||
10260 | enum cpuacct_stat_index idx, cputime_t val) | ||
10261 | { | ||
10262 | struct cpuacct *ca; | ||
10263 | |||
10264 | if (unlikely(!cpuacct_subsys.active)) | ||
10265 | return; | ||
10266 | |||
10267 | rcu_read_lock(); | ||
10268 | ca = task_ca(tsk); | ||
10269 | |||
10270 | do { | ||
10271 | percpu_counter_add(&ca->cpustat[idx], val); | ||
10272 | ca = ca->parent; | ||
10273 | } while (ca); | ||
10274 | rcu_read_unlock(); | ||
10141 | } | 10275 | } |
10142 | 10276 | ||
10143 | struct cgroup_subsys cpuacct_subsys = { | 10277 | struct cgroup_subsys cpuacct_subsys = { |