Author: bonefish Date: 2009-12-02 20:55:59 +0100 (Wed, 02 Dec 2009) New Revision: 34450 Changeset: http://dev.haiku-os.org/changeset/34450/haiku Added: haiku/trunk/headers/private/kernel/vm/VMArea.h haiku/trunk/src/system/kernel/vm/VMArea.cpp Modified: haiku/trunk/headers/private/kernel/vm/vm_types.h haiku/trunk/src/system/kernel/arch/x86/arch_debug.cpp haiku/trunk/src/system/kernel/arch/x86/arch_vm.cpp haiku/trunk/src/system/kernel/elf.cpp haiku/trunk/src/system/kernel/vm/Jamfile haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp haiku/trunk/src/system/kernel/vm/VMCache.cpp haiku/trunk/src/system/kernel/vm/vm.cpp haiku/trunk/src/system/kernel/vm/vm_page.cpp Log: Created VMArea.{h,cpp} and moved VMArea and the global area hash table (new class VMAreaHash) there. Added: haiku/trunk/headers/private/kernel/vm/VMArea.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/VMArea.h (rev 0) +++ haiku/trunk/headers/private/kernel/vm/VMArea.h 2009-12-02 19:55:59 UTC (rev 34450) @@ -0,0 +1,105 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_VM_VM_AREA_H +#define _KERNEL_VM_VM_AREA_H + + +#include <lock.h> +#include <util/OpenHashTable.h> +#include <vm/vm_types.h> + + +struct VMAddressSpace; +struct VMCache; + + +struct VMArea { + char* name; + area_id id; + addr_t base; + addr_t size; + uint32 protection; + uint16 wiring; + uint16 memory_type; + + VMCache* cache; + vint32 no_cache_change; + off_t cache_offset; + uint32 cache_type; + VMAreaMappings mappings; + uint8* page_protections; + + struct VMAddressSpace* address_space; + struct VMArea* address_space_next; + struct VMArea* cache_next; + struct VMArea* cache_prev; + struct VMArea* hash_next; + + bool ContainsAddress(addr_t address) const + { return address >= base && address <= base + (size - 1); } +}; + + +struct VMAreaHashDefinition { + typedef area_id KeyType; + typedef VMArea ValueType; + + size_t HashKey(area_id key) const + { + return key; + } + + size_t Hash(const VMArea* value) const + { + return HashKey(value->id); + } + + bool Compare(area_id key, const VMArea* value) const + { + return value->id == key; + } + + VMArea*& GetLink(VMArea* value) const + { + return value->hash_next; + } +}; + +typedef BOpenHashTable<VMAreaHashDefinition> VMAreaHashTable; + + +struct VMAreaHash { + static status_t Init(); + + static status_t ReadLock() + { return rw_lock_read_lock(&sLock); } + static void ReadUnlock() + { rw_lock_read_unlock(&sLock); } + static status_t WriteLock() + { return rw_lock_write_lock(&sLock); } + static void WriteUnlock() + { rw_lock_write_unlock(&sLock); } + + static VMArea* LookupLocked(area_id id) + { return sTable.Lookup(id); } + static VMArea* Lookup(area_id id); + static area_id Find(const char* name); + static void Insert(VMArea* area); + static void Remove(VMArea* area); + + static VMAreaHashTable::Iterator GetIterator() + { return sTable.GetIterator(); } + +private: + static rw_lock sLock; + static VMAreaHashTable sTable; +}; + + +#endif // _KERNEL_VM_VM_AREA_H Modified: haiku/trunk/headers/private/kernel/vm/vm_types.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/vm_types.h 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/headers/private/kernel/vm/vm_types.h 2009-12-02 19:55:59 UTC (rev 34450) @@ -287,31 +287,4 @@ }; -struct VMArea { - char* name; - area_id id; - addr_t base; - addr_t size; - uint32 protection; - uint16 wiring; - uint16 memory_type; - - VMCache* cache; - vint32 no_cache_change; - off_t cache_offset; - uint32 cache_type; - VMAreaMappings mappings; - uint8* page_protections; - - struct VMAddressSpace* address_space; - struct VMArea* address_space_next; - struct VMArea* cache_next; - struct VMArea* cache_prev; - struct VMArea* hash_next; - - bool ContainsAddress(addr_t address) const - { return address >= base && address <= base + (size - 1); } -}; - - #endif // _KERNEL_VM_VM_TYPES_H Modified: haiku/trunk/src/system/kernel/arch/x86/arch_debug.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/arch_debug.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/arch/x86/arch_debug.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -23,6 +23,7 @@ #include <vm/vm.h> #include <vm/vm_types.h> #include <vm/VMAddressSpace.h> +#include <vm/VMArea.h> #include <arch_cpu.h> Modified: haiku/trunk/src/system/kernel/arch/x86/arch_vm.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/arch_vm.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/arch/x86/arch_vm.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -20,6 +20,7 @@ #include <vm/vm_page.h> #include <vm/vm_priv.h> #include <vm/VMAddressSpace.h> +#include <vm/VMArea.h> #include <arch/vm.h> #include <arch/int.h> Modified: haiku/trunk/src/system/kernel/elf.cpp =================================================================== --- haiku/trunk/src/system/kernel/elf.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/elf.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -34,6 +34,7 @@ #include <vm/vm.h> #include <vm/vm_types.h> #include <vm/VMAddressSpace.h> +#include <vm/VMArea.h> #include <arch/cpu.h> #include <arch/elf.h> Modified: haiku/trunk/src/system/kernel/vm/Jamfile =================================================================== --- haiku/trunk/src/system/kernel/vm/Jamfile 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/vm/Jamfile 2009-12-02 19:55:59 UTC (rev 34450) @@ -11,6 +11,7 @@ VMAddressSpace.cpp VMAnonymousCache.cpp VMAnonymousNoSwapCache.cpp + VMArea.cpp VMCache.cpp VMDeviceCache.cpp VMNullCache.cpp Modified: haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -20,6 +20,7 @@ #include <thread.h> #include <vm/vm.h> #include <vm/vm_priv.h> +#include <vm/VMArea.h> //#define TRACE_VM Added: haiku/trunk/src/system/kernel/vm/VMArea.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMArea.cpp (rev 0) +++ haiku/trunk/src/system/kernel/vm/VMArea.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -0,0 +1,78 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include <vm/VMArea.h> + +#include <vm/vm_priv.h> + + +#define AREA_HASH_TABLE_SIZE 1024 + + +rw_lock VMAreaHash::sLock = RW_LOCK_INITIALIZER("area hash"); +VMAreaHashTable VMAreaHash::sTable; + + +/*static*/ status_t +VMAreaHash::Init() +{ + return sTable.Init(AREA_HASH_TABLE_SIZE); +} + + +/*static*/ VMArea* +VMAreaHash::Lookup(area_id id) +{ + ReadLock(); + VMArea* area = LookupLocked(id); + ReadUnlock(); + return area; +} + + +/*static*/ area_id +VMAreaHash::Find(const char* name) +{ + ReadLock(); + + area_id id = B_NAME_NOT_FOUND; + + // TODO: Iterating through the whole table can be very slow and the whole + // time we're holding the lock! Use a second hash table! + + for (VMAreaHashTable::Iterator it = sTable.GetIterator(); + VMArea* area = it.Next();) { + if (area->id == RESERVED_AREA_ID) + continue; + + if (strcmp(area->name, name) == 0) { + id = area->id; + break; + } + } + + ReadUnlock(); + + return id; +} + + +/*static*/ void +VMAreaHash::Insert(VMArea* area) +{ + WriteLock(); + sTable.Insert(area); + WriteUnlock(); +} + + +/*static*/ void +VMAreaHash::Remove(VMArea* area) +{ + WriteLock(); + sTable.Remove(area); + WriteUnlock(); +} Modified: haiku/trunk/src/system/kernel/vm/VMCache.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMCache.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/vm/VMCache.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -27,6 +27,7 @@ #include <vm/vm_page.h> #include <vm/vm_priv.h> #include <vm/vm_types.h> +#include <vm/VMArea.h> //#define TRACE_VM_CACHE Modified: haiku/trunk/src/system/kernel/vm/vm.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/vm.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/vm/vm.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -47,6 +47,7 @@ #include <vm/vm_page.h> #include <vm/vm_priv.h> #include <vm/VMAddressSpace.h> +#include <vm/VMArea.h> #include <vm/VMCache.h> #include "VMAnonymousCache.h" @@ -190,10 +191,7 @@ }; -#define AREA_HASH_TABLE_SIZE 1024 static area_id sNextAreaID = 1; -static hash_table* sAreaHash; -static rw_lock sAreaHashLock = RW_LOCK_INITIALIZER("area hash"); static mutex sMappingLock = MUTEX_INITIALIZER("page mappings"); static mutex sAreaCacheLock = MUTEX_INITIALIZER("area->cache"); @@ -316,9 +314,7 @@ fSpace->ReadLock(); - rw_lock_read_lock(&sAreaHashLock); - area = (VMArea*)hash_lookup(sAreaHash, &areaID); - rw_lock_read_unlock(&sAreaHashLock); + area = VMAreaHash::Lookup(areaID); if (area == NULL || area->address_space != fSpace) { fSpace->ReadUnlock(); @@ -414,9 +410,7 @@ fSpace->WriteLock(); - rw_lock_read_lock(&sAreaHashLock); - area = (VMArea*)hash_lookup(sAreaHash, &areaID); - rw_lock_read_unlock(&sAreaHashLock); + area = VMAreaHash::Lookup(areaID); if (area == NULL || area->address_space != fSpace) { fSpace->WriteUnlock(); @@ -432,9 +426,9 @@ AddressSpaceWriteLocker::SetFromArea(team_id team, area_id areaID, bool allowKernel, VMArea*& area) { - rw_lock_read_lock(&sAreaHashLock); + VMAreaHash::ReadLock(); - area = (VMArea*)hash_lookup(sAreaHash, &areaID); + area = VMAreaHash::LookupLocked(areaID); if (area != NULL && (area->address_space->ID() == team || (allowKernel && team == VMAddressSpace::KernelID()))) { @@ -442,7 +436,7 @@ fSpace->Get(); } - rw_lock_read_unlock(&sAreaHashLock); + VMAreaHash::ReadUnlock(); if (fSpace == NULL) return B_BAD_VALUE; @@ -452,9 +446,7 @@ fSpace->WriteLock(); - rw_lock_read_lock(&sAreaHashLock); - area = (VMArea*)hash_lookup(sAreaHash, &areaID); - rw_lock_read_unlock(&sAreaHashLock); + area = VMAreaHash::Lookup(areaID); if (area == NULL) { fSpace->WriteUnlock(); @@ -722,9 +714,7 @@ // lock the cache again and check whether anything has changed // check whether the area is gone in the meantime - rw_lock_read_lock(&sAreaHashLock); - area = (VMArea*)hash_lookup(sAreaHash, &areaID); - rw_lock_read_unlock(&sAreaHashLock); + area = VMAreaHash::Lookup(areaID); if (area == NULL) { Unlock(); @@ -892,46 +882,20 @@ // #pragma mark - -static int -area_compare(void* _area, const void* key) -{ - VMArea* area = (VMArea*)_area; - const area_id* id = (const area_id*)key; - - if (area->id == *id) - return 0; - - return -1; -} - - -static uint32 -area_hash(void* _area, const void* key, uint32 range) -{ - VMArea* area = (VMArea*)_area; - const area_id* id = (const area_id*)key; - - if (area != NULL) - return area->id % range; - - return (uint32)*id % range; -} - - static VMAddressSpace* get_address_space_by_area_id(area_id id) { VMAddressSpace* addressSpace = NULL; - rw_lock_read_lock(&sAreaHashLock); + VMAreaHash::ReadLock(); - VMArea* area = (VMArea*)hash_lookup(sAreaHash, &id); + VMArea* area = VMAreaHash::LookupLocked(id); if (area != NULL) { addressSpace = area->address_space; addressSpace->Get(); } - rw_lock_read_unlock(&sAreaHashLock); + VMAreaHash::ReadUnlock(); return addressSpace; } @@ -941,13 +905,13 @@ static VMArea* lookup_area(VMAddressSpace* addressSpace, area_id id) { - rw_lock_read_lock(&sAreaHashLock); + VMAreaHash::ReadLock(); - VMArea* area = (VMArea*)hash_lookup(sAreaHash, &id); + VMArea* area = VMAreaHash::LookupLocked(id); if (area != NULL && area->address_space != addressSpace) area = NULL; - rw_lock_read_unlock(&sAreaHashLock); + VMAreaHash::ReadUnlock(); return area; } @@ -1696,9 +1660,7 @@ cache->Unlock(); // insert the area in the global area hash table - rw_lock_write_lock(&sAreaHashLock); - hash_insert(sAreaHash, area); - rw_lock_write_unlock(&sAreaHashLock); + VMAreaHash::Insert(area); // grab a ref to the address space (the area holds this) addressSpace->Get(); @@ -2746,9 +2708,7 @@ static void delete_area(VMAddressSpace* addressSpace, VMArea* area) { - rw_lock_write_lock(&sAreaHashLock); - hash_remove(sAreaHash, area); - rw_lock_write_unlock(&sAreaHashLock); + VMAreaHash::Remove(area); // At this point the area is removed from the global hash table, but // still exists in the area list. @@ -3974,10 +3934,9 @@ dump_area_struct((struct VMArea*)num, mappings); } else { // walk through the area list, looking for the arguments as a name - struct hash_iterator iter; - hash_open(sAreaHash, &iter); - while ((area = (VMArea*)hash_next(sAreaHash, &iter)) != NULL) { + VMAreaHashTable::Iterator it = VMAreaHash::GetIterator(); + while ((area = it.Next()) != NULL) { if (((mode & 4) != 0 && area->name != NULL && !strcmp(argv[index], area->name)) || (num != 0 && (((mode & 1) != 0 && (addr_t)area->id == num) @@ -4000,7 +3959,6 @@ dump_area_list(int argc, char** argv) { VMArea* area; - struct hash_iterator iter; const char* name = NULL; int32 id = 0; @@ -4012,8 +3970,8 @@ kprintf("addr id base\t\tsize protect lock name\n"); - hash_open(sAreaHash, &iter); - while ((area = (VMArea*)hash_next(sAreaHash, &iter)) != NULL) { + VMAreaHashTable::Iterator it = VMAreaHash::GetIterator(); + while ((area = it.Next()) != NULL) { if ((id != 0 && area->address_space->ID() != id) || (name != NULL && strstr(area->name, name) == NULL)) continue; @@ -4022,7 +3980,6 @@ (void*)area->base, (void*)area->size, area->protection, area->wiring, area->name); } - hash_close(sAreaHash, &iter, false); return 0; } @@ -4456,12 +4413,9 @@ vm_cache_init(args); { - VMArea* area; - sAreaHash = hash_init(AREA_HASH_TABLE_SIZE, - (addr_t)&area->hash_next - (addr_t)area, - &area_compare, &area_hash); - if (sAreaHash == NULL) - panic("vm_init: error creating aspace hash table\n"); + status_t error = VMAreaHash::Init(); + if (error != B_OK) + panic("vm_init: error initializing area hash table\n"); } VMAddressSpace::Init(); @@ -5898,26 +5852,7 @@ area_id find_area(const char* name) { - rw_lock_read_lock(&sAreaHashLock); - struct hash_iterator iterator; - hash_open(sAreaHash, &iterator); - - VMArea* area; - area_id id = B_NAME_NOT_FOUND; - while ((area = (VMArea*)hash_next(sAreaHash, &iterator)) != NULL) { - if (area->id == RESERVED_AREA_ID) - continue; - - if (!strcmp(area->name, name)) { - id = area->id; - break; - } - } - - hash_close(sAreaHash, &iterator, false); - rw_lock_read_unlock(&sAreaHashLock); - - return id; + return VMAreaHash::Find(name); } Modified: haiku/trunk/src/system/kernel/vm/vm_page.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/vm_page.cpp 2009-12-02 18:05:10 UTC (rev 34449) +++ haiku/trunk/src/system/kernel/vm/vm_page.cpp 2009-12-02 19:55:59 UTC (rev 34450) @@ -31,6 +31,7 @@ #include <vm/vm_priv.h> #include <vm/vm_page.h> #include <vm/VMAddressSpace.h> +#include <vm/VMArea.h> #include <vm/VMCache.h> #include "VMAnonymousCache.h"