From b9d74a6b885c2c4ca35a7de2174b282886c5d852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 10 Oct 2004 17:21:38 +0000 Subject: [PATCH] Added vm_delete_aspace() again - unlike before, it now also puts the last reference to the address space, so that the calling team deletion function doesn't have to do this. delete_address_space() doesn't have to delete any areas anymore, since at the point it's called, there is no area anymore, anyway: each area holds a reference to the address space. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9276 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/core/vm/vm_address_space.c | 41 +++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/kernel/core/vm/vm_address_space.c b/src/kernel/core/vm/vm_address_space.c index 7fc8a2a6e8..8eb29d8e24 100644 --- a/src/kernel/core/vm/vm_address_space.c +++ b/src/kernel/core/vm/vm_address_space.c @@ -165,10 +165,17 @@ 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. + */ + static void delete_address_space(vm_address_space *aspace) { - TRACE(("vm_delete_aspace: called on aspace 0x%lx\n", aspace->id)); + TRACE(("delete_address_space: called on aspace 0x%lx\n", aspace->id)); + + if (aspace == kernel_aspace) + 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 @@ -176,8 +183,6 @@ delete_address_space(vm_address_space *aspace) aspace->state = VM_ASPACE_STATE_DELETION; - vm_delete_areas(aspace); - (*aspace->translation_map.ops->destroy)(&aspace->translation_map); free(aspace->name); @@ -244,25 +249,37 @@ vm_get_current_user_aspace_id(void) void vm_put_aspace(vm_address_space *aspace) { -// vm_region *region; - bool removeit = false; + bool remove = false; acquire_sem_etc(aspace_hash_sem, WRITE_COUNT, 0, 0); if (atomic_add(&aspace->ref_count, -1) == 1) { hash_remove(aspace_table, aspace); - removeit = true; + remove = true; } release_sem_etc(aspace_hash_sem, WRITE_COUNT, 0); - if (!removeit) - return; + if (remove) + delete_address_space(aspace); +} - TRACE(("vm_put_aspace: reached zero ref, deleting aspace\n")); - if (aspace == kernel_aspace) - panic("vm_put_aspace: tried to delete the kernel aspace!\n"); +/** 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. + */ - delete_address_space(aspace); +void +vm_delete_aspace(vm_address_space *aspace) +{ + acquire_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0, 0); + aspace->state = VM_ASPACE_STATE_DELETION; + release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0); + + vm_delete_areas(aspace); + vm_put_aspace(aspace); }