Author: axeld Date: 2009-11-27 14:03:28 +0100 (Fri, 27 Nov 2009) New Revision: 34309 Changeset: http://dev.haiku-os.org/changeset/34309/haiku Modified: haiku/trunk/headers/private/kernel/low_resource_manager.h haiku/trunk/headers/private/kernel/vm.h haiku/trunk/src/system/kernel/low_resource_manager.cpp haiku/trunk/src/system/kernel/vm/vm.cpp Log: * The kernel's address space is now also a resource that is known to the low resource manager. * Could be drastically improved, though, by taking the fragmentation into account. Modified: haiku/trunk/headers/private/kernel/low_resource_manager.h =================================================================== --- haiku/trunk/headers/private/kernel/low_resource_manager.h 2009-11-27 12:34:15 UTC (rev 34308) +++ haiku/trunk/headers/private/kernel/low_resource_manager.h 2009-11-27 13:03:28 UTC (rev 34309) @@ -1,6 +1,6 @@ /* * Copyright 2008, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2005-2007, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. + * Copyright 2005-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_LOW_RESOURCE_MANAGER_H @@ -22,10 +22,12 @@ B_KERNEL_RESOURCE_PAGES = 0x01, /* physical pages */ B_KERNEL_RESOURCE_MEMORY = 0x02, /* reservable memory */ B_KERNEL_RESOURCE_SEMAPHORES = 0x04, /* semaphores */ + B_KERNEL_RESOURCE_ADDRESS_SPACE = 0x08, /* address space */ B_ALL_KERNEL_RESOURCES = B_KERNEL_RESOURCE_PAGES | B_KERNEL_RESOURCE_MEMORY | B_KERNEL_RESOURCE_SEMAPHORES + | B_KERNEL_RESOURCE_ADDRESS_SPACE }; typedef void (*low_resource_func)(void *data, uint32 resources, int32 level); Modified: haiku/trunk/headers/private/kernel/vm.h =================================================================== --- haiku/trunk/headers/private/kernel/vm.h 2009-11-27 12:34:15 UTC (rev 34308) +++ haiku/trunk/headers/private/kernel/vm.h 2009-11-27 13:03:28 UTC (rev 34309) @@ -115,6 +115,7 @@ uint32 vm_num_page_faults(void); off_t vm_available_memory(void); off_t vm_available_not_needed_memory(void); +size_t vm_kernel_address_space_left(void); status_t vm_memset_physical(addr_t address, int value, size_t length); status_t vm_memcpy_from_physical(void* to, addr_t from, size_t length, Modified: haiku/trunk/src/system/kernel/low_resource_manager.cpp =================================================================== --- haiku/trunk/src/system/kernel/low_resource_manager.cpp 2009-11-27 12:34:15 UTC (rev 34308) +++ haiku/trunk/src/system/kernel/low_resource_manager.cpp 2009-11-27 13:03:28 UTC (rev 34309) @@ -1,6 +1,6 @@ /* * Copyright 2008, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2005-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2005-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ @@ -35,7 +35,7 @@ struct low_resource_handler : public DoublyLinkedListLinkImpl<low_resource_handler> { low_resource_func function; - void *data; + void* data; uint32 resources; int32 priority; }; @@ -63,6 +63,7 @@ static int32 sLowPagesState = B_NO_LOW_RESOURCE; static int32 sLowMemoryState = B_NO_LOW_RESOURCE; static int32 sLowSemaphoresState = B_NO_LOW_RESOURCE; +static int32 sLowSpaceState = B_NO_LOW_RESOURCE; static uint32 sLowResources = 0; // resources that are not B_NO_LOW_RESOURCE static bigtime_t sLastMeasurement; @@ -85,6 +86,8 @@ state = max_c(state, sLowMemoryState); if ((resources & B_KERNEL_RESOURCE_SEMAPHORES) != 0) state = max_c(state, sLowSemaphoresState); + if ((resources & B_KERNEL_RESOURCE_ADDRESS_SPACE) != 0) + state = max_c(state, sLowSpaceState); return state; } @@ -104,7 +107,7 @@ low_resource_handler marker; sLowResourceHandlers.Insert(&marker, false); - while (low_resource_handler *handler + while (low_resource_handler* handler = sLowResourceHandlers.GetNext(&marker)) { // swap with handler sLowResourceHandlers.Swap(&marker, handler); @@ -173,11 +176,27 @@ sLowSemaphoresState = B_NO_LOW_RESOURCE; sLowResources &= ~B_KERNEL_RESOURCE_SEMAPHORES; } + + // free kernel address space state + // TODO: this should take fragmentation into account + size_t maxSpace = KERNEL_SIZE; + size_t freeSpace = vm_kernel_address_space_left(); + + if (freeSpace < maxSpace >> 16) + sLowSpaceState = B_LOW_RESOURCE_CRITICAL; + if (freeSpace < maxSpace >> 8) + sLowSpaceState = B_LOW_RESOURCE_WARNING; + if (freeSpace < maxSpace >> 4) + sLowSpaceState = B_LOW_RESOURCE_NOTE; + else { + sLowSpaceState = B_NO_LOW_RESOURCE; + sLowResources &= ~B_KERNEL_RESOURCE_ADDRESS_SPACE; + } } -static int32 -low_resource_manager(void *) +static status_t +low_resource_manager(void*) { bigtime_t timeout = kLowResourceInterval; while (true) { @@ -231,15 +250,17 @@ static int -dump_handlers(int argc, char **argv) +dump_handlers(int argc, char** argv) { - kprintf("current state: %c%c%c\n", + kprintf("current state: %c%c%c%c\n", (sLowResources & B_KERNEL_RESOURCE_PAGES) != 0 ? 'p' : '-', (sLowResources & B_KERNEL_RESOURCE_MEMORY) != 0 ? 'm' : '-', - (sLowResources & B_KERNEL_RESOURCE_SEMAPHORES) != 0 ? 's' : '-'); + (sLowResources & B_KERNEL_RESOURCE_SEMAPHORES) != 0 ? 's' : '-', + (sLowResources & B_KERNEL_RESOURCE_ADDRESS_SPACE) != 0 ? 'a' : '-'); kprintf(" pages: %s\n", state_to_string(sLowPagesState)); kprintf(" memory: %s\n", state_to_string(sLowMemoryState)); - kprintf(" sems: %s\n\n", state_to_string(sLowSemaphoresState)); + kprintf(" sems: %s\n", state_to_string(sLowSemaphoresState)); + kprintf(" aspace: %s\n\n", state_to_string(sLowSpaceState)); HandlerList::Iterator iterator = sLowResourceHandlers.GetIterator(); kprintf("function data resources prio function-name\n"); @@ -282,9 +303,10 @@ case B_KERNEL_RESOURCE_PAGES: vm_schedule_page_scanner(requirements); break; + case B_KERNEL_RESOURCE_MEMORY: - break; case B_KERNEL_RESOURCE_SEMAPHORES: + case B_KERNEL_RESOURCE_ADDRESS_SPACE: break; } @@ -354,7 +376,7 @@ status_t -unregister_low_resource_handler(low_resource_func function, void *data) +unregister_low_resource_handler(low_resource_func function, void* data) { TRACE(("unregister_low_resource_handler(function = %p, data = %p)\n", function, data)); @@ -363,7 +385,7 @@ HandlerList::Iterator iterator = sLowResourceHandlers.GetIterator(); while (iterator.HasNext()) { - low_resource_handler *handler = iterator.Next(); + low_resource_handler* handler = iterator.Next(); if (handler->function == function && handler->data == data) { sLowResourceHandlers.Remove(handler); @@ -380,13 +402,13 @@ the handler will be called in low resource situations. */ status_t -register_low_resource_handler(low_resource_func function, void *data, +register_low_resource_handler(low_resource_func function, void* data, uint32 resources, int32 priority) { TRACE(("register_low_resource_handler(function = %p, data = %p)\n", function, data)); - low_resource_handler *newHandler = (low_resource_handler *)malloc( + low_resource_handler *newHandler = (low_resource_handler*)malloc( sizeof(low_resource_handler)); if (newHandler == NULL) return B_NO_MEMORY; @@ -402,7 +424,7 @@ HandlerList::ReverseIterator iterator = sLowResourceHandlers.GetReverseIterator(); - low_resource_handler *last = NULL; + low_resource_handler* last = NULL; while (iterator.HasNext()) { low_resource_handler *handler = iterator.Next(); Modified: haiku/trunk/src/system/kernel/vm/vm.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/vm.cpp 2009-11-27 12:34:15 UTC (rev 34308) +++ haiku/trunk/src/system/kernel/vm/vm.cpp 2009-11-27 13:03:28 UTC (rev 34309) @@ -227,6 +227,9 @@ vm_area** _area, const char* areaName, bool unmapAddressRange, bool kernel); +static size_t sKernelAddressSpaceLeft = KERNEL_SIZE; + + // #pragma mark - @@ -1383,8 +1386,12 @@ status = find_and_insert_area_slot(addressSpace, searchBase, size, searchEnd, addressSpec, area); - if (status == B_OK) + if (status == B_OK) { *_address = (void*)area->base; + + if (addressSpace == vm_kernel_address_space()) + sKernelAddressSpaceLeft -= area->size; + } return status; } @@ -1668,8 +1675,16 @@ } status = insert_area(addressSpace, _virtualAddress, addressSpec, size, area); - if (status != B_OK) + if (status != B_OK) { + // TODO: wait and try again once this is working in the backend +#if 0 + if (status == B_NO_MEMORY && addressSpec == B_ANY_KERNEL_ADDRESS) { + low_resource(B_KERNEL_RESOURCE_ADDRESS_SPACE, size, + 0, 0); + } +#endif goto err2; + } // attach the cache to the area area->cache = cache; @@ -2006,7 +2021,7 @@ addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name, (flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0, kernel); - if (status < B_OK) { + if (status != B_OK) { cache->ReleaseRefAndUnlock(); goto err1; } @@ -2751,6 +2766,9 @@ if (area == addressSpace->area_hint) addressSpace->area_hint = NULL; + if (addressSpace == vm_kernel_address_space()) + sKernelAddressSpaceLeft -= area->size; + if (temp == NULL) panic("vm_area_release_ref: area not found in aspace's area list\n"); } @@ -5264,6 +5282,13 @@ } +size_t +vm_kernel_address_space_left(void) +{ + return sKernelAddressSpaceLeft; +} + + void vm_unreserve_memory(size_t amount) {