diff -urNp linux-2.5.55-ms-ilb/include/linux/sched.h linux-2.5.55-ms-ilb-nb/include/linux/sched.h --- linux-2.5.55-ms-ilb/include/linux/sched.h 2003-01-12 18:03:07.000000000 +0100 +++ linux-2.5.55-ms-ilb-nb/include/linux/sched.h 2003-01-11 17:19:49.000000000 +0100 @@ -450,11 +450,13 @@ extern void node_nr_running_init(void); rq->nr_running++ #define nr_running_dec(rq) atomic_dec(rq->node_ptr); \ rq->nr_running-- +#define decl_numa_int(ctr) int ctr #else #define sched_balance_exec() {} #define node_nr_running_init() {} #define nr_running_inc(rq) rq->nr_running++ #define nr_running_dec(rq) rq->nr_running-- +#define decl_numa_int(ctr) {} #endif extern void set_user_nice(task_t *p, long nice); diff -urNp linux-2.5.55-ms-ilb/kernel/sched.c linux-2.5.55-ms-ilb-nb/kernel/sched.c --- linux-2.5.55-ms-ilb/kernel/sched.c 2003-01-12 18:03:07.000000000 +0100 +++ linux-2.5.55-ms-ilb-nb/kernel/sched.c 2003-01-12 18:12:27.000000000 +0100 @@ -154,6 +154,7 @@ struct runqueue { prio_array_t *active, *expired, arrays[2]; int prev_nr_running[NR_CPUS]; atomic_t * node_ptr; + decl_numa_int(lb_cntr); task_t *migration_thread; struct list_head migration_queue; @@ -703,6 +704,23 @@ void sched_balance_exec(void) sched_migrate_task(current, new_cpu); } } + +static int find_busiest_node(int this_node) +{ + int i, node = this_node, load, this_load, maxload; + + this_load = maxload = atomic_read(&node_nr_running[this_node]); + for (i = 0; i < numnodes; i++) { + if (i == this_node) + continue; + load = atomic_read(&node_nr_running[i]); + if (load > maxload && (4*load > ((5*4*this_load)/4))) { + maxload = load; + node = i; + } + } + return node; +} #endif /* CONFIG_NUMA */ #if CONFIG_SMP @@ -816,6 +834,16 @@ out: static inline runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, int idle, int *imbalance) { unsigned long cpumask = __node_to_cpu_mask(__cpu_to_node(this_cpu)); +#if CONFIG_NUMA + int node; +# define INTERNODE_LB 10 + + /* rebalance across nodes only every INTERNODE_LB call */ + if (!(++(this_rq->lb_cntr) % INTERNODE_LB)) { + node = find_busiest_node(__cpu_to_node(this_cpu)); + cpumask |= __node_to_cpu_mask(node); + } +#endif return find_busiest_in_mask(this_rq, this_cpu, idle, imbalance, cpumask); }