* 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:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user