* Added VMArea subclasses VM{Kernel,User}Area and moved the address space list
link to them.
* VM{Kernel,User}AddressSpace manage the respective VMArea subclass now, and
VMAddressSpace has grown factory methods {Create,Delete}Area.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34493 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -66,6 +66,9 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const = 0;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const = 0;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection) = 0;
|
||||
virtual void DeleteArea(VMArea* area) = 0;
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area) = 0;
|
||||
virtual void RemoveArea(VMArea* area) = 0;
|
||||
|
||||
@@ -48,50 +48,28 @@ struct VMArea {
|
||||
{ return address >= fBase
|
||||
&& address <= fBase + (fSize - 1); }
|
||||
|
||||
static VMArea* Create(VMAddressSpace* addressSpace,
|
||||
const char* name, uint32 wiring,
|
||||
uint32 protection);
|
||||
static VMArea* CreateReserved(VMAddressSpace* addressSpace,
|
||||
uint32 flags);
|
||||
protected:
|
||||
VMArea(VMAddressSpace* addressSpace,
|
||||
uint32 wiring, uint32 protection);
|
||||
~VMArea();
|
||||
|
||||
DoublyLinkedListLink<VMArea>& AddressSpaceLink()
|
||||
{ return fAddressSpaceLink; }
|
||||
const DoublyLinkedListLink<VMArea>& AddressSpaceLink() const
|
||||
{ return fAddressSpaceLink; }
|
||||
status_t Init(const char* name);
|
||||
|
||||
private:
|
||||
protected:
|
||||
friend class VMAddressSpace;
|
||||
friend class VMKernelAddressSpace;
|
||||
friend class VMUserAddressSpace;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void SetBase(addr_t base) { fBase = base; }
|
||||
void SetSize(size_t size) { fSize = size; }
|
||||
|
||||
private:
|
||||
DoublyLinkedListLink<VMArea> fAddressSpaceLink;
|
||||
protected:
|
||||
addr_t fBase;
|
||||
size_t fSize;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
|
||||
@@ -16,8 +16,10 @@ KernelMergeObject kernel_vm.o :
|
||||
VMCache.cpp
|
||||
VMDeviceCache.cpp
|
||||
VMKernelAddressSpace.cpp
|
||||
VMKernelArea.cpp
|
||||
VMNullCache.cpp
|
||||
VMUserAddressSpace.cpp
|
||||
VMUserArea.cpp
|
||||
|
||||
: $(TARGET_KERNEL_PIC_CCFLAGS)
|
||||
;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
#include <heap.h>
|
||||
#include <vm/vm_priv.h>
|
||||
|
||||
|
||||
#define AREA_HASH_TABLE_SIZE 1024
|
||||
@@ -24,61 +23,49 @@ static area_id sNextAreaID = 1;
|
||||
|
||||
// #pragma mark - VMArea
|
||||
|
||||
VMArea::VMArea(VMAddressSpace* addressSpace, uint32 wiring, uint32 protection)
|
||||
:
|
||||
name(NULL),
|
||||
protection(protection),
|
||||
wiring(wiring),
|
||||
memory_type(0),
|
||||
cache(NULL),
|
||||
no_cache_change(0),
|
||||
cache_offset(0),
|
||||
cache_type(0),
|
||||
page_protections(NULL),
|
||||
address_space(addressSpace),
|
||||
cache_next(NULL),
|
||||
cache_prev(NULL),
|
||||
hash_next(NULL)
|
||||
{
|
||||
new (&mappings) VMAreaMappings;
|
||||
}
|
||||
|
||||
/*static*/ VMArea*
|
||||
VMArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||
uint32 wiring, uint32 protection)
|
||||
|
||||
VMArea::~VMArea()
|
||||
{
|
||||
free(page_protections);
|
||||
free(name);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VMArea::Init(const char* name)
|
||||
{
|
||||
// restrict the area name to B_OS_NAME_LENGTH
|
||||
size_t length = strlen(name) + 1;
|
||||
if (length > B_OS_NAME_LENGTH)
|
||||
length = B_OS_NAME_LENGTH;
|
||||
|
||||
VMArea* area = (VMArea*)malloc_nogrow(sizeof(VMArea));
|
||||
if (area == NULL)
|
||||
return NULL;
|
||||
// clone the name
|
||||
this->name = (char*)malloc_nogrow(length);
|
||||
if (this->name == NULL)
|
||||
return B_NO_MEMORY;
|
||||
strlcpy(this->name, name, length);
|
||||
|
||||
area->name = (char*)malloc_nogrow(length);
|
||||
if (area->name == NULL) {
|
||||
free(area);
|
||||
return NULL;
|
||||
}
|
||||
strlcpy(area->name, name, length);
|
||||
|
||||
area->id = atomic_add(&sNextAreaID, 1);
|
||||
area->fBase = 0;
|
||||
area->fSize = 0;
|
||||
area->protection = protection;
|
||||
area->wiring = wiring;
|
||||
area->memory_type = 0;
|
||||
|
||||
area->cache = NULL;
|
||||
area->cache_offset = 0;
|
||||
|
||||
area->address_space = addressSpace;
|
||||
area->cache_next = area->cache_prev = NULL;
|
||||
area->hash_next = NULL;
|
||||
new (&area->mappings) VMAreaMappings;
|
||||
area->page_protections = NULL;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ VMArea*
|
||||
VMArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags)
|
||||
{
|
||||
VMArea* reserved = (VMArea*)malloc_nogrow(sizeof(VMArea));
|
||||
if (reserved == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(reserved, 0, sizeof(VMArea));
|
||||
reserved->id = RESERVED_AREA_ID;
|
||||
// this marks it as reserved space
|
||||
reserved->protection = flags;
|
||||
reserved->address_space = addressSpace;
|
||||
|
||||
return reserved;
|
||||
id = atomic_add(&sNextAreaID, 1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +101,6 @@ VMAreaHash::Find(const char* name)
|
||||
|
||||
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;
|
||||
|
||||
@@ -56,7 +56,7 @@ VMKernelAddressSpace::~VMKernelAddressSpace()
|
||||
inline VMArea*
|
||||
VMKernelAddressSpace::FirstArea() const
|
||||
{
|
||||
VMArea* area = fAreas.Head();
|
||||
VMKernelArea* area = fAreas.Head();
|
||||
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||
area = fAreas.GetNext(area);
|
||||
return area;
|
||||
@@ -64,8 +64,9 @@ VMKernelAddressSpace::FirstArea() const
|
||||
|
||||
|
||||
inline VMArea*
|
||||
VMKernelAddressSpace::NextArea(VMArea* area) const
|
||||
VMKernelAddressSpace::NextArea(VMArea* _area) const
|
||||
{
|
||||
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||
area = fAreas.GetNext(area);
|
||||
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||
area = fAreas.GetNext(area);
|
||||
@@ -73,6 +74,21 @@ VMKernelAddressSpace::NextArea(VMArea* area) const
|
||||
}
|
||||
|
||||
|
||||
VMArea*
|
||||
VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection)
|
||||
{
|
||||
return VMKernelArea::Create(this, name, wiring, protection);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VMKernelAddressSpace::DeleteArea(VMArea* area)
|
||||
{
|
||||
delete static_cast<VMKernelArea*>(area);
|
||||
}
|
||||
|
||||
|
||||
//! You must hold the address space's read lock.
|
||||
VMArea*
|
||||
VMKernelAddressSpace::LookupArea(addr_t address) const
|
||||
@@ -81,8 +97,8 @@ VMKernelAddressSpace::LookupArea(addr_t address) const
|
||||
if (fAreaHint != NULL && fAreaHint->ContainsAddress(address))
|
||||
return fAreaHint;
|
||||
|
||||
for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMKernelAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMKernelArea* area = it.Next();) {
|
||||
if (area->id == RESERVED_AREA_ID)
|
||||
continue;
|
||||
|
||||
@@ -103,8 +119,10 @@ VMKernelAddressSpace::LookupArea(addr_t address) const
|
||||
*/
|
||||
status_t
|
||||
VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area)
|
||||
addr_t size, VMArea* _area)
|
||||
{
|
||||
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||
|
||||
addr_t searchBase, searchEnd;
|
||||
status_t status;
|
||||
|
||||
@@ -146,8 +164,10 @@ VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||
|
||||
//! You must hold the address space's write lock.
|
||||
void
|
||||
VMKernelAddressSpace::RemoveArea(VMArea* area)
|
||||
VMKernelAddressSpace::RemoveArea(VMArea* _area)
|
||||
{
|
||||
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||
|
||||
fAreas.Remove(area);
|
||||
|
||||
if (area->id != RESERVED_AREA_ID) {
|
||||
@@ -163,7 +183,7 @@ VMKernelAddressSpace::RemoveArea(VMArea* area)
|
||||
bool
|
||||
VMKernelAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
||||
{
|
||||
VMArea* next = fAreas.GetNext(area);
|
||||
VMKernelArea* next = fAreas.GetNext(static_cast<VMKernelArea*>(area));
|
||||
addr_t newEnd = area->Base() + (newSize - 1);
|
||||
if (next == NULL) {
|
||||
if (fEndAddress >= newEnd)
|
||||
@@ -187,10 +207,12 @@ VMKernelAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
||||
|
||||
|
||||
status_t
|
||||
VMKernelAddressSpace::ResizeArea(VMArea* area, size_t newSize)
|
||||
VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
||||
{
|
||||
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||
|
||||
addr_t newEnd = area->Base() + (newSize - 1);
|
||||
VMArea* next = fAreas.GetNext(area);
|
||||
VMKernelArea* next = fAreas.GetNext(area);
|
||||
if (next != NULL && next->Base() <= newEnd) {
|
||||
if (next->id != RESERVED_AREA_ID
|
||||
|| next->cache_offset > area->Base()
|
||||
@@ -256,7 +278,7 @@ VMKernelAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||
return B_BAD_TEAM_ID;
|
||||
}
|
||||
|
||||
VMArea* area = VMArea::CreateReserved(this, flags);
|
||||
VMKernelArea* area = VMKernelArea::CreateReserved(this, flags);
|
||||
if (area == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -286,8 +308,8 @@ VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||
|
||||
// search area list and remove any matching reserved ranges
|
||||
addr_t endAddress = address + (size - 1);
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMKernelAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMKernelArea* area = it.Next();) {
|
||||
// the area must be completely part of the reserved range
|
||||
if (area->Base() + (area->Size() - 1) > endAddress)
|
||||
break;
|
||||
@@ -306,8 +328,8 @@ VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||
void
|
||||
VMKernelAddressSpace::UnreserveAllAddressRanges()
|
||||
{
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMKernelAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMKernelArea* area = it.Next();) {
|
||||
if (area->id == RESERVED_AREA_ID) {
|
||||
RemoveArea(area);
|
||||
Put();
|
||||
@@ -325,8 +347,8 @@ VMKernelAddressSpace::Dump() const
|
||||
|
||||
kprintf("area_list:\n");
|
||||
|
||||
for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMKernelAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMKernelArea* area = it.Next();) {
|
||||
kprintf(" area 0x%lx: ", area->id);
|
||||
kprintf("base_addr = 0x%lx ", area->Base());
|
||||
kprintf("size = 0x%lx ", area->Size());
|
||||
@@ -342,11 +364,11 @@ VMKernelAddressSpace::Dump() const
|
||||
*/
|
||||
status_t
|
||||
VMKernelAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
VMArea* area)
|
||||
VMKernelArea* area)
|
||||
{
|
||||
VMArea* next;
|
||||
VMKernelArea* next;
|
||||
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
for (VMKernelAreaList::Iterator it = fAreas.GetIterator();
|
||||
(next = it.Next()) != NULL;) {
|
||||
if (next->Base() <= start
|
||||
&& next->Base() + (next->Size() - 1) >= start + (size - 1)) {
|
||||
@@ -390,7 +412,8 @@ VMKernelAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
} else {
|
||||
// the area splits the reserved range into two separate ones
|
||||
// we need a new reserved area to cover this space
|
||||
VMArea* reserved = VMArea::CreateReserved(this, next->protection);
|
||||
VMKernelArea* reserved = VMKernelArea::CreateReserved(this,
|
||||
next->protection);
|
||||
if (reserved == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -416,10 +439,10 @@ VMKernelAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
/*! Must be called with this address space's write lock held */
|
||||
status_t
|
||||
VMKernelAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
||||
uint32 addressSpec, VMArea* area)
|
||||
uint32 addressSpec, VMKernelArea* area)
|
||||
{
|
||||
VMArea* last = NULL;
|
||||
VMArea* next;
|
||||
VMKernelArea* last = NULL;
|
||||
VMKernelArea* next;
|
||||
bool foundSpot = false;
|
||||
|
||||
TRACE(("VMKernelAddressSpace::_InsertAreaSlot: address space %p, start "
|
||||
@@ -453,7 +476,7 @@ VMKernelAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
||||
|
||||
// walk up to the spot where we should start searching
|
||||
second_chance:
|
||||
VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMKernelAreaList::Iterator it = fAreas.GetIterator();
|
||||
while ((next = it.Next()) != NULL) {
|
||||
if (next->Base() > start + (size - 1)) {
|
||||
// we have a winner
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <vm/VMAddressSpace.h>
|
||||
|
||||
#include "VMKernelArea.h"
|
||||
|
||||
|
||||
struct VMKernelAddressSpace : VMAddressSpace {
|
||||
public:
|
||||
@@ -23,6 +25,9 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection);
|
||||
virtual void DeleteArea(VMArea* area);
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area);
|
||||
virtual void RemoveArea(VMArea* area);
|
||||
@@ -43,13 +48,13 @@ public:
|
||||
|
||||
private:
|
||||
status_t _InsertAreaIntoReservedRegion(addr_t start,
|
||||
size_t size, VMArea* area);
|
||||
size_t size, VMKernelArea* area);
|
||||
status_t _InsertAreaSlot(addr_t start, addr_t size,
|
||||
addr_t end, uint32 addressSpec,
|
||||
VMArea* area);
|
||||
VMKernelArea* area);
|
||||
|
||||
private:
|
||||
VMAddressSpaceAreaList fAreas;
|
||||
VMKernelAreaList fAreas;
|
||||
mutable VMArea* fAreaHint;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "VMKernelArea.h"
|
||||
|
||||
#include <heap.h>
|
||||
#include <vm/vm_priv.h>
|
||||
|
||||
|
||||
VMKernelArea::VMKernelArea(VMAddressSpace* addressSpace, uint32 wiring,
|
||||
uint32 protection)
|
||||
:
|
||||
VMArea(addressSpace, wiring, protection)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VMKernelArea::~VMKernelArea()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*static*/ VMKernelArea*
|
||||
VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||
uint32 wiring, uint32 protection)
|
||||
{
|
||||
VMKernelArea* area = new(nogrow) VMKernelArea(addressSpace, wiring,
|
||||
protection);
|
||||
if (area == NULL)
|
||||
return NULL;
|
||||
|
||||
if (area->Init(name) != B_OK) {
|
||||
delete area;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ VMKernelArea*
|
||||
VMKernelArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags)
|
||||
{
|
||||
VMKernelArea* area = new(nogrow) VMKernelArea(addressSpace, 0, 0);
|
||||
if (area != NULL)
|
||||
area->id = RESERVED_AREA_ID;
|
||||
return area;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#ifndef VM_KERNEL_AREA_H
|
||||
#define VM_KERNEL_AREA_H
|
||||
|
||||
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
|
||||
struct VMKernelAddressSpace;
|
||||
|
||||
|
||||
struct VMKernelArea : VMArea {
|
||||
VMKernelArea(VMAddressSpace* addressSpace,
|
||||
uint32 wiring, uint32 protection);
|
||||
~VMKernelArea();
|
||||
|
||||
static VMKernelArea* Create(VMAddressSpace* addressSpace,
|
||||
const char* name, uint32 wiring,
|
||||
uint32 protection);
|
||||
static VMKernelArea* CreateReserved(VMAddressSpace* addressSpace,
|
||||
uint32 flags);
|
||||
|
||||
DoublyLinkedListLink<VMKernelArea>& AddressSpaceLink()
|
||||
{ return fAddressSpaceLink; }
|
||||
const DoublyLinkedListLink<VMKernelArea>& AddressSpaceLink() const
|
||||
{ return fAddressSpaceLink; }
|
||||
|
||||
private:
|
||||
DoublyLinkedListLink<VMKernelArea> fAddressSpaceLink;
|
||||
};
|
||||
|
||||
|
||||
struct VMKernelAreaGetLink {
|
||||
inline DoublyLinkedListLink<VMKernelArea>* operator()(
|
||||
VMKernelArea* area) const
|
||||
{
|
||||
return &area->AddressSpaceLink();
|
||||
}
|
||||
|
||||
inline const DoublyLinkedListLink<VMKernelArea>* operator()(
|
||||
const VMKernelArea* area) const
|
||||
{
|
||||
return &area->AddressSpaceLink();
|
||||
}
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<VMKernelArea, VMKernelAreaGetLink> VMKernelAreaList;
|
||||
|
||||
|
||||
#endif // VM_KERNEL_AREA_H
|
||||
@@ -56,7 +56,7 @@ VMUserAddressSpace::~VMUserAddressSpace()
|
||||
inline VMArea*
|
||||
VMUserAddressSpace::FirstArea() const
|
||||
{
|
||||
VMArea* area = fAreas.Head();
|
||||
VMUserArea* area = fAreas.Head();
|
||||
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||
area = fAreas.GetNext(area);
|
||||
return area;
|
||||
@@ -64,8 +64,9 @@ VMUserAddressSpace::FirstArea() const
|
||||
|
||||
|
||||
inline VMArea*
|
||||
VMUserAddressSpace::NextArea(VMArea* area) const
|
||||
VMUserAddressSpace::NextArea(VMArea* _area) const
|
||||
{
|
||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||
area = fAreas.GetNext(area);
|
||||
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||
area = fAreas.GetNext(area);
|
||||
@@ -73,6 +74,21 @@ VMUserAddressSpace::NextArea(VMArea* area) const
|
||||
}
|
||||
|
||||
|
||||
VMArea*
|
||||
VMUserAddressSpace::CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection)
|
||||
{
|
||||
return VMUserArea::Create(this, name, wiring, protection);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VMUserAddressSpace::DeleteArea(VMArea* area)
|
||||
{
|
||||
delete static_cast<VMUserArea*>(area);
|
||||
}
|
||||
|
||||
|
||||
//! You must hold the address space's read lock.
|
||||
VMArea*
|
||||
VMUserAddressSpace::LookupArea(addr_t address) const
|
||||
@@ -81,8 +97,8 @@ VMUserAddressSpace::LookupArea(addr_t address) const
|
||||
if (fAreaHint != NULL && fAreaHint->ContainsAddress(address))
|
||||
return fAreaHint;
|
||||
|
||||
for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMUserAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMUserArea* area = it.Next();) {
|
||||
if (area->id == RESERVED_AREA_ID)
|
||||
continue;
|
||||
|
||||
@@ -103,8 +119,10 @@ VMUserAddressSpace::LookupArea(addr_t address) const
|
||||
*/
|
||||
status_t
|
||||
VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area)
|
||||
addr_t size, VMArea* _area)
|
||||
{
|
||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||
|
||||
addr_t searchBase, searchEnd;
|
||||
status_t status;
|
||||
|
||||
@@ -146,8 +164,10 @@ VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||
|
||||
//! You must hold the address space's write lock.
|
||||
void
|
||||
VMUserAddressSpace::RemoveArea(VMArea* area)
|
||||
VMUserAddressSpace::RemoveArea(VMArea* _area)
|
||||
{
|
||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||
|
||||
fAreas.Remove(area);
|
||||
|
||||
if (area->id != RESERVED_AREA_ID) {
|
||||
@@ -163,7 +183,7 @@ VMUserAddressSpace::RemoveArea(VMArea* area)
|
||||
bool
|
||||
VMUserAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
||||
{
|
||||
VMArea* next = fAreas.GetNext(area);
|
||||
VMUserArea* next = fAreas.GetNext(static_cast<VMUserArea*>(area));
|
||||
addr_t newEnd = area->Base() + (newSize - 1);
|
||||
if (next == NULL) {
|
||||
if (fEndAddress >= newEnd)
|
||||
@@ -187,10 +207,12 @@ VMUserAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
||||
|
||||
|
||||
status_t
|
||||
VMUserAddressSpace::ResizeArea(VMArea* area, size_t newSize)
|
||||
VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
||||
{
|
||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||
|
||||
addr_t newEnd = area->Base() + (newSize - 1);
|
||||
VMArea* next = fAreas.GetNext(area);
|
||||
VMUserArea* next = fAreas.GetNext(area);
|
||||
if (next != NULL && next->Base() <= newEnd) {
|
||||
if (next->id != RESERVED_AREA_ID
|
||||
|| next->cache_offset > area->Base()
|
||||
@@ -256,7 +278,7 @@ VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||
return B_BAD_TEAM_ID;
|
||||
}
|
||||
|
||||
VMArea* area = VMArea::CreateReserved(this, flags);
|
||||
VMUserArea* area = VMUserArea::CreateReserved(this, flags);
|
||||
if (area == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -286,8 +308,8 @@ VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||
|
||||
// search area list and remove any matching reserved ranges
|
||||
addr_t endAddress = address + (size - 1);
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMUserArea* area = it.Next();) {
|
||||
// the area must be completely part of the reserved range
|
||||
if (area->Base() + (area->Size() - 1) > endAddress)
|
||||
break;
|
||||
@@ -306,8 +328,8 @@ VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||
void
|
||||
VMUserAddressSpace::UnreserveAllAddressRanges()
|
||||
{
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMUserArea* area = it.Next();) {
|
||||
if (area->id == RESERVED_AREA_ID) {
|
||||
RemoveArea(area);
|
||||
Put();
|
||||
@@ -325,8 +347,8 @@ VMUserAddressSpace::Dump() const
|
||||
|
||||
kprintf("area_list:\n");
|
||||
|
||||
for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMArea* area = it.Next();) {
|
||||
for (VMUserAreaList::ConstIterator it = fAreas.GetIterator();
|
||||
VMUserArea* area = it.Next();) {
|
||||
kprintf(" area 0x%lx: ", area->id);
|
||||
kprintf("base_addr = 0x%lx ", area->Base());
|
||||
kprintf("size = 0x%lx ", area->Size());
|
||||
@@ -342,11 +364,11 @@ VMUserAddressSpace::Dump() const
|
||||
*/
|
||||
status_t
|
||||
VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
VMArea* area)
|
||||
VMUserArea* area)
|
||||
{
|
||||
VMArea* next;
|
||||
VMUserArea* next;
|
||||
|
||||
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
|
||||
(next = it.Next()) != NULL;) {
|
||||
if (next->Base() <= start
|
||||
&& next->Base() + (next->Size() - 1) >= start + (size - 1)) {
|
||||
@@ -390,7 +412,8 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
} else {
|
||||
// the area splits the reserved range into two separate ones
|
||||
// we need a new reserved area to cover this space
|
||||
VMArea* reserved = VMArea::CreateReserved(this, next->protection);
|
||||
VMUserArea* reserved = VMUserArea::CreateReserved(this,
|
||||
next->protection);
|
||||
if (reserved == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -416,10 +439,10 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
/*! Must be called with this address space's write lock held */
|
||||
status_t
|
||||
VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
||||
uint32 addressSpec, VMArea* area)
|
||||
uint32 addressSpec, VMUserArea* area)
|
||||
{
|
||||
VMArea* last = NULL;
|
||||
VMArea* next;
|
||||
VMUserArea* last = NULL;
|
||||
VMUserArea* next;
|
||||
bool foundSpot = false;
|
||||
|
||||
TRACE(("VMUserAddressSpace::_InsertAreaSlot: address space %p, start "
|
||||
@@ -453,7 +476,7 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
||||
|
||||
// walk up to the spot where we should start searching
|
||||
second_chance:
|
||||
VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||
VMUserAreaList::Iterator it = fAreas.GetIterator();
|
||||
while ((next = it.Next()) != NULL) {
|
||||
if (next->Base() > start + (size - 1)) {
|
||||
// we have a winner
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <vm/VMAddressSpace.h>
|
||||
|
||||
#include "VMUserArea.h"
|
||||
|
||||
|
||||
struct VMUserAddressSpace : VMAddressSpace {
|
||||
public:
|
||||
@@ -23,6 +25,9 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection);
|
||||
virtual void DeleteArea(VMArea* area);
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area);
|
||||
virtual void RemoveArea(VMArea* area);
|
||||
@@ -43,13 +48,13 @@ public:
|
||||
|
||||
private:
|
||||
status_t _InsertAreaIntoReservedRegion(addr_t start,
|
||||
size_t size, VMArea* area);
|
||||
size_t size, VMUserArea* area);
|
||||
status_t _InsertAreaSlot(addr_t start, addr_t size,
|
||||
addr_t end, uint32 addressSpec,
|
||||
VMArea* area);
|
||||
VMUserArea* area);
|
||||
|
||||
private:
|
||||
VMAddressSpaceAreaList fAreas;
|
||||
VMUserAreaList fAreas;
|
||||
mutable VMArea* fAreaHint;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "VMUserArea.h"
|
||||
|
||||
#include <heap.h>
|
||||
#include <vm/vm_priv.h>
|
||||
|
||||
|
||||
VMUserArea::VMUserArea(VMAddressSpace* addressSpace, uint32 wiring,
|
||||
uint32 protection)
|
||||
:
|
||||
VMArea(addressSpace, wiring, protection)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VMUserArea::~VMUserArea()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*static*/ VMUserArea*
|
||||
VMUserArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||
uint32 wiring, uint32 protection)
|
||||
{
|
||||
VMUserArea* area = new(nogrow) VMUserArea(addressSpace, wiring,
|
||||
protection);
|
||||
if (area == NULL)
|
||||
return NULL;
|
||||
|
||||
if (area->Init(name) != B_OK) {
|
||||
delete area;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ VMUserArea*
|
||||
VMUserArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags)
|
||||
{
|
||||
VMUserArea* area = new(nogrow) VMUserArea(addressSpace, 0, 0);
|
||||
if (area != NULL)
|
||||
area->id = RESERVED_AREA_ID;
|
||||
return area;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#ifndef VM_USER_AREA_H
|
||||
#define VM_USER_AREA_H
|
||||
|
||||
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
|
||||
struct VMUserAddressSpace;
|
||||
|
||||
|
||||
struct VMUserArea : VMArea {
|
||||
VMUserArea(VMAddressSpace* addressSpace,
|
||||
uint32 wiring, uint32 protection);
|
||||
~VMUserArea();
|
||||
|
||||
static VMUserArea* Create(VMAddressSpace* addressSpace,
|
||||
const char* name, uint32 wiring,
|
||||
uint32 protection);
|
||||
static VMUserArea* CreateReserved(VMAddressSpace* addressSpace,
|
||||
uint32 flags);
|
||||
|
||||
DoublyLinkedListLink<VMUserArea>& AddressSpaceLink()
|
||||
{ return fAddressSpaceLink; }
|
||||
const DoublyLinkedListLink<VMUserArea>& AddressSpaceLink() const
|
||||
{ return fAddressSpaceLink; }
|
||||
|
||||
private:
|
||||
DoublyLinkedListLink<VMUserArea> fAddressSpaceLink;
|
||||
};
|
||||
|
||||
|
||||
struct VMUserAreaGetLink {
|
||||
inline DoublyLinkedListLink<VMUserArea>* operator()(
|
||||
VMUserArea* area) const
|
||||
{
|
||||
return &area->AddressSpaceLink();
|
||||
}
|
||||
|
||||
inline const DoublyLinkedListLink<VMUserArea>* operator()(
|
||||
const VMUserArea* area) const
|
||||
{
|
||||
return &area->AddressSpaceLink();
|
||||
}
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<VMUserArea, VMUserAreaGetLink> VMUserAreaList;
|
||||
|
||||
|
||||
#endif // VM_USER_AREA_H
|
||||
@@ -503,7 +503,7 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache,
|
||||
addressSpec, wiring, protection, _area, areaName));
|
||||
cache->AssertLocked();
|
||||
|
||||
VMArea* area = VMArea::Create(addressSpace, areaName, wiring, protection);
|
||||
VMArea* area = addressSpace->CreateArea(areaName, wiring, protection);
|
||||
if (area == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -594,8 +594,7 @@ err2:
|
||||
sourceCache->Lock();
|
||||
}
|
||||
err1:
|
||||
free(area->name);
|
||||
free(area);
|
||||
addressSpace->DeleteArea(area);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1584,9 +1583,7 @@ delete_area(VMAddressSpace* addressSpace, VMArea* area)
|
||||
area->cache->RemoveArea(area);
|
||||
area->cache->ReleaseRef();
|
||||
|
||||
free(area->page_protections);
|
||||
free(area->name);
|
||||
free(area);
|
||||
addressSpace->DeleteArea(area);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user