From f34a1dd5d701373687b6f3f0e6e76bd2b1ae6007 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 2 Dec 2009 19:55:59 +0000 Subject: [PATCH] Created VMArea.{h,cpp} and moved VMArea and the global area hash table (new class VMAreaHash) there. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34450 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/vm/VMArea.h | 105 ++++++++++++++++++++ headers/private/kernel/vm/vm_types.h | 27 ------ src/system/kernel/arch/x86/arch_debug.cpp | 1 + src/system/kernel/arch/x86/arch_vm.cpp | 1 + src/system/kernel/elf.cpp | 1 + src/system/kernel/vm/Jamfile | 1 + src/system/kernel/vm/VMAddressSpace.cpp | 1 + src/system/kernel/vm/VMArea.cpp | 78 +++++++++++++++ src/system/kernel/vm/VMCache.cpp | 1 + src/system/kernel/vm/vm.cpp | 113 +++++----------------- src/system/kernel/vm/vm_page.cpp | 1 + 11 files changed, 214 insertions(+), 116 deletions(-) create mode 100644 headers/private/kernel/vm/VMArea.h create mode 100644 src/system/kernel/vm/VMArea.cpp diff --git a/headers/private/kernel/vm/VMArea.h b/headers/private/kernel/vm/VMArea.h new file mode 100644 index 0000000000..e7605ffeee --- /dev/null +++ b/headers/private/kernel/vm/VMArea.h @@ -0,0 +1,105 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * 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 +#include +#include + + +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 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 diff --git a/headers/private/kernel/vm/vm_types.h b/headers/private/kernel/vm/vm_types.h index d5ecab7964..b3abf4397f 100644 --- a/headers/private/kernel/vm/vm_types.h +++ b/headers/private/kernel/vm/vm_types.h @@ -287,31 +287,4 @@ public: }; -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 diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index 25ea7541c9..a62d1afbf8 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include diff --git a/src/system/kernel/arch/x86/arch_vm.cpp b/src/system/kernel/arch/x86/arch_vm.cpp index f1dae02257..5882b5019b 100644 --- a/src/system/kernel/arch/x86/arch_vm.cpp +++ b/src/system/kernel/arch/x86/arch_vm.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index dc1b9a4ff2..157ff45ab4 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/src/system/kernel/vm/Jamfile b/src/system/kernel/vm/Jamfile index 5866d12b62..90ec5c9a44 100644 --- a/src/system/kernel/vm/Jamfile +++ b/src/system/kernel/vm/Jamfile @@ -11,6 +11,7 @@ KernelMergeObject kernel_vm.o : VMAddressSpace.cpp VMAnonymousCache.cpp VMAnonymousNoSwapCache.cpp + VMArea.cpp VMCache.cpp VMDeviceCache.cpp VMNullCache.cpp diff --git a/src/system/kernel/vm/VMAddressSpace.cpp b/src/system/kernel/vm/VMAddressSpace.cpp index 7b23fb21b4..91d3f25abc 100644 --- a/src/system/kernel/vm/VMAddressSpace.cpp +++ b/src/system/kernel/vm/VMAddressSpace.cpp @@ -20,6 +20,7 @@ #include #include #include +#include //#define TRACE_VM diff --git a/src/system/kernel/vm/VMArea.cpp b/src/system/kernel/vm/VMArea.cpp new file mode 100644 index 0000000000..5ab2c84278 --- /dev/null +++ b/src/system/kernel/vm/VMArea.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +#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(); +} diff --git a/src/system/kernel/vm/VMCache.cpp b/src/system/kernel/vm/VMCache.cpp index 7ad6fb227a..1ae013c4a9 100644 --- a/src/system/kernel/vm/VMCache.cpp +++ b/src/system/kernel/vm/VMCache.cpp @@ -27,6 +27,7 @@ #include #include #include +#include //#define TRACE_VM_CACHE diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index f72c69a9fc..c065510b11 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "VMAnonymousCache.h" @@ -190,10 +191,7 @@ public: }; -#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 @@ AddressSpaceReadLocker::SetFromArea(area_id areaID, VMArea*& area) 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 @@ AddressSpaceWriteLocker::SetFromArea(area_id areaID, VMArea*& area) 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 @@ status_t 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 @@ AddressSpaceWriteLocker::SetFromArea(team_id team, area_id areaID, fSpace->Get(); } - rw_lock_read_unlock(&sAreaHashLock); + VMAreaHash::ReadUnlock(); if (fSpace == NULL) return B_BAD_VALUE; @@ -452,9 +446,7 @@ AddressSpaceWriteLocker::SetFromArea(team_id team, area_id areaID, 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 @@ MultiAddressSpaceLocker::AddAreaCacheAndLock(area_id areaID, // 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 @@ private: // #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 @@ get_address_space_by_area_id(area_id id) 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 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, 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 @@ vm_clone_area(team_id team, const char* name, void** address, 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(int argc, char** argv) 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 @@ static int dump_area_list(int argc, char** argv) { VMArea* area; - struct hash_iterator iter; const char* name = NULL; int32 id = 0; @@ -4012,8 +3970,8 @@ dump_area_list(int argc, char** argv) 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 @@ dump_area_list(int argc, char** argv) (void*)area->base, (void*)area->size, area->protection, area->wiring, area->name); } - hash_close(sAreaHash, &iter, false); return 0; } @@ -4456,12 +4413,9 @@ vm_init(kernel_args* args) 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_for(void* address) 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); } diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index 884a981145..eebb0816ce 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "VMAnonymousCache.h"