--- mm/cpu_alloc.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) Index: linux-2.6/mm/cpu_alloc.c =================================================================== --- linux-2.6.orig/mm/cpu_alloc.c 2007-11-13 16:15:15.300170721 -0800 +++ linux-2.6/mm/cpu_alloc.c 2007-11-13 16:35:03.299036640 -0800 @@ -68,7 +68,6 @@ static DEFINE_SPINLOCK(cpu_alloc_map_loc static unsigned long *cpu_alloc_map = NULL; static int cpu_alloc_map_order = -1; /* Size of the bitmap in page order */ static unsigned long active_blocks; /* Number of block allocated on each cpu */ -static unsigned long units_free; /* Number of available units */ static unsigned long units_total; /* Total units that are managed */ static unsigned long units_reserved; /* Units reserved by boot allocations */ /* @@ -198,6 +197,7 @@ static int expand_cpu_area(gfp_t flags) unsigned long *new_map = NULL; void *start; + printk("expand_cpu_area\n"); if (active_blocks == MAX_BLOCKS) goto out; @@ -221,6 +221,7 @@ static int expand_cpu_area(gfp_t flags) if (err) { spin_lock(&cpu_alloc_map_lock); + printk("populate failed with error=%d\n", err); goto out; } } @@ -262,7 +263,6 @@ static int expand_cpu_area(gfp_t flags) active_blocks++; units_total += UNITS_PER_BLOCK; - units_free += UNITS_PER_BLOCK; err = 0; out: return err; @@ -274,8 +274,17 @@ void * __init boot_cpu_alloc(unsigned lo unsigned long units = size_to_units(size); printk("boot_cpu_alloc(%lu) reserved=%lu total=%lu\n", size, units_reserved, units_total); - while (units_reserved + units > units_total) + while (units_reserved + units > units_total) { + unsigned long flags; + + /* + * Locking only for compatibilities sake because expand_cpu_area + * unlocks and locks ! + */ + spin_lock_irqsave(&cpu_alloc_map_lock, flags); expand_cpu_area(BOOT_ALLOC); + spin_unlock_irqrestore(&cpu_alloc_map_lock, flags); + } units_reserved += units; return cpu_area + x * UNIT_SIZE; } @@ -291,7 +300,6 @@ void * __init boot_cpu_alloc(unsigned lo static u8 cpu_area[NR_CPUS * ALLOC_SIZE]; static DECLARE_BITMAP(cpu_alloc_map, UNITS_PER_BLOCK); -static int units_free = UNITS_PER_BLOCK; #define cpu_alloc_map_order CONFIG_CPU_AREA_ORDER #define units_total UNITS_PER_BLOCK @@ -349,11 +357,13 @@ void *cpu_alloc(unsigned long size, gfp_ unsigned long map_size; unsigned long flags; + printk("cpu_alloc(%d,%lx,%d)\n", size, gfpflags, align); BUG_ON(gfpflags & ~(GFP_RECLAIM_MASK | __GFP_ZERO)); spin_lock_irqsave(&cpu_alloc_map_lock, flags); restart: + printk("restart point cpu_alloc_map_order=%d first_free =%d\n", cpu_alloc_map_order, first_free); map_size = PAGE_SIZE << cpu_alloc_map_order; first = 1; start = first_free; @@ -364,7 +374,7 @@ restart: if (first) first_free = start; - if (start >= units_total) { + if (start >= units_total - units_reserved) { if (expand_cpu_area(gfpflags)) goto out_of_memory; goto restart; @@ -374,7 +384,7 @@ restart: * Check alignment and that there is enough space after * the starting unit. */ - if (start % (align / UNIT_SIZE) == 0 && + if ((start + units_reserved) % (align / UNIT_SIZE) == 0 && find_next_bit(cpu_alloc_map, map_size, start + 1) >= start + units) break; @@ -385,13 +395,12 @@ restart: if (first) first_free = start + units; - while (start + units > units_total) { + while (start + units > units_total - units_reserved) { if (expand_cpu_area(gfpflags)) goto out_of_memory; } set_map(start, units); - units_free -= units; __count_vm_events(CPU_BYTES, units * UNIT_SIZE); spin_unlock_irqrestore(&cpu_alloc_map_lock, flags); @@ -427,12 +436,11 @@ void cpu_free(void *start, unsigned long BUG_ON(p < (cpu_area + units_reserved * UNIT_SIZE)); index = (p - cpu_area) / UNIT_SIZE - units_reserved; BUG_ON(!test_bit(index, cpu_alloc_map) || - index >= units_total); + index >= units_total - units_reserved); spin_lock_irqsave(&cpu_alloc_map_lock, flags); clear_map(index, units); - units_free += units; __count_vm_events(CPU_BYTES, -units * UNIT_SIZE); if (index < first_free) first_free = index;