Index: linux-2.6.19-rc2-mm1/kernel/sched.c =================================================================== --- linux-2.6.19-rc2-mm1.orig/kernel/sched.c 2006-10-20 15:13:42.000000000 -0500 +++ linux-2.6.19-rc2-mm1/kernel/sched.c 2006-10-20 15:44:17.466164185 -0500 @@ -2835,9 +2835,12 @@ static inline unsigned long cpu_offset(i } /* - * Called from a tasklet with interrupts enabled. + * Called from the migration threads with interrupts enabled. + * + * Returns the time in jiffies when we need to scan the queues + * next. */ -static void rebalance_tick(unsigned long dummy) +static unsigned long rebalance_tick() { int this_cpu = smp_processor_id(); struct rq *this_rq = cpu_rq(this_cpu); @@ -2845,6 +2848,7 @@ static void rebalance_tick(unsigned long unsigned long this_load, interval, j = cpu_offset(this_cpu); struct sched_domain *sd; int i, scale; + unsigned long next_balance = jiffies; /* * A queue is only truely idle if it is the idle queue and no task is runnable @@ -2892,12 +2896,12 @@ static void rebalance_tick(unsigned long idle = NOT_IDLE; } sd->last_balance += interval; + next_balance = max(next_balance, sd->last_balance + interval); } } + return next_balance; } -static DECLARE_TASKLET(rebalance, rebalance_tick, 0); - #else /* * on UP we do not need to balance between CPUs: @@ -3141,9 +3145,6 @@ void scheduler_tick(void) out_unlock: spin_unlock(&rq->lock); out: -#ifdef CONFIG_SMP - tasklet_schedule(&rebalance); -#endif } #ifdef CONFIG_SCHED_SMT @@ -5009,6 +5010,7 @@ static int migration_thread(void *data) { int cpu = (long)data; struct rq *rq; + unsigned long next_balance = jiffies + HZ / 2; rq = cpu_rq(cpu); BUG_ON(rq->migration_thread != current); @@ -5027,6 +5029,9 @@ static int migration_thread(void *data) goto wait_to_die; } + if (jiffies > next_balance) + next_balance = rebalance_tick(); + if (rq->active_balance) { active_load_balance(rq, cpu); rq->active_balance = 0; @@ -5036,7 +5041,7 @@ static int migration_thread(void *data) if (list_empty(head)) { spin_unlock_irq(&rq->lock); - schedule(); + schedule_timeout(max(next_balance - jiffies, 1)); set_current_state(TASK_INTERRUPTIBLE); continue; }