* Implement counting free pages in kernel heaps.
* Suggest growing when there are less than 10% free pages in the last heap. Previously it would suggest growing when there were less than three free pages, which wasn't really any good measure. In quite a few cases this could have lead to too late growing and running out of heap space. * Only panic when memory allocation fails while growing kernel heaps. Otherwise just output a message and return NULL. Even this panic is not really necessary and should be continueable, but for now I'd like to see if this situation actually happens. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26157 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0a7531ac0d
commit
a5db16fc79
@ -87,6 +87,7 @@ typedef struct heap_allocator_s {
|
|||||||
|
|
||||||
uint32 bin_count;
|
uint32 bin_count;
|
||||||
uint32 page_count;
|
uint32 page_count;
|
||||||
|
uint32 free_page_count;
|
||||||
heap_page * free_pages;
|
heap_page * free_pages;
|
||||||
|
|
||||||
heap_bin * bins;
|
heap_bin * bins;
|
||||||
@ -237,13 +238,9 @@ dump_bin(heap_bin *bin)
|
|||||||
static void
|
static void
|
||||||
dump_allocator(heap_allocator *heap)
|
dump_allocator(heap_allocator *heap)
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
dprintf("allocator %p: base: 0x%08lx; size: %lu; bin_count: %lu; free_pages: %p (%lu entr%s)\n",
|
||||||
for (heap_page *page = heap->free_pages; page != NULL; page = page->next)
|
heap, heap->base, heap->size, heap->bin_count, heap->free_pages,
|
||||||
count++;
|
heap->free_page_count, heap->free_page_count == 1 ? "y" : "ies");
|
||||||
|
|
||||||
dprintf("allocator %p: base: 0x%08lx; size: %lu; bin_count: %lu; free_pages: %p (%lu entr%s)\n", heap,
|
|
||||||
heap->base, heap->size, heap->bin_count, heap->free_pages, count,
|
|
||||||
count == 1 ? "y" : "ies");
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < heap->bin_count; i++)
|
for (uint32 i = 0; i < heap->bin_count; i++)
|
||||||
dump_bin(&heap->bins[i]);
|
dump_bin(&heap->bins[i]);
|
||||||
@ -589,6 +586,9 @@ heap_validate_heap(heap_allocator *heap)
|
|||||||
freePageCount++;
|
freePageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (heap->free_page_count != freePageCount)
|
||||||
|
panic("free page count doesn't match free page list\n");
|
||||||
|
|
||||||
// validate the page table
|
// validate the page table
|
||||||
uint32 usedPageCount = 0;
|
uint32 usedPageCount = 0;
|
||||||
for (uint32 i = 0; i < heap->page_count; i++) {
|
for (uint32 i = 0; i < heap->page_count; i++) {
|
||||||
@ -718,6 +718,7 @@ heap_attach(addr_t base, size_t size)
|
|||||||
heap->page_table[i].prev = &heap->page_table[i - 1];
|
heap->page_table[i].prev = &heap->page_table[i - 1];
|
||||||
}
|
}
|
||||||
heap->free_pages = &heap->page_table[0];
|
heap->free_pages = &heap->page_table[0];
|
||||||
|
heap->free_page_count = pageCount;
|
||||||
heap->page_table[0].prev = NULL;
|
heap->page_table[0].prev = NULL;
|
||||||
|
|
||||||
mutex_init(&heap->lock, "heap_mutex");
|
mutex_init(&heap->lock, "heap_mutex");
|
||||||
@ -808,6 +809,7 @@ heap_raw_alloc(heap_allocator *heap, size_t size, uint32 binIndex)
|
|||||||
// small allocation, just grab the next free page
|
// small allocation, just grab the next free page
|
||||||
heap_page *page = heap->free_pages;
|
heap_page *page = heap->free_pages;
|
||||||
heap->free_pages = page->next;
|
heap->free_pages = page->next;
|
||||||
|
heap->free_page_count--;
|
||||||
if (page->next)
|
if (page->next)
|
||||||
page->next->prev = NULL;
|
page->next->prev = NULL;
|
||||||
|
|
||||||
@ -872,6 +874,7 @@ heap_raw_alloc(heap_allocator *heap, size_t size, uint32 binIndex)
|
|||||||
page->free_list = NULL;
|
page->free_list = NULL;
|
||||||
page->allocation_id = (uint16)first;
|
page->allocation_id = (uint16)first;
|
||||||
}
|
}
|
||||||
|
heap->free_page_count -= pageCount;
|
||||||
|
|
||||||
#if KERNEL_HEAP_LEAK_CHECK
|
#if KERNEL_HEAP_LEAK_CHECK
|
||||||
heap_leak_check_info *info = (heap_leak_check_info *)(heap->base
|
heap_leak_check_info *info = (heap_leak_check_info *)(heap->base
|
||||||
@ -929,10 +932,8 @@ heap_memalign(heap_allocator *heap, size_t alignment, size_t size,
|
|||||||
|
|
||||||
if (heap->next == NULL && shouldGrow) {
|
if (heap->next == NULL && shouldGrow) {
|
||||||
// suggest growing if we are the last heap and we have
|
// suggest growing if we are the last heap and we have
|
||||||
// less than three free pages left
|
// less than 10% free pages
|
||||||
*shouldGrow = (heap->free_pages == NULL
|
*shouldGrow = heap->free_page_count < heap->page_count / 10;
|
||||||
|| heap->free_pages->next == NULL
|
|
||||||
|| heap->free_pages->next->next == NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if KERNEL_HEAP_LEAK_CHECK
|
#if KERNEL_HEAP_LEAK_CHECK
|
||||||
@ -1029,6 +1030,7 @@ heap_free(heap_allocator *heap, void *address)
|
|||||||
heap_unlink_page(page, &bin->page_list);
|
heap_unlink_page(page, &bin->page_list);
|
||||||
page->in_use = 0;
|
page->in_use = 0;
|
||||||
heap_link_page(page, &heap->free_pages);
|
heap_link_page(page, &heap->free_pages);
|
||||||
|
heap->free_page_count++;
|
||||||
} else if (page->free_count == 1) {
|
} else if (page->free_count == 1) {
|
||||||
// we need to add ourselfs to the page list of the bin
|
// we need to add ourselfs to the page list of the bin
|
||||||
heap_link_page(page, &bin->page_list);
|
heap_link_page(page, &bin->page_list);
|
||||||
@ -1066,6 +1068,7 @@ heap_free(heap_allocator *heap, void *address)
|
|||||||
|
|
||||||
// return it to the free list
|
// return it to the free list
|
||||||
heap_link_page(&page[i], &heap->free_pages);
|
heap_link_page(&page[i], &heap->free_pages);
|
||||||
|
heap->free_page_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1431,7 +1434,10 @@ malloc_nogrow(size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no memory available
|
// no memory available
|
||||||
panic("heap: all heaps have run out of memory\n");
|
if (thread_get_current_thread_id() == sHeapGrowThread)
|
||||||
|
panic("heap: all heaps have run out of memory while growing\n");
|
||||||
|
else
|
||||||
|
dprintf("heap: all heaps have run out of memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user