From: John Hawkes As recently as 2.6.15-rc5-mm1 the combination of "migration cost matrix" calculations and "dynamic sched domains" is broken. This patch fixes the basic bug, even though I still have larger problems with the "migration cost matrix" concept as implemented. The essence of the bug is that the code and data in the CPU Scheduler that perform the cost calculation are declared as "__initdata" or "__init" or "__devinit", even though a runtime declaration of a cpu-exclusive cpuset will invoke build_sched_domains() to rebuilt the sched domains, and that calls the now-released calibrate_migration_costs(), et al. The attached patch changes the declarations of the code and data to make them persistent. To review, to create a cpu-exclusive cpuset, do something like this: cd /dev/cpuset mkdir cpu0 echo 0 > cpu0/cpus echo 0 > cpu0/mems echo 1 > cpu0/cpu_exclusive Signed-off-by: John Hawkes Cc: Ingo Molnar Signed-off-by: Andrew Morton --- kernel/sched.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff -puN kernel/sched.c~scheduler-cache-hot-autodetect-section-fixes kernel/sched.c --- 25/kernel/sched.c~scheduler-cache-hot-autodetect-section-fixes Mon Dec 12 15:44:57 2005 +++ 25-akpm/kernel/sched.c Mon Dec 12 15:44:57 2005 @@ -5167,7 +5167,7 @@ __setup ("migration_cost=", migration_co #define MIGRATION_FACTOR_SCALE 128 -static __initdata unsigned int migration_factor = MIGRATION_FACTOR_SCALE; +static unsigned int migration_factor = MIGRATION_FACTOR_SCALE; static int __init setup_migration_factor(char *str) { @@ -5182,7 +5182,7 @@ __setup("migration_factor=", setup_migra * Estimated distance of two CPUs, measured via the number of domains * we have to pass for the two CPUs to be in the same span: */ -__devinit static unsigned long domain_distance(int cpu1, int cpu2) +static unsigned long domain_distance(int cpu1, int cpu2) { unsigned long distance = 0; struct sched_domain *sd; @@ -5201,7 +5201,7 @@ __devinit static unsigned long domain_di return distance; } -static __initdata unsigned int migration_debug; +static unsigned int migration_debug; static int __init setup_migration_debug(char *str) { @@ -5217,7 +5217,7 @@ __setup("migration_debug=", setup_migrat * bootup. Gets used in the domain-setup code (i.e. during SMP * bootup). */ -__initdata unsigned int max_cache_size; +unsigned int max_cache_size; static int __init setup_max_cache_size(char *str) { @@ -5232,7 +5232,7 @@ __setup("max_cache_size=", setup_max_cac * is the operation that is timed, so we try to generate unpredictable * cachemisses that still end up filling the L2 cache: */ -__init static void touch_cache(void *__cache, unsigned long __size) +static void touch_cache(void *__cache, unsigned long __size) { unsigned long size = __size/sizeof(long), chunk1 = size/3, chunk2 = 2*size/3; @@ -5254,8 +5254,8 @@ __init static void touch_cache(void *__c /* * Measure the cache-cost of one task migration. Returns in units of nsec. */ -__init static unsigned long long measure_one(void *cache, unsigned long size, - int source, int target) +static unsigned long long measure_one(void *cache, unsigned long size, + int source, int target) { cpumask_t mask, saved_mask; unsigned long long t0, t1, t2, t3, cost; @@ -5321,7 +5321,7 @@ __init static unsigned long long measure * Architectures can prime the upper limit of the search range via * max_cache_size, otherwise the search range defaults to 20MB...64K. */ -__init static unsigned long long +static unsigned long long measure_cost(int cpu1, int cpu2, void *cache, unsigned int size) { unsigned long long cost1, cost2; @@ -5373,7 +5373,7 @@ measure_cost(int cpu1, int cpu2, void *c return cost1 - cost2; } -__devinit static unsigned long long measure_migration_cost(int cpu1, int cpu2) +static unsigned long long measure_migration_cost(int cpu1, int cpu2) { unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0; unsigned int max_size, size, size_found = 0; @@ -5478,7 +5478,7 @@ __devinit static unsigned long long meas return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE; } -void __devinit calibrate_migration_costs(void) +void calibrate_migration_costs(void) { int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id(); struct sched_domain *sd; _