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:
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user