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.
*
* 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_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 */
+7 -1
View File
@@ -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 */
+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_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;
@@ -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;