* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34309 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-11-27 13:03:28 +00:00
parent 95235380f1
commit b8a73945cf
4 changed files with 69 additions and 19 deletions
@@ -1,6 +1,6 @@
/*
* Copyright 2008, Ingo Weinhold, [email protected].
* Copyright 2005-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_LOW_RESOURCE_MANAGER_H
@@ -22,10 +22,12 @@ enum {
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);
+1
View File
@@ -115,6 +115,7 @@ void vm_get_info(struct system_memory_info *info);
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,
+37 -15
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2008, Ingo Weinhold, [email protected].
* Copyright 2005-2008, Axel Dörfler, [email protected].
* Copyright 2005-2009, Axel Dörfler, [email protected].
* 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 off_t sCriticalMemoryLimit;
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 @@ low_resource_state_no_update(uint32 resources)
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 @@ call_handlers(uint32 lowResources)
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 @@ compute_state(void)
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 @@ state_to_string(uint32 state)
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 @@ low_resource(uint32 resource, uint64 requirements, uint32 flags, uint32 timeout)
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 @@ low_resource_manager_init_post_thread(void)
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 @@ unregister_low_resource_handler(low_resource_func function, void *data)
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 @@ unregister_low_resource_handler(low_resource_func function, void *data)
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 @@ register_low_resource_handler(low_resource_func function, void *data,
HandlerList::ReverseIterator iterator
= sLowResourceHandlers.GetReverseIterator();
low_resource_handler *last = NULL;
low_resource_handler* last = NULL;
while (iterator.HasNext()) {
low_resource_handler *handler = iterator.Next();
+28 -3
View File
@@ -227,6 +227,9 @@ static status_t map_backing_store(vm_address_space* addressSpace,
vm_area** _area, const char* areaName, bool unmapAddressRange, bool kernel);
static size_t sKernelAddressSpaceLeft = KERNEL_SIZE;
// #pragma mark -
@@ -1383,8 +1386,12 @@ insert_area(vm_address_space* addressSpace, void** _address,
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 @@ map_backing_store(vm_address_space* addressSpace, vm_cache* cache,
}
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 @@ vm_create_anonymous_area(team_id team, const char* name, void** address,
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 @@ remove_area_from_address_space(vm_address_space* addressSpace, vm_area* area)
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 @@ vm_available_not_needed_memory(void)
}
size_t
vm_kernel_address_space_left(void)
{
return sKernelAddressSpaceLeft;
}
void
vm_unreserve_memory(size_t amount)
{