Added an additional flag B_OVERCOMMITTING_AREA (currently to be specified

along the protection flags).
Changed the handling of B_STACK_AREA types and anonymous vm_areas: now
every area can overcommit if B_OVERCOMMITTING_AREA was specified.
B_STACK_AREA areas are still automatically overcommitting, but
B_KERNEL_STACK_AREA areas no longer.
vm_store_anonymous_noswap.c now only tests for guard pages if there were
any specified which is only done for B_STACK_AREA areas.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12673 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-05-15 15:03:44 +00:00
parent afd1024aef
commit ccc8865ba2
4 changed files with 46 additions and 30 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004, Axel Dörfler, [email protected]. * Copyright 2004-2005, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -8,8 +8,13 @@
#ifndef _KERNEL_VM_STORE_ANONYMOUS_H #ifndef _KERNEL_VM_STORE_ANONYMOUS_H
#define _KERNEL_VM_STORE_ANONYMOUS_H #define _KERNEL_VM_STORE_ANONYMOUS_H
#include <vm_types.h> #include <vm_types.h>
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 */ #endif /* _KERNEL_VM_STORE_ANONYMOUS_H */
+7 -1
View File
@@ -187,7 +187,13 @@ enum {
(B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_KERNEL_EXECUTE_AREA \ (B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_KERNEL_EXECUTE_AREA \
| B_KERNEL_STACK_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_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 */ #endif /* _KERNEL_VM_TYPES_H */
+11 -9
View File
@@ -674,6 +674,7 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
vm_cache_ref *cache_ref; vm_cache_ref *cache_ref;
vm_page *page = NULL; vm_page *page = NULL;
bool isStack = (protection & B_STACK_AREA) != 0; bool isStack = (protection & B_STACK_AREA) != 0;
bool canOvercommit = false;
status_t err; status_t err;
TRACE(("create_anonymous_area %s: size 0x%lx\n", name, size)); 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)) if (!arch_vm_supports_protection(protection))
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
if (isStack || (protection & B_OVERCOMMITTING_AREA) != 0)
canOvercommit = true;
#ifdef DEBUG_KERNEL_STACKS #ifdef DEBUG_KERNEL_STACKS
if ((protection & B_KERNEL_STACK_AREA) != 0) if ((protection & B_KERNEL_STACK_AREA) != 0)
isStack = true; isStack = true;
@@ -730,8 +734,9 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
} }
// create an anonymous store object // create an anonymous store object
store = vm_store_create_anonymous_noswap(isStack, (protection & B_USER_PROTECTION) != 0 ? store = vm_store_create_anonymous_noswap(canOvercommit, isStack ?
USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES); ((protection & B_USER_PROTECTION) != 0 ?
USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES) : 0);
if (store == NULL) if (store == NULL)
panic("vm_create_anonymous_area: vm_create_store_anonymous_noswap returned NULL"); panic("vm_create_anonymous_area: vm_create_store_anonymous_noswap returned NULL");
cache = vm_cache_create(store); cache = vm_cache_create(store);
@@ -755,8 +760,6 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
break; break;
} }
// dprintf("create_anonymous_area: calling map_backing store\n");
vm_cache_acquire_ref(cache_ref, true); 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); err = map_backing_store(aspace, store, address, 0, size, addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name);
vm_cache_release_ref(cache_ref); vm_cache_release_ref(cache_ref);
@@ -778,8 +781,6 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
return err; return err;
} }
// dprintf("create_anonymous_area: done calling map_backing store\n");
cache_ref = store->cache->ref; cache_ref = store->cache->ref;
switch (wiring) { switch (wiring) {
case B_NO_LOCK: case B_NO_LOCK:
@@ -788,10 +789,11 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
case B_FULL_LOCK: 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 // 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; addr_t va;
// XXX remove
for (va = area->base; va < area->base + area->size; va += B_PAGE_SIZE) { for (va = area->base; va < area->base + area->size; va += B_PAGE_SIZE) {
#ifdef DEBUG_KERNEL_STACKS #ifdef DEBUG_KERNEL_STACKS
# ifdef STACK_GROWS_DOWNWARDS # ifdef STACK_GROWS_DOWNWARDS
@@ -877,7 +879,7 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
} }
vm_put_aspace(aspace); vm_put_aspace(aspace);
// dprintf("create_anonymous_area: done\n"); TRACE(("vm_create_anonymous_area: done\n"));
if (area == NULL) if (area == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -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. * Distributed under the terms of the MIT License.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * 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 // 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 // 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 { typedef struct anonymous_store {
vm_store vm; vm_store vm;
bool is_stack; bool can_overcommit;
int32 guarded_size; int32 guarded_size;
} anonymous_store; } anonymous_store;
@@ -46,8 +47,8 @@ anonymous_commit(struct vm_store *_store, off_t size)
{ {
anonymous_store *store = (anonymous_store *)_store; anonymous_store *store = (anonymous_store *)_store;
// if we're a stack, we don't commit here, but in anonymous_fault() // if we can overcommit, we don't commit here, but in anonymous_fault()
if (store->is_stack) if (store->can_overcommit)
return B_OK; return B_OK;
// Check to see how much we could commit - we need real memory // 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; anonymous_store *store = (anonymous_store *)_store;
if (store->is_stack) { if (store->can_overcommit) {
uint32 guardOffset; if (store->guarded_size > 0) {
uint32 guardOffset;
#ifdef STACK_GROWS_DOWNWARDS #ifdef STACK_GROWS_DOWNWARDS
guardOffset = 0; guardOffset = 0;
#elif defined(STACK_GROWS_UPWARDS) #elif defined(STACK_GROWS_UPWARDS)
guardOffset = store->vm.cache->virtual_size - store->guarded_size; guardOffset = store->vm.cache->virtual_size - store->guarded_size;
#else #else
# error Stack direction has not been defined in arch_config.h # error Stack direction has not been defined in arch_config.h
#endif #endif
// report stack fault, guard page hit! // report stack fault, guard page hit!
if (offset >= guardOffset && offset < guardOffset + store->guarded_size) { if (offset >= guardOffset && offset < guardOffset + store->guarded_size) {
TRACE(("stack overflow!\n")); TRACE(("stack overflow!\n"));
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
} }
// try to commit additional memory // try to commit additional memory
@@ -141,19 +144,19 @@ static vm_store_ops anonymous_ops = {
*/ */
vm_store * 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)); anonymous_store *store = malloc(sizeof(anonymous_store));
if (store == NULL) if (store == NULL)
return NULL; return NULL;
TRACE(("vm_store_create_anonymous(stack = %s, numGuardPages = %ld) at %p\n", TRACE(("vm_store_create_anonymous(canOvercommit = %s, numGuardPages = %ld) at %p\n",
stack ? "true" : "false", numGuardPages, store)); canOvercommit ? "yes" : "no", numGuardPages, store));
store->vm.ops = &anonymous_ops; store->vm.ops = &anonymous_ops;
store->vm.cache = NULL; store->vm.cache = NULL;
store->vm.committed_size = 0; store->vm.committed_size = 0;
store->is_stack = stack; store->can_overcommit = canOvercommit;
store->guarded_size = numGuardPages * B_PAGE_SIZE; store->guarded_size = numGuardPages * B_PAGE_SIZE;
return &store->vm; return &store->vm;