We now have a growing heap. hoardUnsbrk() is not yet implemented, though.
The new heap backend will probably be taken from the boot loader's heap implementation (the free chunk stuff). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11958 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -22,13 +22,25 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace BPrivate;
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
|
||||||
static area_id heap_region = -1;
|
struct free_chunk {
|
||||||
static addr_t brk;
|
free_chunk *next;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kInitialHeapSize = 50 * B_PAGE_SIZE;
|
||||||
|
// that's about what hoard allocates anyway
|
||||||
|
|
||||||
|
static area_id sHeapArea;
|
||||||
|
static hoardLockType sHeapLock;
|
||||||
|
static addr_t sHeapBase;
|
||||||
|
static size_t sHeapSize, sHeapAreaSize;
|
||||||
|
static free_chunk *sFreeChunks;
|
||||||
|
|
||||||
|
|
||||||
// ToDo: add real fork() support!
|
// ToDo: add real fork() support!
|
||||||
@@ -36,16 +48,99 @@ static addr_t brk;
|
|||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
__init_heap(void)
|
__init_heap(void)
|
||||||
{
|
{
|
||||||
// XXX do something better here
|
sHeapAreaSize = kInitialHeapSize;
|
||||||
if (heap_region < 0) {
|
sHeapBase = 0x10000000;
|
||||||
heap_region = create_area("heap", (void **)&brk,
|
// let the heap start at 256 MB for now
|
||||||
B_ANY_ADDRESS, 1024 * B_PAGE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
|
||||||
}
|
// ToDo: add a VM call that instructs other areas to avoid the space after the heap when possible
|
||||||
return 0;
|
// (and if not, create it at the end of that range, so that the heap can grow as much as possible)
|
||||||
|
sHeapArea = create_area("heap", (void **)&sHeapBase, B_BASE_ADDRESS,
|
||||||
|
sHeapAreaSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||||
|
|
||||||
|
hoardLockInit(sHeapLock, "heap");
|
||||||
|
return sHeapArea >= B_OK ? B_OK : sHeapArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
|
void *
|
||||||
|
hoardSbrk(long size)
|
||||||
|
{
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
|
// align size request
|
||||||
|
size = (size + hoardHeap::ALIGNMENT - 1) & ~(hoardHeap::ALIGNMENT - 1);
|
||||||
|
|
||||||
|
hoardLock(sHeapLock);
|
||||||
|
|
||||||
|
// find chunk in free list
|
||||||
|
|
||||||
|
free_chunk *chunk = sFreeChunks, *last = NULL;
|
||||||
|
for (; chunk != NULL; chunk = chunk->next, last = chunk) {
|
||||||
|
if (chunk->size < (size_t)size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// this chunk is large enough to satisfy the request
|
||||||
|
|
||||||
|
SERIAL_PRINT(("HEAP-%ld: found free chunk to hold %ld bytes\n",
|
||||||
|
find_thread(NULL), size));
|
||||||
|
|
||||||
|
void *address = (void *)chunk;
|
||||||
|
|
||||||
|
if (chunk->size + sizeof(free_chunk) > (size_t)size)
|
||||||
|
chunk = (free_chunk *)((addr_t)chunk + size);
|
||||||
|
else
|
||||||
|
chunk = chunk->next;
|
||||||
|
|
||||||
|
if (last != NULL)
|
||||||
|
last->next = chunk;
|
||||||
|
else
|
||||||
|
sFreeChunks = chunk;
|
||||||
|
|
||||||
|
hoardUnlock(sHeapLock);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There was no chunk, let's see if the area is large enough
|
||||||
|
|
||||||
|
size_t oldHeapSize = sHeapSize;
|
||||||
|
sHeapSize += size;
|
||||||
|
|
||||||
|
// round to next page size
|
||||||
|
size_t pageSize = (sHeapSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
||||||
|
|
||||||
|
if (pageSize < sHeapAreaSize) {
|
||||||
|
SERIAL_PRINT(("HEAP-%ld: heap area large enough for %ld\n", find_thread(NULL), size));
|
||||||
|
// the area is large enough already
|
||||||
|
hoardUnlock(sHeapLock);
|
||||||
|
return (void *)(sHeapBase + oldHeapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to grow the area
|
||||||
|
|
||||||
|
SERIAL_PRINT(("HEAP-%ld: need to resize heap area to %ld (%ld requested)\n",
|
||||||
|
find_thread(NULL), pageSize, size));
|
||||||
|
|
||||||
|
if (resize_area(sHeapArea, pageSize) < B_OK) {
|
||||||
|
// out of memory - ToDo: as a fall back, we could try to allocate another area
|
||||||
|
hoardUnlock(sHeapLock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sHeapAreaSize = pageSize;
|
||||||
|
|
||||||
|
hoardUnlock(sHeapLock);
|
||||||
|
return (void *)(sHeapBase + oldHeapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
hoardUnsbrk(void *ptr, long size)
|
||||||
|
{
|
||||||
|
// NOT CURRENTLY IMPLEMENTED!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hoardCreateThread(hoardThreadType &thread,
|
hoardCreateThread(hoardThreadType &thread,
|
||||||
void *(*function)(void *), void *arg)
|
void *(*function)(void *), void *arg)
|
||||||
@@ -121,22 +216,6 @@ hoardGetNumProcessors(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
hoardSbrk(long size)
|
|
||||||
{
|
|
||||||
void *ret = (void *)brk;
|
|
||||||
brk += size + hoardHeap::ALIGNMENT - 1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
hoardUnsbrk(void *ptr, long size)
|
|
||||||
{
|
|
||||||
// NOT CURRENTLY IMPLEMENTED!
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hoardYield(void)
|
hoardYield(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user