Ingo Weinhold 35d940014e * Changed the address space area list to doubly linked. The reason is to
simplify migration of the area management, but as a side effect, it also
  makes area deletion O(1) (instead of O(n), n == number of areas in the
  address space).
* Moved more area management functionality from vm.cpp to VMAddressSpace and
  VMArea structure creation to VMArea. Made the list and list link members
  itself private.
* VMAddressSpace tracks its amount of free space, now. This also replaces
  the previous mechanism to do that only for the kernel address space. It
  was broken anyway, since delete_area() subtracted the area size instead of
  adding it.
* vm_free_unused_boot_loader_range():
  - lastEnd could be set to a value < start, which could cause memory
    outside of the given range to be unmapped. Haven't checked whether this
    could happen in practice -- if so, it would be seriously unhealthy.
  - The range between the end of the last area in the range and the end of
    the range would never be freed.
  - Fixed potential integer overflows when computing addresses.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34459 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-12-03 12:41:11 +00:00

138 lines
3.1 KiB
C++

/*
* 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 <lock.h>
#include <util/DoublyLinkedList.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* cache_next;
struct VMArea* cache_prev;
struct VMArea* hash_next;
bool ContainsAddress(addr_t address) const
{ return address >= base
&& address <= base + (size - 1); }
static VMArea* Create(VMAddressSpace* addressSpace,
const char* name, uint32 wiring,
uint32 protection);
static VMArea* CreateReserved(VMAddressSpace* addressSpace,
uint32 flags);
DoublyLinkedListLink<VMArea>& AddressSpaceLink()
{ return fAddressSpaceLink; }
const DoublyLinkedListLink<VMArea>& AddressSpaceLink() const
{ return fAddressSpaceLink; }
private:
DoublyLinkedListLink<VMArea> fAddressSpaceLink;
};
struct VMAddressSpaceAreaGetLink {
inline DoublyLinkedListLink<VMArea>* operator()(VMArea* area) const
{
return &area->AddressSpaceLink();
}
inline const DoublyLinkedListLink<VMArea>* operator()(
const VMArea* area) const
{
return &area->AddressSpaceLink();
}
};
typedef DoublyLinkedList<VMArea, VMAddressSpaceAreaGetLink>
VMAddressSpaceAreaList;
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