Now maintains the new kernel_args addr_range array in the kernel_args structure.
Exports the new insert_address_range() function as declared in boot/addr_range.h. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9416 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,21 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the Haiku License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
#include <boot/stage2.h>
|
#include <boot/stage2.h>
|
||||||
#include <boot/platform.h>
|
#include <boot/platform.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
// ToDo: the kernel_args heap chunks need to be remembered in the kernel_args
|
|
||||||
// structure, so that unneeded memory can be freed in the kernel again.
|
|
||||||
|
|
||||||
|
|
||||||
static const size_t kChunkSize = 16384;
|
static const size_t kChunkSize = 16384;
|
||||||
|
|
||||||
kernel_args gKernelArgs;
|
kernel_args gKernelArgs;
|
||||||
@@ -25,6 +22,115 @@ static void *sLast;
|
|||||||
static size_t sFree = kChunkSize;
|
static size_t sFree = kChunkSize;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_range_index(addr_range *ranges, uint32 &numRanges, uint32 index)
|
||||||
|
{
|
||||||
|
if (index + 1 == numRanges) {
|
||||||
|
// remove last range
|
||||||
|
numRanges--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(&ranges[index], &ranges[index + 1], sizeof(addr_range) * (numRanges - 1 - index));
|
||||||
|
numRanges--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Inserts the specified (start, size) pair (aka range) in the
|
||||||
|
* addr_range array.
|
||||||
|
* It will extend existing ranges in order to have as little
|
||||||
|
* ranges in the array as possible.
|
||||||
|
* Returns B_OK on success, or B_ENTRY_NOT_FOUND if there was
|
||||||
|
* no free array entry available anymore.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
insert_address_range(addr_range *ranges, uint32 *_numRanges, uint32 maxRanges,
|
||||||
|
addr_t start, uint32 size)
|
||||||
|
{
|
||||||
|
uint32 numRanges = *_numRanges;
|
||||||
|
|
||||||
|
start = ROUNDOWN(start, B_PAGE_SIZE);
|
||||||
|
size = ROUNDUP(size, B_PAGE_SIZE);
|
||||||
|
addr_t end = start + size;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < numRanges; i++) {
|
||||||
|
addr_t rangeStart = ranges[i].start;
|
||||||
|
addr_t rangeEnd = rangeStart + ranges[i].size;
|
||||||
|
|
||||||
|
if (end < rangeStart || start > rangeEnd) {
|
||||||
|
// ranges don't intersect or touch each other
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (start >= rangeStart && end <= rangeEnd) {
|
||||||
|
// range is already completely covered
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start < rangeStart) {
|
||||||
|
// prepend to the existing range
|
||||||
|
ranges[i].start = start;
|
||||||
|
ranges[i].size += rangeStart - start;
|
||||||
|
}
|
||||||
|
if (end > ranges[i].start + ranges[i].size) {
|
||||||
|
// append to the existing range
|
||||||
|
ranges[i].size = end - ranges[i].start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// join ranges if possible
|
||||||
|
|
||||||
|
for (uint32 j = 0; j < numRanges; j++) {
|
||||||
|
if (i == j)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rangeStart = ranges[i].start;
|
||||||
|
rangeEnd = rangeStart + ranges[i].size;
|
||||||
|
addr_t joinStart = ranges[j].start;
|
||||||
|
addr_t joinEnd = joinStart + ranges[j].size;
|
||||||
|
|
||||||
|
if (rangeStart <= joinEnd && joinEnd <= rangeEnd) {
|
||||||
|
// join range that used to be before the current one, or
|
||||||
|
// the one that's now entirely included by the current one
|
||||||
|
if (joinStart < rangeStart) {
|
||||||
|
ranges[i].size += rangeStart - joinStart;
|
||||||
|
ranges[i].start = joinStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_range_index(ranges, numRanges, j--);
|
||||||
|
} else if (joinStart <= rangeEnd && joinEnd > rangeEnd) {
|
||||||
|
// join range that used to be after the current one
|
||||||
|
ranges[i].size += joinEnd - rangeEnd;
|
||||||
|
|
||||||
|
remove_range_index(ranges, numRanges, j--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*_numRanges = numRanges;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no range matched, we need to create a new one
|
||||||
|
|
||||||
|
if (numRanges >= maxRanges)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
ranges[numRanges].start = (addr_t)start;
|
||||||
|
ranges[numRanges].size = size;
|
||||||
|
(*_numRanges)++;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
add_kernel_args_range(void *start, uint32 size)
|
||||||
|
{
|
||||||
|
return insert_address_range(gKernelArgs.kernel_args_range,
|
||||||
|
&gKernelArgs.num_kernel_args_ranges, MAX_KERNEL_ARGS_RANGE,
|
||||||
|
(addr_t)start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This function can be used to allocate memory that is going
|
/** This function can be used to allocate memory that is going
|
||||||
* to be passed over to the kernel. For example, the preloaded_image
|
* to be passed over to the kernel. For example, the preloaded_image
|
||||||
* structures are allocated this way.
|
* structures are allocated this way.
|
||||||
@@ -50,6 +156,8 @@ kernel_args_malloc(size_t size)
|
|||||||
if (platform_allocate_region(&block, size, B_READ_AREA | B_WRITE_AREA) != B_OK)
|
if (platform_allocate_region(&block, size, B_READ_AREA | B_WRITE_AREA) != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (add_kernel_args_range(block, size) != B_OK)
|
||||||
|
panic("kernel_args max range to low!\n");
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +169,8 @@ kernel_args_malloc(size_t size)
|
|||||||
sFirstFree = (void *)((addr_t)block + size);
|
sFirstFree = (void *)((addr_t)block + size);
|
||||||
sLast = block;
|
sLast = block;
|
||||||
sFree = kChunkSize - size;
|
sFree = kChunkSize - size;
|
||||||
|
if (add_kernel_args_range(block, size) != B_OK)
|
||||||
|
panic("kernel_args max range to low!\n");
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user