diff --git a/headers/private/kernel/vm_store_anonymous_noswap.h b/headers/private/kernel/vm_store_anonymous_noswap.h index 325e97d434..58f30a4e35 100644 --- a/headers/private/kernel/vm_store_anonymous_noswap.h +++ b/headers/private/kernel/vm_store_anonymous_noswap.h @@ -1,5 +1,5 @@ -/* - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. +/* + * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -8,8 +8,13 @@ #ifndef _KERNEL_VM_STORE_ANONYMOUS_H #define _KERNEL_VM_STORE_ANONYMOUS_H + #include -vm_store *vm_store_create_anonymous_noswap(bool stack, int32 numGuardPages); + +#ifdef __cplusplus +extern "C" +#endif +vm_store *vm_store_create_anonymous_noswap(bool canOvercommit, int32 numGuardPages); #endif /* _KERNEL_VM_STORE_ANONYMOUS_H */ diff --git a/headers/private/kernel/vm_types.h b/headers/private/kernel/vm_types.h index 4a95d3e203..764defe0c9 100644 --- a/headers/private/kernel/vm_types.h +++ b/headers/private/kernel/vm_types.h @@ -187,7 +187,13 @@ enum { (B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_KERNEL_EXECUTE_AREA \ | B_KERNEL_STACK_AREA) +#define B_OVERCOMMITTING_AREA 0x1000 + // ToDo: this is not really a protection flag, but since the "protection" + // field is the only flag field, we currently use it for this. + // A cleaner approach would be appreciated - maybe just an official generic + // flags region in the protection field. + #define B_USER_AREA_FLAGS (B_USER_PROTECTION) -#define B_KERNEL_AREA_FLAGS (B_KERNEL_PROTECTION | B_USER_CLONEABLE_AREA) +#define B_KERNEL_AREA_FLAGS (B_KERNEL_PROTECTION | B_USER_CLONEABLE_AREA | B_OVERCOMMITTING_AREA) #endif /* _KERNEL_VM_TYPES_H */ diff --git a/src/system/kernel/vm/vm.c b/src/system/kernel/vm/vm.c index d33087b91a..339a725e7b 100644 --- a/src/system/kernel/vm/vm.c +++ b/src/system/kernel/vm/vm.c @@ -674,6 +674,7 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, vm_cache_ref *cache_ref; vm_page *page = NULL; bool isStack = (protection & B_STACK_AREA) != 0; + bool canOvercommit = false; status_t err; TRACE(("create_anonymous_area %s: size 0x%lx\n", name, size)); @@ -681,6 +682,9 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, if (!arch_vm_supports_protection(protection)) return B_NOT_SUPPORTED; + if (isStack || (protection & B_OVERCOMMITTING_AREA) != 0) + canOvercommit = true; + #ifdef DEBUG_KERNEL_STACKS if ((protection & B_KERNEL_STACK_AREA) != 0) isStack = true; @@ -730,8 +734,9 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, } // create an anonymous store object - store = vm_store_create_anonymous_noswap(isStack, (protection & B_USER_PROTECTION) != 0 ? - USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES); + store = vm_store_create_anonymous_noswap(canOvercommit, isStack ? + ((protection & B_USER_PROTECTION) != 0 ? + USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES) : 0); if (store == NULL) panic("vm_create_anonymous_area: vm_create_store_anonymous_noswap returned NULL"); cache = vm_cache_create(store); @@ -755,8 +760,6 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, break; } -// dprintf("create_anonymous_area: calling map_backing store\n"); - vm_cache_acquire_ref(cache_ref, true); err = map_backing_store(aspace, store, address, 0, size, addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name); vm_cache_release_ref(cache_ref); @@ -778,8 +781,6 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, return err; } -// dprintf("create_anonymous_area: done calling map_backing store\n"); - cache_ref = store->cache->ref; switch (wiring) { case B_NO_LOCK: @@ -788,10 +789,11 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, case B_FULL_LOCK: { - // pages aren't mapped at this point, but we just simulate a fault on + // Pages aren't mapped at this point, but we just simulate a fault on // every page, which should allocate them + // ToDo: at this point, it would probably be cheaper to allocate + // and map the pages directly addr_t va; - // XXX remove for (va = area->base; va < area->base + area->size; va += B_PAGE_SIZE) { #ifdef DEBUG_KERNEL_STACKS # ifdef STACK_GROWS_DOWNWARDS @@ -877,7 +879,7 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address, } vm_put_aspace(aspace); -// dprintf("create_anonymous_area: done\n"); + TRACE(("vm_create_anonymous_area: done\n")); if (area == NULL) return B_NO_MEMORY; diff --git a/src/system/kernel/vm/vm_store_anonymous_noswap.c b/src/system/kernel/vm/vm_store_anonymous_noswap.c index 3e51ad490e..c00ce8db25 100644 --- a/src/system/kernel/vm/vm_store_anonymous_noswap.c +++ b/src/system/kernel/vm/vm_store_anonymous_noswap.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -24,11 +24,12 @@ // The stack functionality looks like a good candidate to put into its own // store. I have not done this because once we have a swap file backing up -// the memory, it would probably not a good idea to separate this anymore. +// the memory, it would probably not be a good idea to separate this +// anymore. typedef struct anonymous_store { vm_store vm; - bool is_stack; + bool can_overcommit; int32 guarded_size; } anonymous_store; @@ -46,8 +47,8 @@ anonymous_commit(struct vm_store *_store, off_t size) { anonymous_store *store = (anonymous_store *)_store; - // if we're a stack, we don't commit here, but in anonymous_fault() - if (store->is_stack) + // if we can overcommit, we don't commit here, but in anonymous_fault() + if (store->can_overcommit) return B_OK; // Check to see how much we could commit - we need real memory @@ -95,21 +96,23 @@ anonymous_fault(struct vm_store *_store, struct vm_address_space *aspace, off_t { anonymous_store *store = (anonymous_store *)_store; - if (store->is_stack) { - uint32 guardOffset; + if (store->can_overcommit) { + if (store->guarded_size > 0) { + uint32 guardOffset; #ifdef STACK_GROWS_DOWNWARDS - guardOffset = 0; + guardOffset = 0; #elif defined(STACK_GROWS_UPWARDS) - guardOffset = store->vm.cache->virtual_size - store->guarded_size; + guardOffset = store->vm.cache->virtual_size - store->guarded_size; #else # error Stack direction has not been defined in arch_config.h #endif - // report stack fault, guard page hit! - if (offset >= guardOffset && offset < guardOffset + store->guarded_size) { - TRACE(("stack overflow!\n")); - return B_BAD_ADDRESS; + // report stack fault, guard page hit! + if (offset >= guardOffset && offset < guardOffset + store->guarded_size) { + TRACE(("stack overflow!\n")); + return B_BAD_ADDRESS; + } } // try to commit additional memory @@ -141,19 +144,19 @@ static vm_store_ops anonymous_ops = { */ vm_store * -vm_store_create_anonymous_noswap(bool stack, int32 numGuardPages) +vm_store_create_anonymous_noswap(bool canOvercommit, int32 numGuardPages) { anonymous_store *store = malloc(sizeof(anonymous_store)); if (store == NULL) return NULL; - TRACE(("vm_store_create_anonymous(stack = %s, numGuardPages = %ld) at %p\n", - stack ? "true" : "false", numGuardPages, store)); + TRACE(("vm_store_create_anonymous(canOvercommit = %s, numGuardPages = %ld) at %p\n", + canOvercommit ? "yes" : "no", numGuardPages, store)); store->vm.ops = &anonymous_ops; store->vm.cache = NULL; store->vm.committed_size = 0; - store->is_stack = stack; + store->can_overcommit = canOvercommit; store->guarded_size = numGuardPages * B_PAGE_SIZE; return &store->vm;