* 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 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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _KERNEL_LOW_RESOURCE_MANAGER_H #ifndef _KERNEL_LOW_RESOURCE_MANAGER_H
@@ -22,10 +22,12 @@ enum {
B_KERNEL_RESOURCE_PAGES = 0x01, /* physical pages */ B_KERNEL_RESOURCE_PAGES = 0x01, /* physical pages */
B_KERNEL_RESOURCE_MEMORY = 0x02, /* reservable memory */ B_KERNEL_RESOURCE_MEMORY = 0x02, /* reservable memory */
B_KERNEL_RESOURCE_SEMAPHORES = 0x04, /* semaphores */ B_KERNEL_RESOURCE_SEMAPHORES = 0x04, /* semaphores */
B_KERNEL_RESOURCE_ADDRESS_SPACE = 0x08, /* address space */
B_ALL_KERNEL_RESOURCES = B_KERNEL_RESOURCE_PAGES B_ALL_KERNEL_RESOURCES = B_KERNEL_RESOURCE_PAGES
| B_KERNEL_RESOURCE_MEMORY | B_KERNEL_RESOURCE_MEMORY
| B_KERNEL_RESOURCE_SEMAPHORES | B_KERNEL_RESOURCE_SEMAPHORES
| B_KERNEL_RESOURCE_ADDRESS_SPACE
}; };
typedef void (*low_resource_func)(void *data, uint32 resources, int32 level); 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); uint32 vm_num_page_faults(void);
off_t vm_available_memory(void); off_t vm_available_memory(void);
off_t vm_available_not_needed_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_memset_physical(addr_t address, int value, size_t length);
status_t vm_memcpy_from_physical(void* to, addr_t from, 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 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. * Distributed under the terms of the MIT License.
*/ */
@@ -35,7 +35,7 @@
struct low_resource_handler struct low_resource_handler
: public DoublyLinkedListLinkImpl<low_resource_handler> { : public DoublyLinkedListLinkImpl<low_resource_handler> {
low_resource_func function; low_resource_func function;
void *data; void* data;
uint32 resources; uint32 resources;
int32 priority; int32 priority;
}; };
@@ -63,6 +63,7 @@ static off_t sCriticalMemoryLimit;
static int32 sLowPagesState = B_NO_LOW_RESOURCE; static int32 sLowPagesState = B_NO_LOW_RESOURCE;
static int32 sLowMemoryState = B_NO_LOW_RESOURCE; static int32 sLowMemoryState = B_NO_LOW_RESOURCE;
static int32 sLowSemaphoresState = 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 uint32 sLowResources = 0; // resources that are not B_NO_LOW_RESOURCE
static bigtime_t sLastMeasurement; static bigtime_t sLastMeasurement;
@@ -85,6 +86,8 @@ low_resource_state_no_update(uint32 resources)
state = max_c(state, sLowMemoryState); state = max_c(state, sLowMemoryState);
if ((resources & B_KERNEL_RESOURCE_SEMAPHORES) != 0) if ((resources & B_KERNEL_RESOURCE_SEMAPHORES) != 0)
state = max_c(state, sLowSemaphoresState); state = max_c(state, sLowSemaphoresState);
if ((resources & B_KERNEL_RESOURCE_ADDRESS_SPACE) != 0)
state = max_c(state, sLowSpaceState);
return state; return state;
} }
@@ -104,7 +107,7 @@ call_handlers(uint32 lowResources)
low_resource_handler marker; low_resource_handler marker;
sLowResourceHandlers.Insert(&marker, false); sLowResourceHandlers.Insert(&marker, false);
while (low_resource_handler *handler while (low_resource_handler* handler
= sLowResourceHandlers.GetNext(&marker)) { = sLowResourceHandlers.GetNext(&marker)) {
// swap with handler // swap with handler
sLowResourceHandlers.Swap(&marker, handler); sLowResourceHandlers.Swap(&marker, handler);
@@ -173,11 +176,27 @@ compute_state(void)
sLowSemaphoresState = B_NO_LOW_RESOURCE; sLowSemaphoresState = B_NO_LOW_RESOURCE;
sLowResources &= ~B_KERNEL_RESOURCE_SEMAPHORES; 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 static status_t
low_resource_manager(void *) low_resource_manager(void*)
{ {
bigtime_t timeout = kLowResourceInterval; bigtime_t timeout = kLowResourceInterval;
while (true) { while (true) {
@@ -231,15 +250,17 @@ state_to_string(uint32 state)
static int 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_PAGES) != 0 ? 'p' : '-',
(sLowResources & B_KERNEL_RESOURCE_MEMORY) != 0 ? 'm' : '-', (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(" pages: %s\n", state_to_string(sLowPagesState));
kprintf(" memory: %s\n", state_to_string(sLowMemoryState)); 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(); HandlerList::Iterator iterator = sLowResourceHandlers.GetIterator();
kprintf("function data resources prio function-name\n"); 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: case B_KERNEL_RESOURCE_PAGES:
vm_schedule_page_scanner(requirements); vm_schedule_page_scanner(requirements);
break; break;
case B_KERNEL_RESOURCE_MEMORY: case B_KERNEL_RESOURCE_MEMORY:
break;
case B_KERNEL_RESOURCE_SEMAPHORES: case B_KERNEL_RESOURCE_SEMAPHORES:
case B_KERNEL_RESOURCE_ADDRESS_SPACE:
break; break;
} }
@@ -354,7 +376,7 @@ low_resource_manager_init_post_thread(void)
status_t 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", TRACE(("unregister_low_resource_handler(function = %p, data = %p)\n",
function, data)); function, data));
@@ -363,7 +385,7 @@ unregister_low_resource_handler(low_resource_func function, void *data)
HandlerList::Iterator iterator = sLowResourceHandlers.GetIterator(); HandlerList::Iterator iterator = sLowResourceHandlers.GetIterator();
while (iterator.HasNext()) { while (iterator.HasNext()) {
low_resource_handler *handler = iterator.Next(); low_resource_handler* handler = iterator.Next();
if (handler->function == function && handler->data == data) { if (handler->function == function && handler->data == data) {
sLowResourceHandlers.Remove(handler); 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. the handler will be called in low resource situations.
*/ */
status_t 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) uint32 resources, int32 priority)
{ {
TRACE(("register_low_resource_handler(function = %p, data = %p)\n", TRACE(("register_low_resource_handler(function = %p, data = %p)\n",
function, data)); function, data));
low_resource_handler *newHandler = (low_resource_handler *)malloc( low_resource_handler *newHandler = (low_resource_handler*)malloc(
sizeof(low_resource_handler)); sizeof(low_resource_handler));
if (newHandler == NULL) if (newHandler == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -402,7 +424,7 @@ register_low_resource_handler(low_resource_func function, void *data,
HandlerList::ReverseIterator iterator HandlerList::ReverseIterator iterator
= sLowResourceHandlers.GetReverseIterator(); = sLowResourceHandlers.GetReverseIterator();
low_resource_handler *last = NULL; low_resource_handler* last = NULL;
while (iterator.HasNext()) { while (iterator.HasNext()) {
low_resource_handler *handler = iterator.Next(); 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); vm_area** _area, const char* areaName, bool unmapAddressRange, bool kernel);
static size_t sKernelAddressSpaceLeft = KERNEL_SIZE;
// #pragma mark - // #pragma mark -
@@ -1383,8 +1386,12 @@ insert_area(vm_address_space* addressSpace, void** _address,
status = find_and_insert_area_slot(addressSpace, searchBase, size, status = find_and_insert_area_slot(addressSpace, searchBase, size,
searchEnd, addressSpec, area); searchEnd, addressSpec, area);
if (status == B_OK) if (status == B_OK) {
*_address = (void*)area->base; *_address = (void*)area->base;
if (addressSpace == vm_kernel_address_space())
sKernelAddressSpaceLeft -= area->size;
}
return status; return status;
} }
@@ -1668,8 +1675,16 @@ map_backing_store(vm_address_space* addressSpace, vm_cache* cache,
} }
status = insert_area(addressSpace, _virtualAddress, addressSpec, size, area); 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; goto err2;
}
// attach the cache to the area // attach the cache to the area
area->cache = cache; 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, addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name,
(flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0, kernel); (flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0, kernel);
if (status < B_OK) { if (status != B_OK) {
cache->ReleaseRefAndUnlock(); cache->ReleaseRefAndUnlock();
goto err1; goto err1;
} }
@@ -2751,6 +2766,9 @@ remove_area_from_address_space(vm_address_space* addressSpace, vm_area* area)
if (area == addressSpace->area_hint) if (area == addressSpace->area_hint)
addressSpace->area_hint = NULL; addressSpace->area_hint = NULL;
if (addressSpace == vm_kernel_address_space())
sKernelAddressSpaceLeft -= area->size;
if (temp == NULL) if (temp == NULL)
panic("vm_area_release_ref: area not found in aspace's area list\n"); 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 void
vm_unreserve_memory(size_t amount) vm_unreserve_memory(size_t amount)
{ {