Now other code accounts for reserved regions in the standard region_list as well.
Introduced RESERVED_REGION_ID definition. Some minor cleanups. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7886 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+75
-46
@@ -82,15 +82,17 @@ static vm_region *vm_virtual_map_lookup(vm_virtual_map *map, addr_t address);
|
||||
//static void vm_region_release_ref(vm_region *region);
|
||||
//static void vm_region_release_ref2(vm_region *region);
|
||||
|
||||
static int region_compare(void *_r, const void *key)
|
||||
|
||||
static int
|
||||
region_compare(void *_r, const void *key)
|
||||
{
|
||||
vm_region *r = _r;
|
||||
const region_id *id = key;
|
||||
|
||||
if(r->id == *id)
|
||||
if (r->id == *id)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,10 +102,10 @@ region_hash(void *_r, const void *key, uint32 range)
|
||||
vm_region *r = _r;
|
||||
const region_id *id = key;
|
||||
|
||||
if(r != NULL)
|
||||
return (r->id % range);
|
||||
else
|
||||
return (*id % range);
|
||||
if (r != NULL)
|
||||
return r->id % range;
|
||||
|
||||
return *id % range;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,10 +115,10 @@ aspace_compare(void *_a, const void *key)
|
||||
vm_address_space *aspace = _a;
|
||||
const aspace_id *id = key;
|
||||
|
||||
if(aspace->id == *id)
|
||||
if (aspace->id == *id)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,12 +173,15 @@ region_id vm_find_region_by_name(aspace_id aid, const char *name)
|
||||
acquire_sem_etc(aspace->virtual_map.sem, READ_COUNT, 0, 0);
|
||||
|
||||
region = aspace->virtual_map.region_list;
|
||||
while(region != NULL) {
|
||||
if(strcmp(region->name, name) == 0) {
|
||||
for (; region != NULL; region = region->aspace_next) {
|
||||
// ignore reserved space regions
|
||||
if (region->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (strcmp(region->name, name) == 0) {
|
||||
id = region->id;
|
||||
break;
|
||||
}
|
||||
region = region->aspace_next;
|
||||
}
|
||||
|
||||
release_sem_etc(aspace->virtual_map.sem, READ_COUNT, 0);
|
||||
@@ -193,7 +198,7 @@ _vm_create_reserved_region_struct(vm_virtual_map *map)
|
||||
return NULL;
|
||||
|
||||
memset(reserved, 0, sizeof(vm_region));
|
||||
reserved->id = -1;
|
||||
reserved->id = RESERVED_REGION_ID;
|
||||
// this marks it as reserved space
|
||||
reserved->map = map;
|
||||
|
||||
@@ -251,7 +256,7 @@ find_reserved_region(vm_virtual_map *map, addr_t start, addr_t size, vm_region *
|
||||
while (next) {
|
||||
if (next->base <= start && next->base + next->size >= start + size) {
|
||||
// this region covers the requested range
|
||||
if (next->id != -1) {
|
||||
if (next->id != RESERVED_REGION_ID) {
|
||||
// but it's not reserved space, it's a real region
|
||||
return ERR_VM_NO_REGION_SLOT;
|
||||
}
|
||||
@@ -648,7 +653,7 @@ vm_unreserve_address_range(aspace_id aid, void *address, addr_t size)
|
||||
area = addressSpace->virtual_map.region_list;
|
||||
while (area) {
|
||||
// the region must be completely part of the reserved range
|
||||
if (area->id == -1 && area->base >= (addr_t)address
|
||||
if (area->id == RESERVED_REGION_ID && area->base >= (addr_t)address
|
||||
&& area->base + area->size <= (addr_t)address + size) {
|
||||
// remove reserved range
|
||||
vm_region *reserved = area;
|
||||
@@ -1109,7 +1114,7 @@ vm_clone_region(aspace_id aid, char *name, void **address, int addr_type,
|
||||
int err;
|
||||
|
||||
vm_address_space *aspace = vm_get_aspace_by_id(aid);
|
||||
if(aspace == NULL)
|
||||
if (aspace == NULL)
|
||||
return ERR_VM_INVALID_ASPACE;
|
||||
|
||||
src_region = vm_get_region_by_id(source_region);
|
||||
@@ -1128,10 +1133,10 @@ vm_clone_region(aspace_id aid, char *name, void **address, int addr_type,
|
||||
|
||||
vm_put_aspace(aspace);
|
||||
|
||||
if(err < 0)
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return new_region->id;
|
||||
|
||||
return new_region->id;
|
||||
}
|
||||
|
||||
|
||||
@@ -1191,25 +1196,29 @@ _vm_put_region(vm_region *region, bool aspace_locked)
|
||||
vm_address_space *aspace;
|
||||
bool removeit = false;
|
||||
|
||||
// we should never get here, but if we do, we can handle it
|
||||
if (region->id == RESERVED_REGION_ID)
|
||||
return;
|
||||
|
||||
acquire_sem_etc(region_hash_sem, WRITE_COUNT, 0, 0);
|
||||
if(atomic_add(®ion->ref_count, -1) == 1) {
|
||||
if (atomic_add(®ion->ref_count, -1) == 1) {
|
||||
hash_remove(region_table, region);
|
||||
removeit = true;
|
||||
}
|
||||
release_sem_etc(region_hash_sem, WRITE_COUNT, 0);
|
||||
|
||||
if(!removeit)
|
||||
if (!removeit)
|
||||
return;
|
||||
|
||||
aspace = region->aspace;
|
||||
|
||||
// remove the region from the aspace's virtual map
|
||||
if(!aspace_locked)
|
||||
if (!aspace_locked)
|
||||
acquire_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0, 0);
|
||||
temp = aspace->virtual_map.region_list;
|
||||
while(temp != NULL) {
|
||||
if(region == temp) {
|
||||
if(last != NULL) {
|
||||
while (temp != NULL) {
|
||||
if (region == temp) {
|
||||
if (last != NULL) {
|
||||
last->aspace_next = temp->aspace_next;
|
||||
} else {
|
||||
aspace->virtual_map.region_list = temp->aspace_next;
|
||||
@@ -1220,12 +1229,12 @@ _vm_put_region(vm_region *region, bool aspace_locked)
|
||||
last = temp;
|
||||
temp = temp->aspace_next;
|
||||
}
|
||||
if(region == aspace->virtual_map.region_hint)
|
||||
if (region == aspace->virtual_map.region_hint)
|
||||
aspace->virtual_map.region_hint = NULL;
|
||||
if(!aspace_locked)
|
||||
if (!aspace_locked)
|
||||
release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0);
|
||||
|
||||
if(temp == NULL)
|
||||
if (temp == NULL)
|
||||
panic("vm_region_release_ref: region not found in aspace's region_list\n");
|
||||
|
||||
vm_cache_remove_region(region->cache_ref, region);
|
||||
@@ -1239,8 +1248,7 @@ _vm_put_region(vm_region *region, bool aspace_locked)
|
||||
// now we can give up the last ref to the aspace
|
||||
vm_put_aspace(aspace);
|
||||
|
||||
if(region->name)
|
||||
free(region->name);
|
||||
free(region->name);
|
||||
free(region);
|
||||
|
||||
return;
|
||||
@@ -1357,11 +1365,11 @@ dump_cache_ref(int argc, char **argv)
|
||||
vm_region *region;
|
||||
vm_cache_ref *cache_ref;
|
||||
|
||||
if(argc < 2) {
|
||||
if (argc < 2) {
|
||||
dprintf("cache_ref: not enough arguments\n");
|
||||
return 0;
|
||||
}
|
||||
if(strlen(argv[1]) < 2 || argv[1][0] != '0' || argv[1][1] != 'x') {
|
||||
if (strlen(argv[1]) < 2 || argv[1][0] != '0' || argv[1][1] != 'x') {
|
||||
dprintf("cache_ref: invalid argument, pass address\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1374,7 +1382,7 @@ dump_cache_ref(int argc, char **argv)
|
||||
dprintf("lock.holder: %ld\n", cache_ref->lock.holder);
|
||||
dprintf("lock.sem: 0x%lx\n", cache_ref->lock.sem);
|
||||
dprintf("region_list:\n");
|
||||
for(region = cache_ref->region_list; region != NULL; region = region->cache_next) {
|
||||
for (region = cache_ref->region_list; region != NULL; region = region->cache_next) {
|
||||
dprintf(" region 0x%lx: ", region->id);
|
||||
dprintf("base_addr = 0x%lx ", region->base);
|
||||
dprintf("size = 0x%lx ", region->size);
|
||||
@@ -1512,18 +1520,22 @@ dump_region(int argc, char **argv)
|
||||
|
||||
|
||||
region_id
|
||||
find_region_by_address(addr_t vaddress)
|
||||
find_region_by_address(addr_t address)
|
||||
{
|
||||
vm_address_space *aspace;
|
||||
vm_region *region;
|
||||
region_id result=B_ERROR;
|
||||
region_id result = B_ERROR;
|
||||
|
||||
aspace = vm_get_current_user_aspace();
|
||||
for(region = aspace->virtual_map.region_list; region != NULL; region = region->aspace_next)
|
||||
{
|
||||
if ((vaddress>=region->base) && (vaddress<=(region->base+region->size)))
|
||||
result=region->id;
|
||||
for (region = aspace->virtual_map.region_list; region != NULL; region = region->aspace_next) {
|
||||
if (region->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (address >= region->base && address <= region->base + region->size) {
|
||||
result = region->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vm_put_aspace(aspace);
|
||||
return result;
|
||||
}
|
||||
@@ -1802,6 +1814,13 @@ vm_delete_aspace(aspace_id aid)
|
||||
region = aspace->virtual_map.region_list;
|
||||
while (region) {
|
||||
next = region->aspace_next;
|
||||
|
||||
if (region->id == RESERVED_REGION_ID) {
|
||||
// just remove it
|
||||
free(region);
|
||||
region = next;
|
||||
continue;
|
||||
}
|
||||
// decrement the ref on this region, may actually push the ref < 0, but that's okay
|
||||
_vm_put_region(region, true);
|
||||
region = next;
|
||||
@@ -1889,7 +1908,7 @@ vm_thread_dump_max_commit(void *unused)
|
||||
|
||||
(void)(unused);
|
||||
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
snooze(1000000);
|
||||
if (oldmax != max_commit)
|
||||
TRACE(("max_commit 0x%x\n", max_commit));
|
||||
@@ -2103,7 +2122,8 @@ forbid_page_faults(void)
|
||||
}
|
||||
|
||||
|
||||
int vm_page_fault(addr_t address, addr_t fault_address, bool is_write, bool is_user, addr_t *newip)
|
||||
int
|
||||
vm_page_fault(addr_t address, addr_t fault_address, bool is_write, bool is_user, addr_t *newip)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -2443,6 +2463,9 @@ vm_virtual_map_lookup(vm_virtual_map *map, addr_t address)
|
||||
return region;
|
||||
|
||||
for (region = map->region_list; region != NULL; region = region->aspace_next) {
|
||||
if (region->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (region->base <= address && (region->base + region->size) > address)
|
||||
break;
|
||||
}
|
||||
@@ -2452,17 +2475,23 @@ vm_virtual_map_lookup(vm_virtual_map *map, addr_t address)
|
||||
return region;
|
||||
}
|
||||
|
||||
int vm_get_physical_page(addr_t paddr, addr_t *vaddr, int flags)
|
||||
|
||||
int
|
||||
vm_get_physical_page(addr_t paddr, addr_t *vaddr, int flags)
|
||||
{
|
||||
return (*kernel_aspace->translation_map.ops->get_physical_page)(paddr, vaddr, flags);
|
||||
}
|
||||
|
||||
int vm_put_physical_page(addr_t vaddr)
|
||||
|
||||
int
|
||||
vm_put_physical_page(addr_t vaddr)
|
||||
{
|
||||
return (*kernel_aspace->translation_map.ops->put_physical_page)(vaddr);
|
||||
}
|
||||
|
||||
void vm_increase_max_commit(addr_t delta)
|
||||
|
||||
void
|
||||
vm_increase_max_commit(addr_t delta)
|
||||
{
|
||||
int state;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <thread.h>
|
||||
#include <debug.h>
|
||||
@@ -17,7 +18,9 @@ bool trimming_cycle;
|
||||
static addr free_memory_low_water;
|
||||
static addr free_memory_high_water;
|
||||
|
||||
static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
|
||||
static void
|
||||
scan_pages(vm_address_space *aspace, addr free_target)
|
||||
{
|
||||
vm_region *first_region;
|
||||
vm_region *region;
|
||||
@@ -33,46 +36,52 @@ static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
acquire_sem_etc(aspace->virtual_map.sem, READ_COUNT, 0, 0);
|
||||
|
||||
first_region = aspace->virtual_map.region_list;
|
||||
while(first_region && (first_region->base + (first_region->size - 1)) < aspace->scan_va)
|
||||
while (first_region && (first_region->base + (first_region->size - 1)) < aspace->scan_va)
|
||||
first_region = first_region->aspace_next;
|
||||
|
||||
if(!first_region)
|
||||
if (!first_region)
|
||||
first_region = aspace->virtual_map.region_list;
|
||||
|
||||
if(!first_region) {
|
||||
if (!first_region) {
|
||||
release_sem_etc(aspace->virtual_map.sem, READ_COUNT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
region = first_region;
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
// ignore reserved ranges
|
||||
while (region != NULL && region->id == RESERVED_REGION_ID)
|
||||
region = region->aspace_next;
|
||||
if (region == NULL)
|
||||
break;
|
||||
|
||||
// scan the pages in this region
|
||||
mutex_lock(®ion->cache_ref->lock);
|
||||
if(!region->cache_ref->cache->scan_skip) {
|
||||
if (!region->cache_ref->cache->scan_skip) {
|
||||
for(va = region->base; va < (region->base + region->size); va += PAGE_SIZE) {
|
||||
aspace->translation_map.ops->lock(&aspace->translation_map);
|
||||
aspace->translation_map.ops->query(&aspace->translation_map, va, &pa, &flags);
|
||||
if((flags & PAGE_PRESENT) == 0) {
|
||||
if ((flags & PAGE_PRESENT) == 0) {
|
||||
aspace->translation_map.ops->unlock(&aspace->translation_map);
|
||||
continue;
|
||||
}
|
||||
|
||||
page = vm_lookup_page(pa / PAGE_SIZE);
|
||||
if(!page) {
|
||||
if (!page) {
|
||||
aspace->translation_map.ops->unlock(&aspace->translation_map);
|
||||
continue;
|
||||
}
|
||||
|
||||
// see if this page is busy, if it is lets forget it and move on
|
||||
if(page->state == PAGE_STATE_BUSY || page->state == PAGE_STATE_WIRED) {
|
||||
if (page->state == PAGE_STATE_BUSY || page->state == PAGE_STATE_WIRED) {
|
||||
aspace->translation_map.ops->unlock(&aspace->translation_map);
|
||||
continue;
|
||||
}
|
||||
|
||||
flags2 = 0;
|
||||
if(free_target > 0) {
|
||||
if (free_target > 0) {
|
||||
// look for a page we can steal
|
||||
if(!(flags & PAGE_ACCESSED) && page->state == PAGE_STATE_ACTIVE) {
|
||||
if (!(flags & PAGE_ACCESSED) && page->state == PAGE_STATE_ACTIVE) {
|
||||
// unmap the page
|
||||
aspace->translation_map.ops->unmap(&aspace->translation_map, va, va + PAGE_SIZE);
|
||||
|
||||
@@ -87,7 +96,7 @@ static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
|
||||
// decrement the ref count on the page. If we just unmapped it for the last time,
|
||||
// put the page on the inactive list
|
||||
if(atomic_add(&page->ref_count, -1) == 1) {
|
||||
if (atomic_add(&page->ref_count, -1) == 1) {
|
||||
vm_page_set_state(page, PAGE_STATE_INACTIVE);
|
||||
free_target--;
|
||||
}
|
||||
@@ -95,23 +104,23 @@ static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
}
|
||||
|
||||
// if the page is modified, but the state is active or inactive, put it on the modified list
|
||||
if(((flags & PAGE_MODIFIED) || (flags2 & PAGE_MODIFIED))
|
||||
if (((flags & PAGE_MODIFIED) || (flags2 & PAGE_MODIFIED))
|
||||
&& (page->state == PAGE_STATE_ACTIVE || page->state == PAGE_STATE_INACTIVE)) {
|
||||
vm_page_set_state(page, PAGE_STATE_MODIFIED);
|
||||
}
|
||||
|
||||
aspace->translation_map.ops->unlock(&aspace->translation_map);
|
||||
if(--quantum == 0)
|
||||
if (--quantum == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(®ion->cache_ref->lock);
|
||||
// move to the next region, wrapping around and stopping if we get back to the first region
|
||||
region = region->aspace_next ? region->aspace_next : aspace->virtual_map.region_list;
|
||||
if(region == first_region)
|
||||
if (region == first_region)
|
||||
break;
|
||||
|
||||
if(quantum == 0)
|
||||
if (quantum == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -121,6 +130,7 @@ static void scan_pages(vm_address_space *aspace, addr free_target)
|
||||
// dprintf("exiting scan_pages\n");
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
page_daemon(void *unused)
|
||||
{
|
||||
@@ -135,31 +145,31 @@ page_daemon(void *unused)
|
||||
dprintf("page daemon starting\n");
|
||||
(void)unused;
|
||||
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
snooze(PAGE_DAEMON_INTERVAL);
|
||||
|
||||
// scan through all of the address spaces
|
||||
vm_aspace_walk_start(&i);
|
||||
aspace = vm_aspace_walk_next(&i);
|
||||
while(aspace) {
|
||||
while (aspace) {
|
||||
mapped_size = aspace->translation_map.ops->get_mapped_size(&aspace->translation_map);
|
||||
|
||||
// dprintf("page_daemon: looking at aspace 0x%x, id 0x%x, mapped size %d\n", aspace, aspace->id, mapped_size);
|
||||
|
||||
now = system_time();
|
||||
if(now - aspace->last_working_set_adjust > WORKING_SET_ADJUST_INTERVAL) {
|
||||
if (now - aspace->last_working_set_adjust > WORKING_SET_ADJUST_INTERVAL) {
|
||||
faults_per_second = (aspace->fault_count * 1000000) / (now - aspace->last_working_set_adjust);
|
||||
// dprintf(" faults_per_second = %d\n", faults_per_second);
|
||||
aspace->last_working_set_adjust = now;
|
||||
aspace->fault_count = 0;
|
||||
|
||||
if(faults_per_second > MAX_FAULTS_PER_SECOND
|
||||
if (faults_per_second > MAX_FAULTS_PER_SECOND
|
||||
&& mapped_size >= aspace->working_set_size
|
||||
&& aspace->working_set_size < aspace->max_working_set) {
|
||||
|
||||
aspace->working_set_size += WORKING_SET_INCREMENT;
|
||||
// dprintf(" new working set size = %d\n", aspace->working_set_size);
|
||||
} else if(faults_per_second < MIN_FAULTS_PER_SECOND
|
||||
} else if (faults_per_second < MIN_FAULTS_PER_SECOND
|
||||
&& mapped_size <= aspace->working_set_size
|
||||
&& aspace->working_set_size > aspace->min_working_set) {
|
||||
|
||||
@@ -169,14 +179,14 @@ page_daemon(void *unused)
|
||||
}
|
||||
|
||||
// decide if we need to enter or leave the trimming cycle
|
||||
if(!trimming_cycle && vm_page_num_free_pages() < free_memory_low_water)
|
||||
if (!trimming_cycle && vm_page_num_free_pages() < free_memory_low_water)
|
||||
trimming_cycle = true;
|
||||
else if(trimming_cycle && vm_page_num_free_pages() > free_memory_high_water)
|
||||
else if (trimming_cycle && vm_page_num_free_pages() > free_memory_high_water)
|
||||
trimming_cycle = false;
|
||||
|
||||
// scan some pages, trying to free some if needed
|
||||
free_memory_target = 0;
|
||||
if(trimming_cycle && mapped_size > aspace->working_set_size)
|
||||
if (trimming_cycle && mapped_size > aspace->working_set_size)
|
||||
free_memory_target = mapped_size - aspace->working_set_size;
|
||||
|
||||
scan_pages(aspace, free_memory_target);
|
||||
|
||||
Reference in New Issue
Block a user