* creating (or dividing) reserved areas did not acquire a ref to an address
space - but they were released upon deletion. It's probably not really needed, but now all reserved areas also grab a reference to their address space. * Rearranged team tear down to be a bit more sane: the I/O context is removed first (where semaphores/areas/ports/whatever might still be used), and the address space is deleted last. * delete_area() can now remove its address space reference again (due to the two changes above), and therefore fixes bug #1374. * cleaned up vm_address_space.c a bit (no functional change there, though). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22130 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1781,11 +1781,11 @@ team_delete_team(struct team *team)
|
||||
|
||||
// free team resources
|
||||
|
||||
vm_delete_address_space(team->address_space);
|
||||
vfs_free_io_context(team->io_context);
|
||||
delete_owned_ports(teamID);
|
||||
sem_delete_owned_sems(teamID);
|
||||
remove_images(team);
|
||||
vfs_free_io_context(team->io_context);
|
||||
vm_delete_address_space(team->address_space);
|
||||
|
||||
delete_team_struct(team);
|
||||
|
||||
|
||||
@@ -741,6 +741,7 @@ find_reserved_area(vm_address_space *addressSpace, addr_t start,
|
||||
if (reserved == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
atomic_add(&addressSpace->ref_count, 1);
|
||||
reserved->address_space_next = next->address_space_next;
|
||||
area->address_space_next = reserved;
|
||||
next->address_space_next = area;
|
||||
@@ -1185,6 +1186,7 @@ vm_reserve_address_range(team_id team, void **_address, uint32 addressSpec,
|
||||
area->cache_offset = area->base;
|
||||
// we cache the original base address here
|
||||
|
||||
atomic_add(&locker.AddressSpace()->ref_count, 1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -1872,10 +1874,7 @@ delete_area(vm_address_space *addressSpace, vm_area *area)
|
||||
|
||||
arch_vm_unset_memory_type(area);
|
||||
remove_area_from_address_space(addressSpace, area);
|
||||
// TODO: the following line fixes an address space leak - however,
|
||||
// there seems to be something wrong with the order in which teams
|
||||
// are torn down, and the first shell command hangs on a pipe then
|
||||
//vm_put_address_space(addressSpace);
|
||||
vm_put_address_space(addressSpace);
|
||||
|
||||
vm_cache_remove_area(area->cache, area);
|
||||
vm_cache_release_ref(area->cache);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
|
||||
//#include <OS.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <vm.h>
|
||||
@@ -132,10 +131,9 @@ aspace_hash(void *_a, const void *key, uint32 range)
|
||||
}
|
||||
|
||||
|
||||
/** When this function is called, all references to this address space
|
||||
* have been released, so it's safe to remove it.
|
||||
*/
|
||||
|
||||
/*! When this function is called, all references to this address space
|
||||
have been released, so it's safe to remove it.
|
||||
*/
|
||||
static void
|
||||
delete_address_space(vm_address_space *addressSpace)
|
||||
{
|
||||
@@ -144,14 +142,8 @@ delete_address_space(vm_address_space *addressSpace)
|
||||
if (addressSpace == sKernelAddressSpace)
|
||||
panic("tried to delete the kernel aspace!\n");
|
||||
|
||||
// put this aspace in the deletion state
|
||||
// this guarantees that no one else will add regions to the list
|
||||
acquire_sem_etc(addressSpace->sem, WRITE_COUNT, 0, 0);
|
||||
|
||||
addressSpace->state = VM_ASPACE_STATE_DELETION;
|
||||
|
||||
(*addressSpace->translation_map.ops->destroy)(&addressSpace->translation_map);
|
||||
|
||||
delete_sem(addressSpace->sem);
|
||||
free(addressSpace);
|
||||
}
|
||||
@@ -161,17 +153,17 @@ delete_address_space(vm_address_space *addressSpace)
|
||||
|
||||
|
||||
vm_address_space *
|
||||
vm_get_address_space_by_id(team_id aid)
|
||||
vm_get_address_space_by_id(team_id id)
|
||||
{
|
||||
vm_address_space *aspace;
|
||||
vm_address_space *addressSpace;
|
||||
|
||||
acquire_sem_etc(sAddressSpaceHashSem, READ_COUNT, 0, 0);
|
||||
aspace = hash_lookup(sAddressSpaceTable, &aid);
|
||||
if (aspace)
|
||||
atomic_add(&aspace->ref_count, 1);
|
||||
addressSpace = hash_lookup(sAddressSpaceTable, &id);
|
||||
if (addressSpace)
|
||||
atomic_add(&addressSpace->ref_count, 1);
|
||||
release_sem_etc(sAddressSpaceHashSem, READ_COUNT, 0);
|
||||
|
||||
return aspace;
|
||||
return addressSpace;
|
||||
}
|
||||
|
||||
|
||||
@@ -228,30 +220,29 @@ vm_current_user_address_space_id(void)
|
||||
|
||||
|
||||
void
|
||||
vm_put_address_space(vm_address_space *aspace)
|
||||
vm_put_address_space(vm_address_space *addressSpace)
|
||||
{
|
||||
bool remove = false;
|
||||
|
||||
acquire_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0, 0);
|
||||
if (atomic_add(&aspace->ref_count, -1) == 1) {
|
||||
hash_remove(sAddressSpaceTable, aspace);
|
||||
if (atomic_add(&addressSpace->ref_count, -1) == 1) {
|
||||
hash_remove(sAddressSpaceTable, addressSpace);
|
||||
remove = true;
|
||||
}
|
||||
release_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0);
|
||||
|
||||
if (remove)
|
||||
delete_address_space(aspace);
|
||||
delete_address_space(addressSpace);
|
||||
}
|
||||
|
||||
|
||||
/** Deletes all areas in the specified address space, and the address
|
||||
* space by decreasing all reference counters. It also marks the
|
||||
* address space of being in deletion state, so that no more areas
|
||||
* can be created in it.
|
||||
* After this, the address space is not operational anymore, but might
|
||||
* still be in memory until the last reference has been released.
|
||||
*/
|
||||
|
||||
/*! Deletes all areas in the specified address space, and the address
|
||||
space by decreasing all reference counters. It also marks the
|
||||
address space of being in deletion state, so that no more areas
|
||||
can be created in it.
|
||||
After this, the address space is not operational anymore, but might
|
||||
still be in memory until the last reference has been released.
|
||||
*/
|
||||
void
|
||||
vm_delete_address_space(vm_address_space *addressSpace)
|
||||
{
|
||||
@@ -298,13 +289,15 @@ vm_create_address_space(team_id id, addr_t base, addr_t size,
|
||||
addressSpace->state = VM_ASPACE_STATE_NORMAL;
|
||||
addressSpace->fault_count = 0;
|
||||
addressSpace->scan_va = base;
|
||||
addressSpace->working_set_size = kernel ? DEFAULT_KERNEL_WORKING_SET : DEFAULT_WORKING_SET;
|
||||
addressSpace->working_set_size = kernel
|
||||
? DEFAULT_KERNEL_WORKING_SET : DEFAULT_WORKING_SET;
|
||||
addressSpace->max_working_set = DEFAULT_MAX_WORKING_SET;
|
||||
addressSpace->min_working_set = DEFAULT_MIN_WORKING_SET;
|
||||
addressSpace->last_working_set_adjust = system_time();
|
||||
|
||||
// initialize the corresponding translation map
|
||||
status = arch_vm_translation_map_init_map(&addressSpace->translation_map, kernel);
|
||||
status = arch_vm_translation_map_init_map(&addressSpace->translation_map,
|
||||
kernel);
|
||||
if (status < B_OK) {
|
||||
free(addressSpace);
|
||||
return status;
|
||||
@@ -349,8 +342,9 @@ vm_address_space_init(void)
|
||||
// create the area and address space hash tables
|
||||
{
|
||||
vm_address_space *aspace;
|
||||
sAddressSpaceTable = hash_init(ASPACE_HASH_TABLE_SIZE, (addr_t)&aspace->hash_next - (addr_t)aspace,
|
||||
&aspace_compare, &aspace_hash);
|
||||
sAddressSpaceTable = hash_init(ASPACE_HASH_TABLE_SIZE,
|
||||
(addr_t)&aspace->hash_next - (addr_t)aspace, &aspace_compare,
|
||||
&aspace_hash);
|
||||
if (sAddressSpaceTable == NULL)
|
||||
panic("vm_init: error creating aspace hash table\n");
|
||||
}
|
||||
@@ -362,8 +356,10 @@ vm_address_space_init(void)
|
||||
true, &sKernelAddressSpace) != B_OK)
|
||||
panic("vm_init: error creating kernel address space!\n");
|
||||
|
||||
add_debugger_command("aspaces", &dump_aspace_list, "Dump a list of all address spaces");
|
||||
add_debugger_command("aspace", &dump_aspace, "Dump info about a particular address space");
|
||||
add_debugger_command("aspaces", &dump_aspace_list,
|
||||
"Dump a list of all address spaces");
|
||||
add_debugger_command("aspace", &dump_aspace,
|
||||
"Dump info about a particular address space");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -372,11 +368,13 @@ vm_address_space_init(void)
|
||||
status_t
|
||||
vm_address_space_init_post_sem(void)
|
||||
{
|
||||
status_t status = arch_vm_translation_map_init_kernel_map_post_sem(&sKernelAddressSpace->translation_map);
|
||||
status_t status = arch_vm_translation_map_init_kernel_map_post_sem(
|
||||
&sKernelAddressSpace->translation_map);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
status = sKernelAddressSpace->sem = create_sem(WRITE_COUNT, "kernel_aspacelock");
|
||||
status = sKernelAddressSpace->sem = create_sem(WRITE_COUNT,
|
||||
"kernel_aspacelock");
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user