* 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
|
// free team resources
|
||||||
|
|
||||||
vm_delete_address_space(team->address_space);
|
vfs_free_io_context(team->io_context);
|
||||||
delete_owned_ports(teamID);
|
delete_owned_ports(teamID);
|
||||||
sem_delete_owned_sems(teamID);
|
sem_delete_owned_sems(teamID);
|
||||||
remove_images(team);
|
remove_images(team);
|
||||||
vfs_free_io_context(team->io_context);
|
vm_delete_address_space(team->address_space);
|
||||||
|
|
||||||
delete_team_struct(team);
|
delete_team_struct(team);
|
||||||
|
|
||||||
|
|||||||
@@ -741,6 +741,7 @@ find_reserved_area(vm_address_space *addressSpace, addr_t start,
|
|||||||
if (reserved == NULL)
|
if (reserved == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
atomic_add(&addressSpace->ref_count, 1);
|
||||||
reserved->address_space_next = next->address_space_next;
|
reserved->address_space_next = next->address_space_next;
|
||||||
area->address_space_next = reserved;
|
area->address_space_next = reserved;
|
||||||
next->address_space_next = area;
|
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;
|
area->cache_offset = area->base;
|
||||||
// we cache the original base address here
|
// we cache the original base address here
|
||||||
|
|
||||||
|
atomic_add(&locker.AddressSpace()->ref_count, 1);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1872,10 +1874,7 @@ delete_area(vm_address_space *addressSpace, vm_area *area)
|
|||||||
|
|
||||||
arch_vm_unset_memory_type(area);
|
arch_vm_unset_memory_type(area);
|
||||||
remove_area_from_address_space(addressSpace, area);
|
remove_area_from_address_space(addressSpace, area);
|
||||||
// TODO: the following line fixes an address space leak - however,
|
vm_put_address_space(addressSpace);
|
||||||
// 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_cache_remove_area(area->cache, area);
|
vm_cache_remove_area(area->cache, area);
|
||||||
vm_cache_release_ref(area->cache);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//#include <OS.h>
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include <vm.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
|
/*! When this function is called, all references to this address space
|
||||||
* have been released, so it's safe to remove it.
|
have been released, so it's safe to remove it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
delete_address_space(vm_address_space *addressSpace)
|
delete_address_space(vm_address_space *addressSpace)
|
||||||
{
|
{
|
||||||
@@ -144,14 +142,8 @@ delete_address_space(vm_address_space *addressSpace)
|
|||||||
if (addressSpace == sKernelAddressSpace)
|
if (addressSpace == sKernelAddressSpace)
|
||||||
panic("tried to delete the kernel aspace!\n");
|
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);
|
acquire_sem_etc(addressSpace->sem, WRITE_COUNT, 0, 0);
|
||||||
|
|
||||||
addressSpace->state = VM_ASPACE_STATE_DELETION;
|
|
||||||
|
|
||||||
(*addressSpace->translation_map.ops->destroy)(&addressSpace->translation_map);
|
(*addressSpace->translation_map.ops->destroy)(&addressSpace->translation_map);
|
||||||
|
|
||||||
delete_sem(addressSpace->sem);
|
delete_sem(addressSpace->sem);
|
||||||
free(addressSpace);
|
free(addressSpace);
|
||||||
}
|
}
|
||||||
@@ -161,17 +153,17 @@ delete_address_space(vm_address_space *addressSpace)
|
|||||||
|
|
||||||
|
|
||||||
vm_address_space *
|
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);
|
acquire_sem_etc(sAddressSpaceHashSem, READ_COUNT, 0, 0);
|
||||||
aspace = hash_lookup(sAddressSpaceTable, &aid);
|
addressSpace = hash_lookup(sAddressSpaceTable, &id);
|
||||||
if (aspace)
|
if (addressSpace)
|
||||||
atomic_add(&aspace->ref_count, 1);
|
atomic_add(&addressSpace->ref_count, 1);
|
||||||
release_sem_etc(sAddressSpaceHashSem, READ_COUNT, 0);
|
release_sem_etc(sAddressSpaceHashSem, READ_COUNT, 0);
|
||||||
|
|
||||||
return aspace;
|
return addressSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -228,30 +220,29 @@ vm_current_user_address_space_id(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_put_address_space(vm_address_space *aspace)
|
vm_put_address_space(vm_address_space *addressSpace)
|
||||||
{
|
{
|
||||||
bool remove = false;
|
bool remove = false;
|
||||||
|
|
||||||
acquire_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0, 0);
|
acquire_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0, 0);
|
||||||
if (atomic_add(&aspace->ref_count, -1) == 1) {
|
if (atomic_add(&addressSpace->ref_count, -1) == 1) {
|
||||||
hash_remove(sAddressSpaceTable, aspace);
|
hash_remove(sAddressSpaceTable, addressSpace);
|
||||||
remove = true;
|
remove = true;
|
||||||
}
|
}
|
||||||
release_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0);
|
release_sem_etc(sAddressSpaceHashSem, WRITE_COUNT, 0);
|
||||||
|
|
||||||
if (remove)
|
if (remove)
|
||||||
delete_address_space(aspace);
|
delete_address_space(addressSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Deletes all areas in the specified address space, and the address
|
/*! Deletes all areas in the specified address space, and the address
|
||||||
* space by decreasing all reference counters. It also marks the
|
space by decreasing all reference counters. It also marks the
|
||||||
* address space of being in deletion state, so that no more areas
|
address space of being in deletion state, so that no more areas
|
||||||
* can be created in it.
|
can be created in it.
|
||||||
* After this, the address space is not operational anymore, but might
|
After this, the address space is not operational anymore, but might
|
||||||
* still be in memory until the last reference has been released.
|
still be in memory until the last reference has been released.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_delete_address_space(vm_address_space *addressSpace)
|
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->state = VM_ASPACE_STATE_NORMAL;
|
||||||
addressSpace->fault_count = 0;
|
addressSpace->fault_count = 0;
|
||||||
addressSpace->scan_va = base;
|
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->max_working_set = DEFAULT_MAX_WORKING_SET;
|
||||||
addressSpace->min_working_set = DEFAULT_MIN_WORKING_SET;
|
addressSpace->min_working_set = DEFAULT_MIN_WORKING_SET;
|
||||||
addressSpace->last_working_set_adjust = system_time();
|
addressSpace->last_working_set_adjust = system_time();
|
||||||
|
|
||||||
// initialize the corresponding translation map
|
// 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) {
|
if (status < B_OK) {
|
||||||
free(addressSpace);
|
free(addressSpace);
|
||||||
return status;
|
return status;
|
||||||
@@ -349,8 +342,9 @@ vm_address_space_init(void)
|
|||||||
// create the area and address space hash tables
|
// create the area and address space hash tables
|
||||||
{
|
{
|
||||||
vm_address_space *aspace;
|
vm_address_space *aspace;
|
||||||
sAddressSpaceTable = hash_init(ASPACE_HASH_TABLE_SIZE, (addr_t)&aspace->hash_next - (addr_t)aspace,
|
sAddressSpaceTable = hash_init(ASPACE_HASH_TABLE_SIZE,
|
||||||
&aspace_compare, &aspace_hash);
|
(addr_t)&aspace->hash_next - (addr_t)aspace, &aspace_compare,
|
||||||
|
&aspace_hash);
|
||||||
if (sAddressSpaceTable == NULL)
|
if (sAddressSpaceTable == NULL)
|
||||||
panic("vm_init: error creating aspace hash table\n");
|
panic("vm_init: error creating aspace hash table\n");
|
||||||
}
|
}
|
||||||
@@ -362,8 +356,10 @@ vm_address_space_init(void)
|
|||||||
true, &sKernelAddressSpace) != B_OK)
|
true, &sKernelAddressSpace) != B_OK)
|
||||||
panic("vm_init: error creating kernel address space!\n");
|
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("aspaces", &dump_aspace_list,
|
||||||
add_debugger_command("aspace", &dump_aspace, "Dump info about a particular address space");
|
"Dump a list of all address spaces");
|
||||||
|
add_debugger_command("aspace", &dump_aspace,
|
||||||
|
"Dump info about a particular address space");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -372,11 +368,13 @@ vm_address_space_init(void)
|
|||||||
status_t
|
status_t
|
||||||
vm_address_space_init_post_sem(void)
|
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)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = sKernelAddressSpace->sem = create_sem(WRITE_COUNT, "kernel_aspacelock");
|
status = sKernelAddressSpace->sem = create_sem(WRITE_COUNT,
|
||||||
|
"kernel_aspacelock");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user