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
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
||||
* 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
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -11,6 +11,7 @@ KernelMergeObject kernel_vm.o :
|
||||
VMAddressSpace.cpp
|
||||
VMAnonymousCache.cpp
|
||||
VMAnonymousNoSwapCache.cpp
|
||||
VMArea.cpp
|
||||
VMCache.cpp
|
||||
VMDeviceCache.cpp
|
||||
VMNullCache.cpp
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <thread.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_priv.h>
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
|
||||
//#define TRACE_VM
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
+24
-89
@@ -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 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user