diff options
author | Siddha, Suresh B <suresh.b.siddha@intel.com> | 2007-05-08 03:32:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:17 -0400 |
commit | bdecea3a9282d529b54954f3f1e59877629baba1 (patch) | |
tree | c7330b1cec4b4a9bf18657bc99100276343efc38 /kernel/sched.c | |
parent | 2bd7e20e0d24325b0799544bc8105cc57cc8e2aa (diff) |
sched: fix idle load balancing in softirqd context
Periodic load balancing in recent kernels happen in the softirq. In
certain -rt configurations, these softirqs are handled in softirqd context.
And hence the check for idle processor was always returning busy (as
nr_running > 1).
This patch captures the idle information at the tick and passes this info
to softirq context through an element 'idle_at_tick' in rq.
[kernel@kolivas.org: Fix reverse idle at tick logic]
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 5530ed211f72..ba053d88c8c6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -223,6 +223,7 @@ struct rq { | |||
223 | unsigned long raw_weighted_load; | 223 | unsigned long raw_weighted_load; |
224 | #ifdef CONFIG_SMP | 224 | #ifdef CONFIG_SMP |
225 | unsigned long cpu_load[3]; | 225 | unsigned long cpu_load[3]; |
226 | unsigned char idle_at_tick; | ||
226 | #endif | 227 | #endif |
227 | unsigned long long nr_switches; | 228 | unsigned long long nr_switches; |
228 | 229 | ||
@@ -2943,12 +2944,7 @@ static void run_rebalance_domains(struct softirq_action *h) | |||
2943 | struct rq *this_rq = cpu_rq(this_cpu); | 2944 | struct rq *this_rq = cpu_rq(this_cpu); |
2944 | unsigned long interval; | 2945 | unsigned long interval; |
2945 | struct sched_domain *sd; | 2946 | struct sched_domain *sd; |
2946 | /* | 2947 | enum idle_type idle = this_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE; |
2947 | * We are idle if there are no processes running. This | ||
2948 | * is valid even if we are the idle process (SMT). | ||
2949 | */ | ||
2950 | enum idle_type idle = !this_rq->nr_running ? | ||
2951 | SCHED_IDLE : NOT_IDLE; | ||
2952 | /* Earliest time when we have to call run_rebalance_domains again */ | 2948 | /* Earliest time when we have to call run_rebalance_domains again */ |
2953 | unsigned long next_balance = jiffies + 60*HZ; | 2949 | unsigned long next_balance = jiffies + 60*HZ; |
2954 | 2950 | ||
@@ -3218,14 +3214,16 @@ void scheduler_tick(void) | |||
3218 | unsigned long long now = sched_clock(); | 3214 | unsigned long long now = sched_clock(); |
3219 | struct task_struct *p = current; | 3215 | struct task_struct *p = current; |
3220 | int cpu = smp_processor_id(); | 3216 | int cpu = smp_processor_id(); |
3217 | int idle_at_tick = idle_cpu(cpu); | ||
3221 | struct rq *rq = cpu_rq(cpu); | 3218 | struct rq *rq = cpu_rq(cpu); |
3222 | 3219 | ||
3223 | update_cpu_clock(p, rq, now); | 3220 | update_cpu_clock(p, rq, now); |
3224 | 3221 | ||
3225 | if (p != rq->idle) | 3222 | if (!idle_at_tick) |
3226 | task_running_tick(rq, p); | 3223 | task_running_tick(rq, p); |
3227 | #ifdef CONFIG_SMP | 3224 | #ifdef CONFIG_SMP |
3228 | update_load(rq); | 3225 | update_load(rq); |
3226 | rq->idle_at_tick = idle_at_tick; | ||
3229 | if (time_after_eq(jiffies, rq->next_balance)) | 3227 | if (time_after_eq(jiffies, rq->next_balance)) |
3230 | raise_softirq(SCHED_SOFTIRQ); | 3228 | raise_softirq(SCHED_SOFTIRQ); |
3231 | #endif | 3229 | #endif |