Make the all_areas list ordered by base and take advantage of this ordering

when looking up the target area on free(). This makes free() scale better with
large area counts, as the lookup can abort early when it knows that no area
below the only candidate can contain the address.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26258 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2008-07-05 01:12:34 +00:00
parent a8f9741c8c
commit dde0ba6223

View File

@ -641,7 +641,7 @@ heap_validate_heap(heap_allocator *heap)
uint32 totalPageCount = 0;
uint32 totalFreePageCount = 0;
heap_area *area = heap->all_areas;
while (area) {
while (area != NULL) {
// validate the free pages list
uint32 freePageCount = 0;
heap_page *lastPage = NULL;
@ -693,9 +693,9 @@ heap_validate_heap(heap_allocator *heap)
area = heap->areas;
heap_area *lastArea = NULL;
uint32 lastFreeCount = 0;
while (area) {
while (area != NULL) {
if (area->free_page_count < lastFreeCount)
panic("ordering of area list broken\n");
panic("size ordering of area list broken\n");
if (area->prev != lastArea)
panic("area list entry has invalid prev link\n");
@ -705,6 +705,16 @@ heap_validate_heap(heap_allocator *heap)
area = area->next;
}
lastArea = NULL;
area = heap->all_areas;
while (area != NULL) {
if (lastArea != NULL && lastArea->base < area->base)
panic("base ordering of all_areas list broken\n");
lastArea = area;
area = area->all_next;
}
// validate the bins
for (uint32 i = 0; i < heap->bin_count; i++) {
heap_bin *bin = &heap->bins[i];
@ -845,8 +855,19 @@ heap_add_area(heap_allocator *heap, area_id areaID, addr_t base, size_t size)
area->prev = lastArea;
}
area->all_next = heap->all_areas;
heap->all_areas = area;
// insert this area in the all_areas list so it stays ordered by base
if (heap->all_areas == NULL || heap->all_areas->base < area->base) {
area->all_next = heap->all_areas;
heap->all_areas = area;
} else {
heap_area *insert = heap->all_areas;
while (insert->all_next && insert->all_next->base > area->base)
insert = insert->all_next;
area->all_next = insert->all_next;
insert->all_next = area;
}
heap->total_pages += area->page_count;
heap->total_free_pages += area->free_page_count;
@ -1283,9 +1304,19 @@ heap_free(heap_allocator *heap, void *address)
heap_area *area = heap->all_areas;
while (area) {
if ((addr_t)address >= area->base
&& (addr_t)address < area->base + area->size)
// since the all_areas list is ordered by base with the biggest
// base at the top, we need only find the first area with a base
// smaller than our address to become our only candidate for freeing
if (area->base <= (addr_t)address) {
if ((addr_t)address >= area->base + area->size) {
// the only candidate area doesn't contain the address,
// set it to NULL so we return below (none of the other areas
// can contain the address as the list is ordered)
area = NULL;
}
break;
}
area = area->all_next;
}