diff options
author | Johannes Weiner <hannes@saeurebad.de> | 2008-07-24 08:28:05 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 21:47:20 +0400 |
commit | d747fa4bcebcf3696607b86a6b0dafa644be0676 (patch) | |
tree | ca6efae6f21cc357b75ecf2c91344d79ac465645 /mm/bootmem.c | |
parent | 5f2809e69c7128f86316048221cf45146f69a4a0 (diff) | |
download | linux-d747fa4bcebcf3696607b86a6b0dafa644be0676.tar.xz |
bootmem: free/reserve helpers
Factor out the common operation of marking a range on the bitmap.
[akpm@linux-foundation.org: fix various warnings]
Signed-off-by: Johannes Weiner <hannes@saeurebad.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Andi Kleen <andi@firstfloor.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r-- | mm/bootmem.c | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 94ea612deccf..9d03ff651359 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -225,6 +225,44 @@ unsigned long __init free_all_bootmem(void) return free_all_bootmem_core(NODE_DATA(0)->bdata); } +static void __init __free(bootmem_data_t *bdata, + unsigned long sidx, unsigned long eidx) +{ + unsigned long idx; + + bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data, + sidx + PFN_DOWN(bdata->node_boot_start), + eidx + PFN_DOWN(bdata->node_boot_start)); + + for (idx = sidx; idx < eidx; idx++) + if (!test_and_clear_bit(idx, bdata->node_bootmem_map)) + BUG(); +} + +static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx, + unsigned long eidx, int flags) +{ + unsigned long idx; + int exclusive = flags & BOOTMEM_EXCLUSIVE; + + bdebug("nid=%td start=%lx end=%lx flags=%x\n", + bdata - bootmem_node_data, + sidx + PFN_DOWN(bdata->node_boot_start), + eidx + PFN_DOWN(bdata->node_boot_start), + flags); + + for (idx = sidx; idx < eidx; idx++) + if (test_and_set_bit(idx, bdata->node_bootmem_map)) { + if (exclusive) { + __free(bdata, sidx, idx); + return -EBUSY; + } + bdebug("silent double reserve of PFN %lx\n", + idx + PFN_DOWN(bdata->node_boot_start)); + } + return 0; +} + static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long size) { @@ -258,14 +296,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); - bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data, - sidx + PFN_DOWN(bdata->node_boot_start), - eidx + PFN_DOWN(bdata->node_boot_start)); - - for (i = sidx; i < eidx; i++) { - if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map))) - BUG(); - } + __free(bdata, sidx, eidx); } /** @@ -367,16 +398,7 @@ static void __init reserve_bootmem_core(bootmem_data_t *bdata, if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start)) eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start); - bdebug("nid=%td start=%lx end=%lx flags=%x\n", - bdata - bootmem_node_data, - sidx + PFN_DOWN(bdata->node_boot_start), - eidx + PFN_DOWN(bdata->node_boot_start), - flags); - - for (i = sidx; i < eidx; i++) - if (test_and_set_bit(i, bdata->node_bootmem_map)) - bdebug("hm, page %lx reserved twice.\n", - PFN_DOWN(bdata->node_boot_start) + i); + return __reserve(bdata, sidx, eidx, flags); } /** @@ -511,10 +533,9 @@ find_block: /* * Reserve the area now: */ - for (i = PFN_DOWN(start_off) + merge; - i < PFN_UP(end_off); i++) - if (test_and_set_bit(i, bdata->node_bootmem_map)) - BUG(); + if (__reserve(bdata, PFN_DOWN(start_off) + merge, + PFN_UP(end_off), BOOTMEM_EXCLUSIVE)) + BUG(); region = phys_to_virt(bdata->node_boot_start + start_off); memset(region, 0, size); |