--- linux-2.6.0-test11-batch-4/kernel/sched.c 2003-12-16 00:34:51.115494522 +1100 +++ linux-2.6.0-test11-ck2/kernel/sched.c 2003-12-16 00:09:08.597055914 +1100 @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef CONFIG_NUMA #define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu)) @@ -357,6 +358,59 @@ static inline void enqueue_task(struct t p->array = array; } +/* idle balancing infrastructure */ +struct idle_cpus_list { + spinlock_t lock; + struct list_head list; +}; + +struct idle_cpu { + struct list_head list; + int cpuid; +}; + +DEFINE_PER_CPU(struct idle_cpu, cpu_is_idle); +/* global idle cpu list */ +struct idle_cpus_list idle_list; + +static void set_cpu_idle(struct idle_cpus_list* ic, int cpu) +{ + spin_lock(&ic->lock); + + list_add(&per_cpu(cpu_is_idle, cpu).list, &ic->list); + + spin_unlock(&ic->lock); +} + +static inline void set_cpu_not_idle(struct idle_cpus_list* ic, int cpu) +{ + spin_lock(&ic->lock); + + list_del(&per_cpu(cpu_is_idle, cpu).list); + + spin_unlock(&ic->lock); +} + +/* return the ID of the idlest cpu */ +/* -1 if no CPU is idle */ +static int idlest_cpu(struct idle_cpus_list* ic) +{ + struct idle_cpu* cpu; + + spin_lock(&ic->lock); + + if (list_empty(&ic->list)) { + spin_unlock(&ic->lock); + return NR_CPUS + 1; + } + + cpu = list_entry(ic->list.next, struct idle_cpu, list); + + spin_unlock(&ic->lock); + + return cpu->cpuid; +} + /* * effective_prio - return the priority that is based on the static * priority but is modified by bonuses/penalties. @@ -389,6 +443,8 @@ static int effective_prio(task_t *p) return prio; } +static inline void resched_task(task_t *p); + /* * __activate_task - move a task to the runqueue. */ @@ -401,6 +457,13 @@ static inline void __activate_task(task_ enqueue_task(p, rq->active); nr_running_inc(rq); +#ifdef CONFIG_SMP + if (rq->nr_running > 1){ + unsigned long cpu = idlest_cpu(&idle_list); + if (cpu <= NR_CPUS) + resched_task(cpu_rq(cpu)->idle); + } +#endif } static void recalc_task_prio(task_t *p, unsigned long long now) @@ -1441,7 +1504,6 @@ void scheduler_tick(int user_ticks, int resched_task(p); goto out; } - rebalance_tick(rq, 1); return; } @@ -1706,6 +1768,12 @@ switch_tasks: rq->nr_switches++; rq->curr = next; + if (unlikely(next == rq->idle)) + set_cpu_idle(&idle_list, rq->cpu); + else + if (prev == rq->idle) + set_cpu_not_idle(&idle_list, rq->cpu); + prepare_arch_switch(rq, next); prev = context_switch(rq, prev, next); barrier(); @@ -2925,6 +2993,24 @@ __init static void init_kstat(void) { register_cpu_notifier(&kstat_nb); } +static void init_idle_cpus_list(struct idle_cpus_list* ic) +{ + int i; + + memset(ic, 0, sizeof(*ic)); + + spin_lock_init(&ic->lock); + + /* no CPU is currently idle */ + INIT_LIST_HEAD(&ic->list); + + /* initialize the per cpu list of idle_cpu structs */ + for (i = 0; i < NR_CPUS; ++i) { + INIT_LIST_HEAD(&per_cpu(cpu_is_idle, i).list); + per_cpu(cpu_is_idle, i).cpuid = i; + } +} + void __init sched_init(void) { runqueue_t *rq; @@ -2932,6 +3018,8 @@ void __init sched_init(void) /* Init the kstat counters */ init_kstat(); + init_idle_cpus_list(&idle_list); + for (i = 0; i < NR_CPUS; i++) { prio_array_t *array;