The heap now grows if needed; this allows VLC to load all of its plugins.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19046 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-10-11 17:45:13 +00:00
parent 6f0994d460
commit 5cfd3a1592
+51 -48
View File
@@ -50,8 +50,7 @@ struct free_chunk {
}; };
static void *sHeapBase; static uint32 sAvailable;
static uint32 /*sHeapSize,*/ sMaxHeapSize, sAvailable;
static free_chunk sFreeAnchor; static free_chunk sFreeAnchor;
@@ -172,52 +171,56 @@ free_chunk::SetToAllocated(void *allocated)
} }
// #pragma mark - // #pragma mark - private functions
static status_t
add_area(size_t size)
{
void *base;
area_id area = _kern_create_area("rld heap", &base, B_ANY_ADDRESS, size,
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (area < B_OK)
return area;
sAvailable += size - sizeof(uint32);
// declare the whole heap as one chunk, and add it
// to the free list
free_chunk *chunk = (free_chunk *)base;
chunk->size = size;
chunk->next = sFreeAnchor.next;
sFreeAnchor.next = chunk;
return B_OK;
}
static status_t
grow_heap(uint32 bytes)
{
// align the area size to an 32768 bytes boundary
bytes = (bytes + 32767) & ~32767;
return add_area(bytes);
}
// #pragma mark - public API
status_t status_t
heap_init(void) heap_init(void)
{ {
area_id area = _kern_create_area("rld heap", status_t status = add_area(kInitialHeapSize);
&sHeapBase, B_ANY_ADDRESS, kInitialHeapSize, if (status < B_OK)
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); return status;
if (area < B_OK)
return area;
sMaxHeapSize = kInitialHeapSize;
sAvailable = sMaxHeapSize - sizeof(uint32);
// declare the whole heap as one chunk, and add it
// to the free list
free_chunk *chunk = (free_chunk *)sHeapBase;
chunk->size = sMaxHeapSize;
chunk->next = NULL;
sFreeAnchor.size = 0; sFreeAnchor.size = 0;
sFreeAnchor.next = chunk;
return B_OK; return B_OK;
} }
#if 0
char *
grow_heap(uint32 bytes)
{
char *start;
if (sHeapSize + bytes > sMaxHeapSize)
return NULL;
start = (char *)sHeapBase + sHeapSize;
memset(start, 0, bytes);
sHeapSize += bytes;
return start;
}
#endif
#ifdef HEAP_TEST #ifdef HEAP_TEST
void void
dump_chunks(void) dump_chunks(void)
@@ -230,27 +233,24 @@ dump_chunks(void)
chunk = chunk->next; chunk = chunk->next;
} }
} }
uint32
heap_available(void)
{
return sAvailable;
}
#endif #endif
void * void *
malloc(size_t size) malloc(size_t size)
{ {
if (sHeapBase == NULL || size == 0) if (size == 0)
return NULL; return NULL;
// align the size requirement to an 8 bytes boundary // align the size requirement to an 8 bytes boundary
size = (size + 7) & ~7; size = (size + 7) & ~7;
if (size > sAvailable) restart:
return NULL; if (size > sAvailable) {
// try to enlarge heap
if (grow_heap(size) < B_OK)
return NULL;
}
free_chunk *chunk = sFreeAnchor.next, *last = &sFreeAnchor; free_chunk *chunk = sFreeAnchor.next, *last = &sFreeAnchor;
while (chunk && chunk->Size() < size) { while (chunk && chunk->Size() < size) {
@@ -260,7 +260,10 @@ malloc(size_t size)
if (chunk == NULL) { if (chunk == NULL) {
// could not find a free chunk as large as needed // could not find a free chunk as large as needed
return NULL; if (grow_heap(size) < B_OK)
return NULL;
goto restart;
} }
if (chunk->Size() > size + sizeof(free_chunk) + 4) { if (chunk->Size() > size + sizeof(free_chunk) + 4) {