diff --git a/headers/private/kernel/memheap.h b/headers/private/kernel/heap.h similarity index 60% rename from headers/private/kernel/memheap.h rename to headers/private/kernel/heap.h index 44d318e1ab..8064f63d39 100644 --- a/headers/private/kernel/memheap.h +++ b/headers/private/kernel/heap.h @@ -5,18 +5,17 @@ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. */ -#ifndef _KERNEL_MEMHEAP_H -#define _KERNEL_MEMHEAP_H - +#ifndef _KERNEL_HEAP_H +#define _KERNEL_HEAP_H #include -struct kernel_args; +// allocate 16MB initial heap for the kernel +#define INITIAL_HEAP_SIZE 16 * 1024 * 1024 +// grow by another 8MB each time the heap runs out of memory +#define HEAP_GROW_SIZE 8 * 1024 * 1024 -#define HEAP_SIZE 0x02000000 - // 32 MB heap for the kernel (!) - #ifdef __cplusplus extern "C" { @@ -25,8 +24,8 @@ extern "C" { void *memalign(size_t alignment, size_t size); status_t heap_init(addr_t heapBase, size_t heapSize); -status_t heap_init_post_sem(struct kernel_args *args); -status_t heap_init_post_thread(struct kernel_args *args); +status_t heap_init_post_sem(); +status_t heap_init_post_thread(); #ifdef __cplusplus } diff --git a/src/system/kernel/Jamfile b/src/system/kernel/Jamfile index fc7354c471..13fe475fa6 100644 --- a/src/system/kernel/Jamfile +++ b/src/system/kernel/Jamfile @@ -21,7 +21,7 @@ KernelMergeObject kernel_core.o : condition_variable.cpp cpu.c elf.cpp - heap.c + heap.cpp image.c int.c kernel_daemon.c diff --git a/src/system/kernel/heap.c b/src/system/kernel/heap.c deleted file mode 100644 index 2635e7219e..0000000000 --- a/src/system/kernel/heap.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - * - * Copyright 2001, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -//#define TRACE_HEAP -#ifdef TRACE_HEAP -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - -/* prevent freeing pointers that were not allocated by kmalloc or are already freeed */ -#if KDEBUG > 1 -# define PARANOID_POINTER_CHECK 1 -#else -# define PARANOID_POINTER_CHECK 0 -#endif -/* initialize newly allocated memory with something non zero */ -#define PARANOID_KMALLOC 1 -/* check if freed pointers are already freed, and fill freed memory with 0xdeadbeef */ -#define PARANOID_KFREE 1 -/* use a back and front wall around each allocation */ -#define USE_WALL 0 -#define USE_CHECKING_WALL 0 - -#define WALL_SIZE 8 - // must be a multiple of 4 - -#if USE_CHECKING_WALL -# define WALL_CHECK_FREQUENCY 1 /* every tenth second */ -#endif - -#if USE_WALL -struct front_wall { -# if USE_CHECKING_WALL - struct list_link link; -# endif - size_t alignment; - size_t size; - uint32 wall[WALL_SIZE / 4]; -}; - -struct back_wall { - uint32 wall[WALL_SIZE / 4]; -}; -#endif // USE_WALL - -// heap stuff -// ripped mostly from nujeffos - -struct heap_page { - uint16 bin_index : 5; - uint16 free_count : 9; - uint16 cleaning : 1; - uint16 in_use : 1; -} PACKED; - -// used for bin==bin_count allocations -#define allocation_id free_count - -static vint32 current_alloc_id = 0; -static struct heap_page *heap_alloc_table; -static addr_t heap_base_ptr; -static addr_t heap_base; -static addr_t heap_size; - -struct heap_bin { - uint32 element_size; - uint32 grow_size; - uint32 alloc_count; - void *free_list; - uint32 free_count; - char *raw_list; - uint32 raw_count; -}; - -static struct heap_bin bins[] = { - {16, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {32, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {64, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {128, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {256, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {512, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {1024, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {2048, B_PAGE_SIZE, 0, 0, 0, 0, 0}, - {0x1000, 0x1000, 0, 0, 0, 0, 0}, - {0x2000, 0x2000, 0, 0, 0, 0, 0}, - {0x3000, 0x3000, 0, 0, 0, 0, 0}, - {0x4000, 0x4000, 0, 0, 0, 0, 0}, - {0x5000, 0x5000, 0, 0, 0, 0, 0}, - {0x6000, 0x6000, 0, 0, 0, 0, 0}, - {0x7000, 0x7000, 0, 0, 0, 0, 0}, - {0x8000, 0x8000, 0, 0, 0, 0, 0}, - {0x9000, 0x9000, 0, 0, 0, 0, 0}, - {0xa000, 0xa000, 0, 0, 0, 0, 0}, - {0xb000, 0xb000, 0, 0, 0, 0, 0}, - {0xc000, 0xc000, 0, 0, 0, 0, 0}, - {0xd000, 0xd000, 0, 0, 0, 0, 0}, - {0xe000, 0xe000, 0, 0, 0, 0, 0}, - {0xf000, 0xf000, 0, 0, 0, 0, 0}, - {0x10000, 0x10000, 0, 0, 0, 0, 0} // 64k -}; - -static const int bin_count = sizeof(bins) / sizeof(struct heap_bin); -static mutex heap_lock; - -#if USE_CHECKING_WALL -sem_id sWallCheckLock = -1; -struct list sWalls; -#endif - -#if PARANOID_POINTER_CHECK - -#define PTRCHECKLIST_ENTRIES 32768 -static void *ptrchecklist[PTRCHECKLIST_ENTRIES]; /* automatically initialized to zero */ - -static void -ptrchecklist_store(void *ptr) -{ - int i; - mutex_lock(&heap_lock); - for (i = 0; i != PTRCHECKLIST_ENTRIES; i++) - if (ptrchecklist[i] == NULL) { - ptrchecklist[i] = ptr; - break; - } - mutex_unlock(&heap_lock); - if (i == PTRCHECKLIST_ENTRIES) - panic("Sorry, out of entries, increase PTRCHECKLIST_ENTRIES in heap.c\n"); -} - - -static bool -ptrchecklist_remove(void *ptr) -{ - int i; - bool found = false; - mutex_lock(&heap_lock); - for (i = 0; i != PTRCHECKLIST_ENTRIES; i++) - if (ptrchecklist[i] == ptr) { - ptrchecklist[i] = NULL; - found = true; - break; - } - mutex_unlock(&heap_lock); - return found; -} - -#endif /* PARANOID_POINTER_CHECK */ - -#if USE_WALL - -static size_t -wall_size(size_t alignment) -{ - if (alignment == 0) - return sizeof(struct front_wall) + sizeof(struct back_wall); - - return 2 * alignment; -} - - -static void * -get_base_address_from_wall(struct front_wall *wall) -{ - if (wall->alignment == 0) - return (void *)wall; - - return (void *)((addr_t)wall + sizeof(struct front_wall) - wall->alignment); -} - - -static struct front_wall * -get_wall(void *address) -{ - return (struct front_wall *)((addr_t)address - sizeof(struct front_wall)); -} - - -static void -set_wall(struct front_wall *wall, size_t size, size_t alignment) -{ - struct back_wall *backWall; - uint32 i; - - size -= wall_size(alignment); - - wall->alignment = alignment; - wall->size = size; - - for (i = 0; i < WALL_SIZE / sizeof(uint32); i++) { - wall->wall[i] = 0xabadcafe; - } - - backWall = (struct back_wall *)((addr_t)wall + sizeof(struct front_wall) + size); - for (i = 0; i < WALL_SIZE / sizeof(uint32); i++) { - backWall->wall[i] = 0xabadcafe; - } -} - - -static void * -add_wall(void *address, size_t size, size_t alignment) -{ - struct front_wall *wall; - - if (alignment == 0) - address = (uint8 *)address + sizeof(struct front_wall); - else - address = (uint8 *)address + alignment; - - wall = get_wall(address); - set_wall(wall, size, alignment); - -#if USE_CHECKING_WALL - acquire_sem(sWallCheckLock); - list_add_link_to_tail(&sWalls, &wall->link); - release_sem(sWallCheckLock); -#endif - return address; -} - - -void check_wall(void *address); -void -check_wall(void *address) -{ - struct front_wall *frontWall = get_wall(address); - struct back_wall *backWall; - uint32 i; - - for (i = 0; i < WALL_SIZE / 4; i++) { - if (frontWall->wall[i] != 0xabadcafe) { - panic("free: front wall %i (%p) was overwritten (allocation at %p, %lu bytes): %08lx\n", - i, frontWall, address, frontWall->size, frontWall->wall[i]); - } - } - - backWall = (struct back_wall *)((uint8 *)address + frontWall->size); - - for (i = 0; i < WALL_SIZE / 4; i++) { - if (backWall->wall[i] != 0xabadcafe) { - panic("free: back wall %i (%p) was overwritten (allocation at %p, %lu bytes): %08lx\n", - i, backWall, address, frontWall->size, backWall->wall[i]); - } - } -} - -#endif /* USE_WALL */ - -#if USE_CHECKING_WALL - -static void -check_wall_daemon(void *arg, int iteration) -{ - struct front_wall *wall = NULL; - - acquire_sem(sWallCheckLock); - - while ((wall = list_get_next_item(&sWalls, wall)) != NULL) { - check_wall((uint8 *)wall + sizeof(struct front_wall)); - } - - release_sem(sWallCheckLock); -} - -#endif /* USE_CHECKING_WALL */ - -static void -dump_bin(int bin_index) -{ - struct heap_bin *bin = &bins[bin_index]; - unsigned int *temp; - - dprintf("%d:\tesize %lu\tgrow_size %lu\talloc_count %lu\tfree_count %lu\traw_count %lu\traw_list %p\n", - bin_index, bin->element_size, bin->grow_size, bin->alloc_count, bin->free_count, bin->raw_count, bin->raw_list); - dprintf("free_list: "); - for(temp = bin->free_list; temp != NULL; temp = (unsigned int *)*temp) { - dprintf("%p ", temp); - } - dprintf("NULL\n"); -} - - -static int -dump_bin_list(int argc, char **argv) -{ - int i; - - dprintf("%d heap bins at %p:\n", bin_count, bins); - - for (i = 0; i < bin_count; i++) { - dump_bin(i); - } - return 0; -} - - -/* called from vm_init. The heap should already be mapped in at this point, we just - * do a little housekeeping to set up the data structure. - */ - -status_t -heap_init(addr_t heapBase, size_t heapSize) -{ - const unsigned int page_entries = B_PAGE_SIZE / sizeof(struct heap_page); - // set some global pointers - heap_alloc_table = (struct heap_page *)heapBase; - heap_size = ((uint64)heapSize * page_entries / (page_entries + 1)) & ~(B_PAGE_SIZE-1); - heap_base = (unsigned int)heap_alloc_table + PAGE_ALIGN(heap_size / page_entries); - heap_base_ptr = heap_base; - TRACE(("heap_alloc_table = %p, heap_base = 0x%lx, heap_size = 0x%lx\n", - heap_alloc_table, heap_base, heap_size)); - - // zero out the heap alloc table at the base of the heap - memset((void *)heap_alloc_table, 0, (heap_size / B_PAGE_SIZE) * sizeof(struct heap_page)); - - // pre-init the mutex to at least fall through any semaphore calls - heap_lock.sem = -1; - heap_lock.holder = -1; - -#if USE_CHECKING_WALL - list_init(&sWalls); -#endif - - // set up some debug commands - add_debugger_command("heap_bindump", &dump_bin_list, "dump stats about bin usage"); - - return B_OK; -} - - -status_t -heap_init_post_sem(kernel_args *args) -{ - if (mutex_init(&heap_lock, "heap_mutex") < 0) - panic("error creating heap mutex\n"); - -#if USE_CHECKING_WALL - sWallCheckLock = create_sem(1, "check wall"); -#endif - return B_OK; -} - - -status_t -heap_init_post_thread(kernel_args *args) -{ -#if USE_CHECKING_WALL - register_kernel_daemon(check_wall_daemon, NULL, WALL_CHECK_FREQUENCY); -#endif - return B_OK; -} - - -static inline int32 -next_alloc_id(void) -{ - return atomic_add(¤t_alloc_id, 1) & ((1<<(9-1))-1); -} - - -static char * -raw_alloc(unsigned int size, int bin_index) -{ - unsigned int new_heap_ptr; - char *retval; - struct heap_page *page; - addr_t addr; - - new_heap_ptr = heap_base_ptr + PAGE_ALIGN(size); - if (new_heap_ptr > heap_base + heap_size) { - panic("heap overgrew itself!\n"); - return NULL; - } - - for (addr = heap_base_ptr; addr < new_heap_ptr; addr += B_PAGE_SIZE) { - page = &heap_alloc_table[(addr - heap_base) / B_PAGE_SIZE]; - page->in_use = 1; - page->cleaning = 0; - page->bin_index = bin_index; - if (bin_index < bin_count && bins[bin_index].element_size < B_PAGE_SIZE) - page->free_count = B_PAGE_SIZE / bins[bin_index].element_size; - else - page->free_count = 1; - } - - retval = (char *)heap_base_ptr; - heap_base_ptr = new_heap_ptr; - return retval; -} - - -#if DEBUG -static bool -is_valid_alignment(size_t number) -{ - // this cryptic line accepts zero and all powers of two - return ((~number + 1) | ((number << 1) - 1)) == ~0UL; -} -#endif - - -// #pragma mark - - - -void * -memalign(size_t alignment, size_t size) -{ - void *address = NULL; - int bin_index; - unsigned int i; - struct heap_page *page; - - TRACE(("memalign(alignment = %lu, size = %lu\n", alignment, size)); - -#if DEBUG - if (!is_valid_alignment(alignment)) - panic("memalign() with an alignment which is not a power of 2\n"); -#endif - - if (!kernel_startup && !are_interrupts_enabled()) - panic("malloc: called with interrupts disabled\n"); - - mutex_lock(&heap_lock); - -#if USE_WALL - if (alignment > 0) { - // make the alignment big enough to contain the front wall - while (alignment < sizeof(struct front_wall)) - alignment *= 2; - } - - size += wall_size(alignment); -#else - // ToDo: that code "aligns" the buffer because the bins are always - // aligned on their bin size - if (size < alignment) - size = alignment; -#endif - - for (bin_index = 0; bin_index < bin_count; bin_index++) - if (size <= bins[bin_index].element_size) - break; - - if (bin_index == bin_count) { - int32 alloc_id; - alloc_id = next_alloc_id(); - - // try to find freed blocks first... - if (size < (heap_base_ptr - heap_base) / 10) { // but don't try too hard - int first = -1; - page = heap_alloc_table; - for (i = 0; i < (heap_base_ptr - heap_base) / B_PAGE_SIZE; i++) { - if (page[i].in_use) { - first = -1; - continue; - } - if (first > 0) { - if ((1 + i - first) * B_PAGE_SIZE > size) - break; - } else - first = i; - } - if (first > -1) - address = (void *)(heap_base + first * B_PAGE_SIZE); - } - if (address == NULL) - address = raw_alloc(size, bin_index); - page = &heap_alloc_table[((unsigned int)address - heap_base) / B_PAGE_SIZE]; - for (i = 0; i < (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE; i++) { - page[i].in_use = 1; - page[i].cleaning = 0; - page[i].bin_index = bin_count; - page[i].allocation_id = alloc_id; - } - } else { - if (bins[bin_index].free_list != NULL) { - address = bins[bin_index].free_list; - bins[bin_index].free_list = (void *)(*(unsigned int *)bins[bin_index].free_list); - bins[bin_index].free_count--; -#if PARANOID_KFREE - // Ensure that the 0xdeadbeef is cleared so we do not walk this - // freelist if the user does not clear/use these bytes. - ((uint32 *)address)[1] = 0; -#endif - } else { - if (bins[bin_index].raw_count == 0) { - bins[bin_index].raw_list = raw_alloc(bins[bin_index].grow_size, bin_index); - bins[bin_index].raw_count = bins[bin_index].grow_size / bins[bin_index].element_size; - } - - bins[bin_index].raw_count--; - address = bins[bin_index].raw_list; - bins[bin_index].raw_list += bins[bin_index].element_size; - } - - bins[bin_index].alloc_count++; - page = &heap_alloc_table[((unsigned int)address - heap_base) / B_PAGE_SIZE]; - page[0].free_count--; - - TRACE(("kmalloc0: page %p: bin_index %d, free_count %d\n", page, page->bin_index, page->free_count)); - - for(i = 1; i < bins[bin_index].element_size / B_PAGE_SIZE; i++) { - page[i].free_count--; - TRACE(("kmalloc1: page 0x%x: bin_index %d, free_count %d\n", page[i], page[i].bin_index, page[i].free_count)); - } - } - - mutex_unlock(&heap_lock); - - TRACE(("kmalloc: asked to allocate size %d, returning ptr = %p\n", size, address)); - -#if PARANOID_KMALLOC - memset(address, 0xcc, size); -#endif - -#if PARANOID_POINTER_CHECK - ptrchecklist_store(address); -#endif - -#if USE_WALL - address = add_wall(address, size, alignment); -#endif - - return address; -} - - -void * -malloc(size_t size) -{ - return memalign(0, size); -} - - -void -free(void *address) -{ - struct heap_page *page; - struct heap_bin *bin; - unsigned int i; - - if (!kernel_startup && !are_interrupts_enabled()) - panic("free: called with interrupts disabled\n"); - - if (address == NULL) - return; - - if ((addr_t)address < heap_base || (addr_t)address >= (heap_base + heap_size)) - panic("free: asked to free invalid address %p\n", address); - -#if USE_WALL - { - struct front_wall *wall = get_wall(address); - -#if USE_CHECKING_WALL - acquire_sem(sWallCheckLock); - list_remove_link(&wall->link); - release_sem(sWallCheckLock); -#endif - check_wall(address); - address = get_base_address_from_wall(wall); - } -#endif - -#if PARANOID_POINTER_CHECK - if (!ptrchecklist_remove(address)) - panic("free(): asked to free invalid pointer %p\n", address); -#endif - - mutex_lock(&heap_lock); - - TRACE(("free(): asked to free at ptr = %p\n", address)); - - page = &heap_alloc_table[((unsigned)address - heap_base) / B_PAGE_SIZE]; - - TRACE(("free(): page %p: bin_index %d, free_count %d\n", page, page->bin_index, page->free_count)); - - if (page[0].bin_index > bin_count) - panic("free(): page %p: invalid bin_index %d\n", page, page->bin_index); - - if (page[0].bin_index < bin_count) { - bin = &bins[page[0].bin_index]; - - if (bin->element_size <= B_PAGE_SIZE && (addr_t)address % bin->element_size != 0) - panic("kfree: passed invalid pointer %p! Supposed to be in bin for esize 0x%lx\n", address, bin->element_size); - - for (i = 0; i < bin->element_size / B_PAGE_SIZE; i++) { - if (page[i].bin_index != page[0].bin_index) - panic("free(): not all pages in allocation match bin_index\n"); - page[i].free_count++; - } - -#if PARANOID_KFREE - if (((uint32 *)address)[1] == 0xdeadbeef) { - // This block looks like it was freed already, walk the free list - // on this bin to make sure this address doesn't exist. - unsigned int *temp; - for (temp = bin->free_list; temp != NULL; temp = (unsigned int *)*temp) { - if (temp == (unsigned int *)address) - panic("free(): address %p already exists in bin free list\n", address); - } - } - - // mark the free space as freed - { - uint32 i; - uint32 *dead = (uint32 *)address; - - if (bin->element_size % 4 != 0) - panic("free(): didn't expect a bin element size that is not a multiple of 4\n"); - - // the first 4 bytes are overwritten with the next free list pointer later - for (i = 1; i < bin->element_size / 4; i++) - dead[i] = 0xdeadbeef; - } -#endif - - *(unsigned int *)address = (unsigned int)bin->free_list; - bin->free_list = address; - bin->alloc_count--; - bin->free_count++; - } else { - // this chunk has been allocated via raw_alloc() directly - // TODO: since the heap must be replaced anyway, we don't - // free this allocation anymore... (tracking them would - // require some extra stuff) - - for (i = 1; i <= (heap_base_ptr - heap_base) / B_PAGE_SIZE; i++) { - if (!page[i].in_use) - break; - if (page[i].bin_index != bin_count) - break; - if (page[i].allocation_id != page[0].allocation_id) - break; - page[i].in_use = 0; - page[i].cleaning = 0; - page[i].allocation_id = 0; - } - page[0].in_use = 0; - page[0].cleaning = 0; - page[0].allocation_id = 0; - } - - mutex_unlock(&heap_lock); -} - - -/** Naive implementation of realloc() - it's very simple but - * it's there and working. - * It takes the bin of the current allocation if the new size - * fits in and is larger than the size of the next smaller bin. - * If not, it allocates a new chunk of memory, and copies and - * frees the old buffer. - */ - -void * -realloc(void *address, size_t newSize) -{ - void *newAddress = NULL; - size_t maxSize = 0, minSize; - - if (!kernel_startup && !are_interrupts_enabled()) - panic("realloc(): called with interrupts disabled\n"); - - if (address != NULL && ((addr_t)address < heap_base || (addr_t)address >= (heap_base + heap_size))) - panic("realloc(): asked to realloc invalid address %p\n", address); - - if (newSize == 0) { - free(address); - return NULL; - } - - // find out the size of the old allocation first - - if (address != NULL) { - struct heap_page *page; -#if USE_WALL - struct front_wall *wall = get_wall(address); -#endif - - mutex_lock(&heap_lock); - page = &heap_alloc_table[((unsigned)address - heap_base) / B_PAGE_SIZE]; - - TRACE(("realloc(): page %p: bin_index %d, free_count %d\n", page, page->bin_index, page->free_count)); - - if (page[0].bin_index > bin_count) - panic("realloc(): page %p: invalid bin_index %d\n", page, page->bin_index); - - if (page[0].bin_index < bin_count) { - maxSize = bins[page[0].bin_index].element_size; - minSize = page[0].bin_index > 0 ? bins[page[0].bin_index - 1].element_size : 0; - } else { - int i; - for (i = 1; (addr_t)&page[i] < heap_base; i++) { - if (!page[i].in_use) - break; - if (page[i].bin_index != bin_count) - break; - if (page[i].allocation_id != page[0].allocation_id) - break; - } - minSize = 0; - maxSize = i * B_PAGE_SIZE; - } - - mutex_unlock(&heap_lock); - -#if USE_WALL - newSize += wall_size(wall->alignment); -#endif - - // does the new allocation simply fit in the bin? - if (newSize > minSize && newSize <= maxSize) { -#if USE_WALL - check_wall(address); - - // we need to move the back wall, and honour the - // alignment so that the address stays the same - set_wall(wall, newSize, wall->alignment); -#endif - return address; - } - } - - // if not, allocate a new chunk of memory - newAddress = malloc(newSize); - if (newAddress == NULL) - return NULL; - - // copy the old data and free the old allocation - if (address) { - // we do have the maxSize of the bin at this point - memcpy(newAddress, address, min(maxSize, newSize)); - free(address); - } - - return newAddress; -} - - -void * -calloc(size_t numElements, size_t size) -{ - void *address = malloc(numElements * size); - if (address != NULL) - memset(address, 0, numElements * size); - - return address; -} - diff --git a/src/system/kernel/heap.cpp b/src/system/kernel/heap.cpp new file mode 100644 index 0000000000..f8c00e6ff4 --- /dev/null +++ b/src/system/kernel/heap.cpp @@ -0,0 +1,921 @@ +/* + * Copyright 2008, Michael Lotz, mmlr@mlotz.ch. + * Distributed under the terms of the MIT License. + * + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define TRACE_HEAP +#ifdef TRACE_HEAP +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +// initialize newly allocated memory with something non zero +#define PARANOID_KMALLOC 1 +// check for double free, and fill freed memory with 0xdeadbeef +#define PARANOID_KFREE 1 +// validate sanity of the heap after each operation (slow!) +#define PARANOID_VALIDATION 0 + +typedef struct heap_page_s { + uint16 index; + uint16 bin_index : 5; + uint16 free_count : 10; + uint16 in_use : 1; + heap_page_s * next; + heap_page_s * prev; + uint16 empty_index; + addr_t * free_list; +} heap_page; + +// used for bin == bin_count allocations +#define allocation_id free_count + +typedef struct heap_bin_s { + uint32 element_size; + uint16 max_free_count; + heap_page * page_list; // sorted so that the desired page is always first +} heap_bin; + +typedef struct heap_allocator_s { + addr_t base; + size_t size; + mutex lock; + vint32 large_alloc_id; + + uint32 bin_count; + uint32 page_count; + heap_page * free_pages; + + heap_bin * bins; + heap_page * page_table; + + heap_allocator_s * next; +} heap_allocator; + +static heap_allocator *sHeapList = NULL; +static heap_allocator *sLastGrowRequest = NULL; +static sem_id sHeapGrowSem = -1; +static sem_id sHeapGrownNotify = -1; + + +static void +dump_page(heap_page *page) +{ + uint32 count = 0; + for (addr_t *temp = page->free_list; temp != NULL; temp = (addr_t *)*temp) + count++; + + dprintf("\t\tpage %p: bin_index: %u; free_count: %u; empty_index: %u; free_list %p (%lu entr%s)\n", + page, page->bin_index, page->free_count, page->empty_index, + page->free_list, count, count == 1 ? "y" : "ies"); +} + + +static void +dump_bin(heap_bin *bin) +{ + dprintf("\telement_size: %lu; max_free_count: %u; page_list %p;\n", + bin->element_size, bin->max_free_count, bin->page_list); + + for (heap_page *temp = bin->page_list; temp != NULL; temp = temp->next) + dump_page(temp); +} + + +static void +dump_allocator(heap_allocator *heap) +{ + uint32 count = 0; + for (heap_page *page = heap->free_pages; page != NULL; page = page->next) + count++; + + 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++) + dump_bin(&heap->bins[i]); + + dprintf("\n"); +} + + +static int +dump_heap_list(int argc, char **argv) +{ + heap_allocator *heap = sHeapList; + while (heap) { + dump_allocator(heap); + heap = heap->next; + } + + return 0; +} + + +#if PARANOID_VALIDATION +static void +heap_validate_heap(heap_allocator *heap) +{ + mutex_lock(&heap->lock); + + // validate the free pages list + uint32 freePageCount = 0; + heap_page *lastPage = NULL; + heap_page *page = heap->free_pages; + while (page) { + if ((addr_t)page < (addr_t)&heap->page_table[0] + || (addr_t)page >= (addr_t)&heap->page_table[heap->page_count]) + panic("free page is not part of the page table\n"); + + if (page->index >= heap->page_count) + panic("free page has invalid index\n"); + + if ((addr_t)&heap->page_table[page->index] != (addr_t)page) + panic("free page index does not lead to target page\n"); + + if (page->prev != lastPage) + panic("free page entry has invalid prev link\n"); + + if (page->in_use) + panic("free page marked as in use\n"); + + lastPage = page; + page = page->next; + freePageCount++; + } + + // validate the page table + uint32 usedPageCount = 0; + for (uint32 i = 0; i < heap->page_count; i++) { + if (heap->page_table[i].in_use) + usedPageCount++; + } + + if (freePageCount + usedPageCount != heap->page_count) { + panic("free pages and used pages do not add up (%lu + %lu != %lu)\n", + freePageCount, usedPageCount, heap->page_count); + } + + // validate the bins + for (uint32 i = 0; i < heap->bin_count; i++) { + heap_bin *bin = &heap->bins[i]; + + lastPage = NULL; + page = bin->page_list; + int32 lastFreeCount = 0; + while (page) { + if ((addr_t)page < (addr_t)&heap->page_table[0] + || (addr_t)page >= (addr_t)&heap->page_table[heap->page_count]) + panic("used page is not part of the page table\n"); + + if (page->index >= heap->page_count) + panic("used page has invalid index\n"); + + if ((addr_t)&heap->page_table[page->index] != (addr_t)page) + panic("used page index does not lead to target page\n"); + + if (page->prev != lastPage) + panic("used page entry has invalid prev link (%p vs %p bin %lu)\n", + page->prev, lastPage, i); + + if (!page->in_use) + panic("used page marked as not in use\n"); + + if (page->bin_index != i) + panic("used page with bin index %u in page list of bin %lu\n", + page->bin_index, i); + + if (page->free_count < lastFreeCount) + panic("ordering of bin page list broken\n"); + + // validate the free list + uint32 freeSlotsCount = 0; + addr_t *element = page->free_list; + addr_t pageBase = heap->base + page->index * B_PAGE_SIZE; + while (element) { + if ((addr_t)element < pageBase + || (addr_t)element >= pageBase + B_PAGE_SIZE) + panic("free list entry out of page range\n"); + + if (((addr_t)element - pageBase) % bin->element_size != 0) + panic("free list entry not on a element boundary\n"); + + element = (addr_t *)*element; + freeSlotsCount++; + } + + uint32 slotCount = bin->max_free_count; + if (page->empty_index > slotCount) + panic("empty index beyond slot count (%u with %lu slots)\n", + page->empty_index, slotCount); + + freeSlotsCount += (slotCount - page->empty_index); + if (freeSlotsCount > slotCount) + panic("more free slots than fit into the page\n"); + + lastPage = page; + lastFreeCount = page->free_count; + page = page->next; + } + } + + mutex_unlock(&heap->lock); +} +#endif + + +heap_allocator * +heap_attach(addr_t base, size_t size, bool postSem) +{ + heap_allocator *heap = (heap_allocator *)base; + base += sizeof(heap_allocator); + size -= sizeof(heap_allocator); + + size_t binSizes[] = { 16, 32, 64, 96, 128, 192, 256, 384, 512, 1024, 2048, B_PAGE_SIZE }; + uint32 binCount = sizeof(binSizes) / sizeof(binSizes[0]); + heap->bin_count = binCount; + heap->bins = (heap_bin *)base; + base += binCount * sizeof(heap_bin); + size -= binCount * sizeof(heap_bin); + + for (uint32 i = 0; i < binCount; i++) { + heap_bin *bin = &heap->bins[i]; + bin->element_size = binSizes[i]; + bin->max_free_count = B_PAGE_SIZE / binSizes[i]; + bin->page_list = NULL; + } + + uint32 pageCount = size / B_PAGE_SIZE; + size_t pageTableSize = pageCount * sizeof(heap_page); + heap->page_table = (heap_page *)base; + base += pageTableSize; + size -= pageTableSize; + + // the rest is now actually usable memory (rounded to the next page) + heap->base = (addr_t)(base + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE; + heap->size = (size_t)(size / B_PAGE_SIZE) * B_PAGE_SIZE; + + // now we know the real page count + pageCount = heap->size / B_PAGE_SIZE; + heap->page_count = pageCount; + + // zero out the heap alloc table at the base of the heap + memset((void *)heap->page_table, 0, pageTableSize); + for (uint32 i = 0; i < pageCount; i++) + heap->page_table[i].index = i; + + // add all pages up into the free pages list + for (uint32 i = 1; i < pageCount; i++) { + heap->page_table[i - 1].next = &heap->page_table[i]; + heap->page_table[i].prev = &heap->page_table[i - 1]; + } + heap->free_pages = &heap->page_table[0]; + heap->page_table[0].prev = NULL; + + if (postSem) { + if (mutex_init(&heap->lock, "heap_mutex") < 0) { + panic("heap_attach(): error creating heap mutex\n"); + return NULL; + } + } else { + // pre-init the mutex to at least fall through any semaphore calls + heap->lock.sem = -1; + heap->lock.holder = -1; + } + + heap->next = NULL; + dprintf("heap_attach: attached to %p - usable range 0x%08lx - 0x%08lx\n", + heap, heap->base, heap->base + heap->size); + return heap; +} + + +static inline uint32 +heap_next_alloc_id(heap_allocator *heap) +{ + return atomic_add(&heap->large_alloc_id, 1) & ((1 << 9) - 1); +} + + +static inline void +heap_link_page(heap_page *page, heap_page **list) +{ + page->prev = NULL; + page->next = *list; + if (page->next) + page->next->prev = page; + *list = page; +} + + +static inline void +heap_unlink_page(heap_page *page, heap_page **list) +{ + if (page->prev) + page->prev->next = page->next; + if (page->next) + page->next->prev = page->prev; + if (list && *list == page) { + *list = page->next; + if (page->next) + page->next->prev = NULL; + } +} + + +static void * +heap_raw_alloc(heap_allocator *heap, size_t size, uint32 binIndex) +{ + heap_bin *bin = NULL; + if (binIndex < heap->bin_count) + bin = &heap->bins[binIndex]; + + if (bin && bin->page_list != NULL) { + // we have a page where we have a free slot + void *address = NULL; + heap_page *page = bin->page_list; + if (page->free_list) { + // there's a previously freed entry we can use + address = page->free_list; + page->free_list = (addr_t *)*page->free_list; + } else { + // the page hasn't been fully allocated so use the next empty_index + address = (void *)(heap->base + page->index * B_PAGE_SIZE + + page->empty_index * bin->element_size); + page->empty_index++; + } + + page->free_count--; + if (page->free_count == 0) { + // the page is now full so we remove it from the page_list + bin->page_list = page->next; + if (page->next) + page->next->prev = NULL; + page->next = page->prev = NULL; + } + + return address; + } + + // we don't have anything free right away, we must allocate a new page + if (heap->free_pages == NULL) { + // there are no free pages anymore, we ran out of memory + TRACE(("heap %p: no free pages to allocate %lu bytes\n", heap, size)); + return NULL; + } + + if (bin) { + // small allocation, just grab the next free page + heap_page *page = heap->free_pages; + heap->free_pages = page->next; + if (page->next) + page->next->prev = NULL; + + page->in_use = 1; + page->bin_index = binIndex; + page->free_count = bin->max_free_count - 1; + page->empty_index = 1; + page->free_list = NULL; + page->next = page->prev = NULL; + + if (page->free_count > 0) { + // by design there are no other pages in the bins page list + bin->page_list = page; + } + + // we return the first slot in this page + return (void *)(heap->base + page->index * B_PAGE_SIZE); + } + + // large allocation, we must search for contiguous slots + bool found = false; + int32 first = -1; + for (uint32 i = 0; i < heap->page_count; i++) { + if (heap->page_table[i].in_use) { + first = -1; + continue; + } + + if (first > 0) { + if ((1 + i - first) * B_PAGE_SIZE >= size) { + found = true; + break; + } + } else + first = i; + } + + if (!found) { + TRACE(("heap %p: found no contiguous pages to allocate %ld bytes\n", heap, size)); + return NULL; + } + + uint32 allocationID = heap_next_alloc_id(heap); + uint32 pageCount = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE; + for (uint32 i = first; i < first + pageCount; i++) { + heap_page *page = &heap->page_table[i]; + page->in_use = 1; + page->bin_index = binIndex; + + heap_unlink_page(page, &heap->free_pages); + + page->next = page->prev = NULL; + page->free_list = NULL; + page->allocation_id = allocationID; + } + + return (void *)(heap->base + first * B_PAGE_SIZE); +} + + +#if DEBUG +static bool +is_valid_alignment(size_t number) +{ + // this cryptic line accepts zero and all powers of two + return ((~number + 1) | ((number << 1) - 1)) == ~0UL; +} +#endif + + +static void * +heap_memalign(heap_allocator *heap, size_t alignment, size_t size, + bool *shouldGrow) +{ + TRACE(("memalign(alignment = %lu, size = %lu)\n", alignment, size)); + +#if DEBUG + if (!is_valid_alignment(alignment)) + panic("memalign() with an alignment which is not a power of 2\n"); +#endif + + mutex_lock(&heap->lock); + + // ToDo: that code "aligns" the buffer because the bins are always + // aligned on their bin size + if (size < alignment) + size = alignment; + + uint32 binIndex; + for (binIndex = 0; binIndex < heap->bin_count; binIndex++) { + if (size <= heap->bins[binIndex].element_size) + break; + } + + void *address = heap_raw_alloc(heap, size, binIndex); + + TRACE(("memalign(): asked to allocate %lu bytes, returning pointer %p\n", size, address)); + + if (heap->next == NULL) { + // suggest growing if we are the last heap and we have + // less than three free pages left + *shouldGrow = (heap->free_pages == NULL + || heap->free_pages->next == NULL + || heap->free_pages->next->next == NULL); + } + + mutex_unlock(&heap->lock); + if (address == NULL) + return address; + +#if PARANOID_KFREE + // make sure 0xdeadbeef is cleared if we do not overwrite the memory + // and the user does not clear it + ((uint32 *)address)[1] = 0xcccccccc; +#endif + +#if PARANOID_KMALLOC + memset(address, 0xcc, size); +#endif + + return address; +} + + +static status_t +heap_free(heap_allocator *heap, void *address) +{ + if (address == NULL) + return B_OK; + + if ((addr_t)address < heap->base + || (addr_t)address >= heap->base + heap->size) { + // this address does not belong to us + return B_ENTRY_NOT_FOUND; + } + + mutex_lock(&heap->lock); + + TRACE(("free(): asked to free at ptr = %p\n", address)); + + heap_page *page = &heap->page_table[((addr_t)address - heap->base) / B_PAGE_SIZE]; + + TRACE(("free(): page %p: bin_index %d, free_count %d\n", page, page->bin_index, page->free_count)); + + if (page->bin_index > heap->bin_count) { + panic("free(): page %p: invalid bin_index %d\n", page, page->bin_index); + mutex_unlock(&heap->lock); + return B_ERROR; + } + + if (page->bin_index < heap->bin_count) { + // small allocation + heap_bin *bin = &heap->bins[page->bin_index]; + if (((addr_t)address - heap->base - page->index * B_PAGE_SIZE) % bin->element_size != 0) { + panic("free(): passed invalid pointer %p supposed to be in bin for element size %ld\n", address, bin->element_size); + mutex_unlock(&heap->lock); + return B_ERROR; + } + +#if PARANOID_KFREE + if (((uint32 *)address)[1] == 0xdeadbeef) { + // This block looks like it was freed already, walk the free list + // on this page to make sure this address doesn't exist. + for (addr_t *temp = page->free_list; temp != NULL; temp = (addr_t *)*temp) { + if (temp == address) { + panic("free(): address %p already exists in page free list\n", address); + mutex_unlock(&heap->lock); + return B_ERROR; + } + } + } + + uint32 *dead = (uint32 *)address; + if (bin->element_size % 4 != 0) { + panic("free(): didn't expect a bin element size that is not a multiple of 4\n"); + mutex_unlock(&heap->lock); + return B_ERROR; + } + + // the first 4 bytes are overwritten with the next free list pointer later + for (uint32 i = 1; i < bin->element_size / sizeof(uint32); i++) + dead[i] = 0xdeadbeef; +#endif + + // add the address to the page free list + *(addr_t *)address = (addr_t)page->free_list; + page->free_list = (addr_t *)address; + page->free_count++; + + if (page->free_count == bin->max_free_count) { + // we are now empty, remove the page from the bin list + heap_unlink_page(page, &bin->page_list); + page->in_use = 0; + heap_link_page(page, &heap->free_pages); + } else if (page->free_count == 1) { + // we need to add ourselfs to the page list of the bin + heap_link_page(page, &bin->page_list); + } else { + // we might need to move back in the free pages list + if (page->next && page->next->free_count < page->free_count) { + // move ourselfs so the list stays ordered + heap_page *insert = page->next; + while (insert->next + && insert->next->free_count < page->free_count) + insert = insert->next; + + heap_unlink_page(page, &bin->page_list); + + page->prev = insert; + page->next = insert->next; + if (page->next) + page->next->prev = page; + insert->next = page; + } + } + } else { + // large allocation, just return the pages to the page free list + uint32 allocationID = page->allocation_id; + uint32 maxPages = heap->page_count - page->index; + for (uint32 i = 0; i < maxPages; i++) { + // loop until we find the end of this allocation + if (!page[i].in_use || page[i].bin_index != heap->bin_count + || page[i].allocation_id != allocationID) + break; + + // this page still belongs to the same allocation + page[i].in_use = 0; + page[i].allocation_id = 0; + + // return it to the free list + heap_link_page(&page[i], &heap->free_pages); + } + } + + mutex_unlock(&heap->lock); + return B_OK; +} + + +static status_t +heap_realloc(heap_allocator *heap, void *address, void **newAddress, + size_t newSize) +{ + if ((addr_t)address < heap->base + || (addr_t)address >= heap->base + heap->size) { + // this address does not belong to us + return B_ENTRY_NOT_FOUND; + } + + mutex_lock(&heap->lock); + TRACE(("realloc(address = %p, newSize = %lu)\n", address, newSize)); + + heap_page *page = &heap->page_table[((addr_t)address - heap->base) / B_PAGE_SIZE]; + if (page->bin_index > heap->bin_count) { + panic("realloc(): page %p: invalid bin_index %d\n", page, page->bin_index); + mutex_unlock(&heap->lock); + return B_ERROR; + } + + // find out the size of the old allocation first + size_t minSize = 0; + size_t maxSize = 0; + if (page->bin_index < heap->bin_count) { + // this was a small allocation + heap_bin *bin = &heap->bins[page->bin_index]; + maxSize = bin->element_size; + if (page->bin_index > 0) + minSize = heap->bins[page->bin_index - 1].element_size + 1; + } else { + // this was a large allocation + uint32 allocationID = page->allocation_id; + uint32 maxPages = heap->page_count - page->index; + maxSize = B_PAGE_SIZE; + for (uint32 i = 1; i < maxPages; i++) { + if (!page[i].in_use || page[i].bin_index != heap->bin_count + || page[i].allocation_id != allocationID) + break; + + minSize += B_PAGE_SIZE; + maxSize += B_PAGE_SIZE; + } + } + + mutex_unlock(&heap->lock); + + // does the new allocation simply fit in the old allocation? + if (newSize > minSize && newSize <= maxSize) { + *newAddress = address; + return B_OK; + } + + // if not, allocate a new chunk of memory + *newAddress = malloc(newSize); + if (*newAddress == NULL) { + // we tried but it didn't work out, but still the operation is done + return B_OK; + } + + // copy the old data and free the old allocation + memcpy(*newAddress, address, min_c(maxSize, newSize)); + free(address); + return B_OK; +} + + +// #pragma mark - + + +static int32 +heap_grow_thread(void *) +{ + heap_allocator *heap = sHeapList; + while (true) { + // wait for a request to grow the heap list + if (acquire_sem(sHeapGrowSem) < B_OK) + continue; + + // find the last heap + while (heap->next) + heap = heap->next; + + if (sLastGrowRequest != heap) { + // we have already grown since the latest request, just ignore + continue; + } + + TRACE(("heap_grower: kernel heap will run out of memory soon, allocating new one\n")); + void *heapAddress = NULL; + area_id heapArea = create_area("additional heap", &heapAddress, + B_ANY_KERNEL_BLOCK_ADDRESS, HEAP_GROW_SIZE, B_FULL_LOCK, + B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + if (heapArea < B_OK) { + panic("heap_grower: couldn't allocate additional heap area\n"); + continue; + } + + heap_allocator *newHeap = heap_attach((addr_t)heapAddress, + HEAP_GROW_SIZE, true); + if (newHeap == NULL) { + panic("heap_grower: could not attach additional heap!\n"); + delete_area(heapArea); + continue; + } + +#if PARANOID_VALIDATION + heap_validate_heap(newHeap); +#endif + heap->next = newHeap; + TRACE(("heap_grower: new heap linked in\n")); + + // notify anyone waiting for this request + release_sem_etc(sHeapGrownNotify, -1, B_RELEASE_ALL); + } + + return 0; +} + + +status_t +heap_init(addr_t base, size_t size) +{ + sHeapList = heap_attach(base, size, false); + + // set up some debug commands + add_debugger_command("heap", &dump_heap_list, "dump stats about the kernel heap(s)"); + return B_OK; +} + + +status_t +heap_init_post_sem() +{ + // create the lock for the initial heap + if (mutex_init(&sHeapList->lock, "heap_mutex") < B_OK) { + panic("heap_init_post_sem(): error creating heap mutex\n"); + return B_ERROR; + } + + sHeapGrowSem = create_sem(0, "heap_grow_sem"); + if (sHeapGrowSem < 0) { + panic("heap_init_post_sem(): failed to create heap grow sem\n"); + return B_ERROR; + } + + sHeapGrownNotify = create_sem(0, "heap_grown_notify"); + if (sHeapGrownNotify < 0) { + panic("heap_init_post_sem(): failed to create heap grown notify sem\n"); + return B_ERROR; + } + + return B_OK; +} + + +status_t +heap_init_post_thread() +{ + thread_id thread = spawn_kernel_thread(heap_grow_thread, "heap grower", + B_URGENT_PRIORITY, NULL); + if (thread < 0) { + panic("heap_init_post_thread(): cannot create heap grow thread\n"); + return B_ERROR; + } + + send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE); + return B_OK; +} + + +// #pragma mark - + + +void * +memalign(size_t alignment, size_t size) +{ + if (!kernel_startup && !are_interrupts_enabled()) { + panic("memalign(): called with interrupts disabled\n"); + return NULL; + } + + if (size > (HEAP_GROW_SIZE * 3) / 4) { + // don't even attempt such a huge allocation + panic("heap: huge allocation of %lu bytes asked!\n", size); + return NULL; + } + + heap_allocator *heap = sHeapList; + while (heap) { + bool shouldGrow = false; + void *result = heap_memalign(heap, alignment, size, &shouldGrow); + if (heap->next == NULL && (shouldGrow || result == NULL)) { + // the last heap will or has run out of memory, notify the grower + sLastGrowRequest = heap; + if (result == NULL) { + // urgent request, do the request and wait for at max 250ms + release_sem(sHeapGrowSem); + acquire_sem_etc(sHeapGrownNotify, 1, B_RELATIVE_TIMEOUT, 250000); + } else { + // not so urgent, just notify the grower + release_sem_etc(sHeapGrowSem, 1, B_DO_NOT_RESCHEDULE); + } + } + + if (result == NULL) { + heap = heap->next; + continue; + } + +#if PARANOID_VALIDATION + heap_validate_heap(heap); +#endif + + return result; + } + + panic("heap: kernel heap has run out of memory\n"); + return NULL; +} + + +void * +malloc(size_t size) +{ + return memalign(0, size); +} + + +void +free(void *address) +{ + if (!kernel_startup && !are_interrupts_enabled()) { + panic("free(): called with interrupts disabled\n"); + return; + } + + heap_allocator *heap = sHeapList; + while (heap) { + if (heap_free(heap, address) == B_OK) { +#if PARANOID_VALIDATION + heap_validate_heap(heap); +#endif + return; + } + + heap = heap->next; + } + + panic("free(): free failed for address %p\n", address); +} + + +void * +realloc(void *address, size_t newSize) +{ + if (!kernel_startup && !are_interrupts_enabled()) { + panic("realloc(): called with interrupts disabled\n"); + return NULL; + } + + if (address == NULL) + return malloc(newSize); + + if (newSize == 0) { + free(address); + return NULL; + } + + heap_allocator *heap = sHeapList; + while (heap) { + void *newAddress = NULL; + if (heap_realloc(heap, address, &newAddress, newSize) == B_OK) { +#if PARANOID_VALIDATION + heap_validate_heap(heap); +#endif + return newAddress; + } + + heap = heap->next; + } + + panic("realloc(): failed to realloc address %p to size %lu\n", address, newSize); + return NULL; +} + + +void * +calloc(size_t numElements, size_t size) +{ + void *address = memalign(0, numElements * size); + if (address != NULL) + memset(address, 0, numElements * size); + + return address; +} diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 666cdb2c16..291640a3c2 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -3480,16 +3480,8 @@ vm_init(kernel_args *args) vm_page_init_num_pages(args); sAvailableMemory = vm_page_num_pages() * B_PAGE_SIZE; - // reduce the heap size if we have not so much RAM - size_t heapSize = HEAP_SIZE; - if (sAvailableMemory < 100 * 1024 * 1024) - heapSize /= 4; - else if (sAvailableMemory < 200 * 1024 * 1024) - heapSize /= 2; - else if (sAvailableMemory >= 1024 * 1024 * 1024) - heapSize *= 2; - // map in the new heap and initialize it + size_t heapSize = INITIAL_HEAP_SIZE; addr_t heapBase = vm_allocate_early(args, heapSize, heapSize, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); TRACE(("heap at 0x%lx\n", heapBase)); @@ -3607,8 +3599,7 @@ vm_init_post_sem(kernel_args *args) mutex_init(&sMappingLock, "page mappings"); slab_init_post_sem(); - - return heap_init_post_sem(args); + return heap_init_post_sem(); } @@ -3618,8 +3609,7 @@ vm_init_post_thread(kernel_args *args) vm_page_init_post_thread(args); vm_daemon_init(); vm_low_memory_init_post_thread(); - - return heap_init_post_thread(args); + return heap_init_post_thread(); }