Added a basic low memory handler service.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13090 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
b1a248305b
commit
b84688be5f
37
headers/private/kernel/vm_low_memory.h
Normal file
37
headers/private/kernel/vm_low_memory.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_VM_LOW_MEMORY_H
|
||||
#define _KERNEL_VM_LOW_MEMORY_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
/* warning levels for low memory handlers */
|
||||
enum {
|
||||
B_LOW_MEMORY_NOTE,
|
||||
B_LOW_MEMORY_WARNING,
|
||||
B_LOW_MEMORY_CRITICAL,
|
||||
};
|
||||
|
||||
typedef void (*low_memory_func)(void *data, int32 level);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
status_t vm_low_memory_init(void);
|
||||
void vm_low_memory(size_t requirements);
|
||||
|
||||
// these calls might get public some day
|
||||
status_t register_low_memory_handler(low_memory_func function, void *data,
|
||||
int32 priority);
|
||||
status_t unregister_low_memory_handler(low_memory_func function, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL_VM_LOW_MEMORY_H */
|
@ -5,6 +5,7 @@ KernelMergeObject kernel_vm.o :
|
||||
vm_address_space.c
|
||||
vm_cache.c
|
||||
vm_daemons.c
|
||||
vm_low_memory.cpp
|
||||
vm_page.c
|
||||
vm_store_anonymous_noswap.c
|
||||
vm_store_device.c
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <vm_store_anonymous_noswap.h>
|
||||
#include <vm_store_device.h>
|
||||
#include <vm_store_null.h>
|
||||
#include <vm_low_memory.h>
|
||||
#include <file_cache.h>
|
||||
#include <memheap.h>
|
||||
#include <debug.h>
|
||||
@ -54,6 +55,7 @@
|
||||
#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
|
||||
#define ROUNDOWN(a, b) (((a) / (b)) * (b))
|
||||
|
||||
|
||||
extern vm_address_space *kernel_aspace;
|
||||
|
||||
#define REGION_HASH_TABLE_SIZE 1024
|
||||
@ -2237,6 +2239,7 @@ vm_init_post_thread(kernel_args *args)
|
||||
{
|
||||
vm_page_init_post_thread(args);
|
||||
vm_daemon_init();
|
||||
vm_low_memory_init();
|
||||
|
||||
return heap_init_post_thread(args);
|
||||
}
|
||||
@ -2590,7 +2593,7 @@ vm_soft_fault(addr_t originalAddress, bool isWrite, bool isUser)
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
err = B_OK;
|
||||
acquire_sem_etc(map->sem, READ_COUNT, 0, 0);
|
||||
if (change_count != map->change_count) {
|
||||
// something may have changed, see if the address is still valid
|
||||
@ -2603,7 +2606,7 @@ vm_soft_fault(addr_t originalAddress, bool isWrite, bool isUser)
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
if (err == B_OK) {
|
||||
// All went fine, all there is left to do is to map the page into the address space
|
||||
|
||||
// If the page doesn't reside in the area's cache, we need to make sure it's
|
||||
|
142
src/system/kernel/vm/vm_low_memory.cpp
Normal file
142
src/system/kernel/vm/vm_low_memory.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <vm_low_memory.h>
|
||||
#include <vm_page.h>
|
||||
#include <lock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
|
||||
static const bigtime_t kLowMemoryInterval = 2000000; // 2 secs
|
||||
|
||||
static const size_t kNoteLimit = 1024;
|
||||
static const size_t kWarnLimit = 256;
|
||||
static const size_t kCriticalLimit = 32;
|
||||
|
||||
|
||||
struct low_memory_handler : public DoublyLinkedListLinkImpl<low_memory_handler> {
|
||||
low_memory_func function;
|
||||
void *data;
|
||||
int32 priority;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<low_memory_handler> HandlerList;
|
||||
|
||||
static mutex sLowMemoryMutex;
|
||||
static sem_id sLowMemoryWaitSem;
|
||||
static HandlerList sLowMemoryHandlers;
|
||||
|
||||
|
||||
static void
|
||||
call_handlers(int32 level)
|
||||
{
|
||||
MutexLocker locker(&sLowMemoryMutex);
|
||||
HandlerList::Iterator iterator = sLowMemoryHandlers.GetIterator();
|
||||
|
||||
while (iterator.HasNext()) {
|
||||
low_memory_handler *handler = iterator.Next();
|
||||
|
||||
handler->function(handler->data, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
low_memory(void *)
|
||||
{
|
||||
while (true) {
|
||||
snooze(kLowMemoryInterval);
|
||||
|
||||
uint32 freePages = vm_page_num_free_pages();
|
||||
if (freePages >= kNoteLimit)
|
||||
continue;
|
||||
|
||||
// specify low memory level
|
||||
int32 level = B_LOW_MEMORY_NOTE;
|
||||
if (freePages < kCriticalLimit)
|
||||
level = B_LOW_MEMORY_CRITICAL;
|
||||
else if (freePages < kWarnLimit)
|
||||
level = B_LOW_MEMORY_WARNING;
|
||||
|
||||
call_handlers(level);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
vm_low_memory(size_t requirements)
|
||||
{
|
||||
// ToDo: compute level with requirements in mind
|
||||
|
||||
call_handlers(B_LOW_MEMORY_NOTE);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vm_low_memory_init(void)
|
||||
{
|
||||
thread_id thread;
|
||||
|
||||
if (mutex_init(&sLowMemoryMutex, "low memory") < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
sLowMemoryWaitSem = create_sem(0, "low memory wait");
|
||||
if (sLowMemoryWaitSem < B_OK)
|
||||
return sLowMemoryWaitSem;
|
||||
|
||||
new(&sLowMemoryHandlers) HandlerList;
|
||||
// static initializers do not work in the kernel,
|
||||
// so we have to do it here, manually
|
||||
|
||||
thread = spawn_kernel_thread(&low_memory, "low memory handler", B_LOW_PRIORITY, NULL);
|
||||
send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
unregister_low_memory_handler(low_memory_func function, void *data)
|
||||
{
|
||||
MutexLocker locker(&sLowMemoryMutex);
|
||||
|
||||
HandlerList::Iterator iterator = sLowMemoryHandlers.GetIterator();
|
||||
|
||||
while (iterator.HasNext()) {
|
||||
low_memory_handler *handler = iterator.Next();
|
||||
|
||||
if (handler->function == function && handler->data == data) {
|
||||
sLowMemoryHandlers.Remove(handler);
|
||||
free(handler);
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
register_low_memory_handler(low_memory_func function, void *data, int32 priority)
|
||||
{
|
||||
low_memory_handler *handler = (low_memory_handler *)malloc(sizeof(low_memory_handler));
|
||||
if (handler == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
handler->function = function;
|
||||
handler->data = data;
|
||||
handler->priority = priority;
|
||||
|
||||
MutexLocker locker(&sLowMemoryMutex);
|
||||
sLowMemoryHandlers.Add(handler);
|
||||
return B_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user