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:
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user