--- mm/cpu_alloc.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) Index: linux-2.6/mm/cpu_alloc.c =================================================================== --- linux-2.6.orig/mm/cpu_alloc.c 2007-11-03 19:45:26.576728550 -0700 +++ linux-2.6/mm/cpu_alloc.c 2007-11-03 19:48:36.071727479 -0700 @@ -231,6 +231,7 @@ out: u8 cpu_area[NR_CPUS * BLOCK_SIZE]; static DECLARE_BITMAP(cpu_alloc_map, UNITS_PER_BLOCK); +#define cpu_alloc_map_order CONFIG_CPU_AREA_ORDER #define CPU_AREA_BASE (unsigned long)cpu_area static int units_free = UNITS_PER_BLOCK; #define units_total UNITS_PER_BLOCK @@ -241,8 +242,7 @@ static inline int expand_cpu_area(gfp_t } #endif -static int end_full_alloc; /* 0 .. end_full_alloc are all allocated */ -static int begin_all_free; /* begin_all_free .. units_total are all free */ +static int first_free; /* First known free unit */ /* * How many units are needed for an object of a given size @@ -283,49 +283,39 @@ void *cpu_alloc(unsigned long size, gfp_ { unsigned long start; int units = size_to_units(size); - unsigned end; void *ptr; int first; + unsigned long map_size; BUG_ON(gfpflags & ~(GFP_RECLAIM_MASK | __GFP_ZERO)); spin_lock(&cpu_alloc_map_lock); restart: + map_size = PAGE_SIZE << cpu_alloc_map_order; first = 1; - start = end_full_alloc; + start = first_free; for ( ; ; ) { - while (start < units_total && - test_bit(start, cpu_alloc_map)) - start++; - + start = find_next_zero_bit(cpu_alloc_map, map_size, start); if (first) - end_full_alloc = start; + first_free = start; - if (start == units_total) { + if (start >= units_total) { if (!expand_cpu_area(gfpflags)) goto restart; spin_unlock(&cpu_alloc_map_lock); return NULL; } - /* Ok we found a free cell */ - end = start + 1; /* Alignment okay ? */ - if (start % (align / UNIT_SIZE) == 0) { - /* See if we can find enough units for the object */ - while (end < units_total && end - start < units && - !test_bit(end, cpu_alloc_map)) - end++; - if (end - start == units) + if (start % (align / UNIT_SIZE) == 0 && + find_next_bit(cpu_alloc_map, map_size, start + 1) + >= start + units); break; - } - start = end; + start++; first = 0; }; if (first) - end_full_alloc = end; - if (end > begin_all_free) - begin_all_free = end; + first_free = start + units; set_map(start, units); units_free -= units; @@ -362,8 +352,8 @@ void cpu_free(void *pcpu, unsigned long clear_map(index, units); units_free += units; __count_vm_events(CPU_BYTES, -units * UNIT_SIZE); - if (start < end_full_alloc) - end_full_alloc = start; + if (start < first_free) + first_free = start; spin_unlock(&cpu_alloc_map_lock); } EXPORT_SYMBOL(cpu_free);