From 73a72c42e2be61a6ebd778343b345de3cc65ed00 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 10 Mar 2010 18:36:44 +0000 Subject: [PATCH] Added get_free_address_range() to get a free range in a given range array. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35801 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/boot/addr_range.h | 2 ++ src/system/boot/loader/kernel_args.cpp | 34 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/headers/private/kernel/boot/addr_range.h b/headers/private/kernel/boot/addr_range.h index 201fb9fcc3..5367fde6a3 100644 --- a/headers/private/kernel/boot/addr_range.h +++ b/headers/private/kernel/boot/addr_range.h @@ -23,6 +23,8 @@ status_t insert_address_range(addr_range *ranges, uint32 *_numRanges, uint32 max addr_t start, uint32 size); status_t remove_addr_range(addr_range *ranges, uint32 *_numRanges, uint32 maxRanges, addr_t start, uint32 size); +bool get_free_address_range(addr_range *ranges, uint32 numRanges, addr_t base, + size_t size, addr_t *_rangeBase); status_t insert_physical_memory_range(addr_t start, uint32 size); status_t insert_physical_allocated_range(addr_t start, uint32 size); diff --git a/src/system/boot/loader/kernel_args.cpp b/src/system/boot/loader/kernel_args.cpp index 96ec8125a8..f66014e0a2 100644 --- a/src/system/boot/loader/kernel_args.cpp +++ b/src/system/boot/loader/kernel_args.cpp @@ -180,6 +180,40 @@ remove_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, } +bool +get_free_address_range(addr_range *ranges, uint32 numRanges, addr_t base, + size_t size, addr_t *_rangeBase) +{ + addr_t end = base + size - 1; + if (end < base) + return false; + + // Note: We don't assume that the ranges are sorted, so we can't do this + // in a simple loop. Instead we restart the loop whenever our range + // intersects with an existing one. + + for (uint32 i = 0; i < numRanges;) { + addr_t rangeStart = ranges[i].start; + addr_t rangeEnd = ranges[i].start + ranges[i].size - 1; + + if (base <= rangeEnd && rangeStart <= end) { + base = rangeEnd + 1; + end = rangeEnd + size; + if (base == 0 || end < base) + return false; + + i = 0; + continue; + } + + i++; + } + + *_rangeBase = base; + return true; +} + + status_t insert_physical_memory_range(addr_t start, uint32 size) {