Moved all knowledge of reserved areas from vm.cpp to VMAddressSpace. It's a
pure address space feature, so it should be handled there. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34491 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,13 +12,14 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <vm/vm_priv.h>
|
||||||
#include <vm/vm_translation_map.h>
|
#include <vm/vm_translation_map.h>
|
||||||
#include <vm/VMArea.h>
|
#include <vm/VMArea.h>
|
||||||
|
|
||||||
|
|
||||||
struct VMAddressSpace {
|
struct VMAddressSpace {
|
||||||
public:
|
public:
|
||||||
class Iterator;
|
class AreaIterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VMAddressSpace(team_id id, addr_t base,
|
VMAddressSpace(team_id id, addr_t base,
|
||||||
@@ -30,7 +31,7 @@ public:
|
|||||||
|
|
||||||
team_id ID() const { return fID; }
|
team_id ID() const { return fID; }
|
||||||
addr_t Base() const { return fBase; }
|
addr_t Base() const { return fBase; }
|
||||||
size_t Size() const { return fSize; }
|
addr_t EndAddress() const { return fEndAddress; }
|
||||||
size_t FreeSpace() const { return fFreeSpace; }
|
size_t FreeSpace() const { return fFreeSpace; }
|
||||||
bool IsBeingDeleted() const { return fDeleting; }
|
bool IsBeingDeleted() const { return fDeleting; }
|
||||||
|
|
||||||
@@ -57,19 +58,26 @@ public:
|
|||||||
void IncrementChangeCount()
|
void IncrementChangeCount()
|
||||||
{ fChangeCount++; }
|
{ fChangeCount++; }
|
||||||
|
|
||||||
VMArea* FirstArea() const
|
VMArea* FirstArea() const;
|
||||||
{ return fAreas.Head(); }
|
|
||||||
VMArea* NextArea(VMArea* area) const
|
|
||||||
{ return fAreas.GetNext(area); }
|
|
||||||
|
|
||||||
VMArea* LookupArea(addr_t address) const;
|
VMArea* LookupArea(addr_t address) const;
|
||||||
status_t InsertArea(void** _address, uint32 addressSpec,
|
status_t InsertArea(void** _address, uint32 addressSpec,
|
||||||
addr_t size, VMArea* area);
|
addr_t size, VMArea* area);
|
||||||
void RemoveArea(VMArea* area);
|
void RemoveArea(VMArea* area);
|
||||||
|
|
||||||
|
bool CanResizeArea(VMArea* area, size_t newSize);
|
||||||
|
status_t ResizeArea(VMArea* area, size_t newSize);
|
||||||
status_t ResizeAreaHead(VMArea* area, size_t size);
|
status_t ResizeAreaHead(VMArea* area, size_t size);
|
||||||
status_t ResizeAreaTail(VMArea* area, size_t size);
|
status_t ResizeAreaTail(VMArea* area, size_t size);
|
||||||
|
|
||||||
inline Iterator GetIterator();
|
status_t ReserveAddressRange(void** _address,
|
||||||
|
uint32 addressSpec, size_t size,
|
||||||
|
uint32 flags);
|
||||||
|
status_t UnreserveAddressRange(addr_t address,
|
||||||
|
size_t size);
|
||||||
|
void UnreserveAllAddressRanges();
|
||||||
|
|
||||||
|
inline AreaIterator GetAreaIterator();
|
||||||
|
|
||||||
static status_t Create(team_id teamID, addr_t base, size_t size,
|
static status_t Create(team_id teamID, addr_t base, size_t size,
|
||||||
bool kernel,
|
bool kernel,
|
||||||
@@ -108,7 +116,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
VMAddressSpace* fHashTableLink;
|
VMAddressSpace* fHashTableLink;
|
||||||
addr_t fBase;
|
addr_t fBase;
|
||||||
size_t fSize;
|
addr_t fEndAddress; // base + (size - 1)
|
||||||
size_t fFreeSpace;
|
size_t fFreeSpace;
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
team_id fID;
|
team_id fID;
|
||||||
@@ -123,42 +131,65 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class VMAddressSpace::Iterator {
|
class VMAddressSpace::AreaIterator {
|
||||||
public:
|
public:
|
||||||
Iterator()
|
AreaIterator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(VMAddressSpace* addressSpace)
|
AreaIterator(VMAddressSpace* addressSpace)
|
||||||
:
|
:
|
||||||
fIterator(addressSpace->fAreas.GetIterator())
|
fIterator(addressSpace->fAreas.GetIterator())
|
||||||
{
|
{
|
||||||
|
_SkipReserved();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasNext() const
|
bool HasNext() const
|
||||||
{
|
{
|
||||||
return fIterator.HasNext();
|
return fNext != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VMArea* Next()
|
VMArea* Next()
|
||||||
{
|
{
|
||||||
return fIterator.Next();
|
VMArea* result = fNext;
|
||||||
|
_SkipReserved();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rewind()
|
void Rewind()
|
||||||
{
|
{
|
||||||
fIterator.Rewind();
|
fIterator.Rewind();
|
||||||
|
_SkipReserved();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VMAddressSpaceAreaList::Iterator fIterator;
|
void _SkipReserved()
|
||||||
|
{
|
||||||
|
while ((fNext = fIterator.Next()) != NULL
|
||||||
|
&& fNext->id == RESERVED_AREA_ID) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VMAddressSpaceAreaList::Iterator fIterator;
|
||||||
|
VMArea* fNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline VMAddressSpace::Iterator
|
inline VMArea*
|
||||||
VMAddressSpace::GetIterator()
|
VMAddressSpace::FirstArea() const
|
||||||
{
|
{
|
||||||
return Iterator(this);
|
VMArea* area = fAreas.Head();
|
||||||
|
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||||
|
area = fAreas.GetNext(area);
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline VMAddressSpace::AreaIterator
|
||||||
|
VMAddressSpace::GetAreaIterator()
|
||||||
|
{
|
||||||
|
return AreaIterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1304,7 +1304,8 @@ public:
|
|||||||
{
|
{
|
||||||
// find the runtime loader debug area
|
// find the runtime loader debug area
|
||||||
VMArea* area;
|
VMArea* area;
|
||||||
for (VMAddressSpace::Iterator it = team->address_space->GetIterator();
|
for (VMAddressSpace::AreaIterator it
|
||||||
|
= team->address_space->GetAreaIterator();
|
||||||
(area = it.Next()) != NULL;) {
|
(area = it.Next()) != NULL;) {
|
||||||
if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
|
if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <heap.h>
|
#include <heap.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_priv.h>
|
|
||||||
#include <vm/VMArea.h>
|
#include <vm/VMArea.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -88,7 +87,7 @@ VMAddressSpace::VMAddressSpace(team_id id, addr_t base, size_t size,
|
|||||||
bool kernel)
|
bool kernel)
|
||||||
:
|
:
|
||||||
fBase(base),
|
fBase(base),
|
||||||
fSize(size),
|
fEndAddress(base + (size - 1)),
|
||||||
fFreeSpace(size),
|
fFreeSpace(size),
|
||||||
fID(id),
|
fID(id),
|
||||||
fRefCount(1),
|
fRefCount(1),
|
||||||
@@ -317,7 +316,7 @@ VMAddressSpace::InsertArea(void** _address, uint32 addressSpec, addr_t size,
|
|||||||
|
|
||||||
case B_BASE_ADDRESS:
|
case B_BASE_ADDRESS:
|
||||||
searchBase = (addr_t)*_address;
|
searchBase = (addr_t)*_address;
|
||||||
searchEnd = fBase + (fSize - 1);
|
searchEnd = fEndAddress;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_ANY_ADDRESS:
|
case B_ANY_ADDRESS:
|
||||||
@@ -328,7 +327,7 @@ VMAddressSpace::InsertArea(void** _address, uint32 addressSpec, addr_t size,
|
|||||||
// completely (currently needs a userland address space!)
|
// completely (currently needs a userland address space!)
|
||||||
if (searchBase == USER_BASE)
|
if (searchBase == USER_BASE)
|
||||||
searchBase = USER_BASE_ANY;
|
searchBase = USER_BASE_ANY;
|
||||||
searchEnd = fBase + (fSize - 1);
|
searchEnd = fEndAddress;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -361,6 +360,64 @@ VMAddressSpace::RemoveArea(VMArea* area)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
VMAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
||||||
|
{
|
||||||
|
VMArea* next = fAreas.GetNext(area);
|
||||||
|
addr_t newEnd = area->Base() + (newSize - 1);
|
||||||
|
if (next == NULL) {
|
||||||
|
if (fEndAddress >= newEnd)
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (next->Base() > newEnd)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the area was created inside a reserved area, it can
|
||||||
|
// also be resized in that area
|
||||||
|
// TODO: if there is free space after the reserved area, it could
|
||||||
|
// be used as well...
|
||||||
|
if (next->id == RESERVED_AREA_ID && next->cache_offset <= area->Base()
|
||||||
|
&& next->Base() + (next->Size() - 1) >= newEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VMAddressSpace::ResizeArea(VMArea* area, size_t newSize)
|
||||||
|
{
|
||||||
|
addr_t newEnd = area->Base() + (newSize - 1);
|
||||||
|
VMArea* next = fAreas.GetNext(area);
|
||||||
|
if (next != NULL && next->Base() <= newEnd) {
|
||||||
|
if (next->id != RESERVED_AREA_ID
|
||||||
|
|| next->cache_offset > area->Base()
|
||||||
|
|| next->Base() + (next->Size() - 1) < newEnd) {
|
||||||
|
panic("resize situation for area %p has changed although we "
|
||||||
|
"should have the address space lock", area);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize reserved area
|
||||||
|
addr_t offset = area->Base() + newSize - next->Base();
|
||||||
|
if (next->Size() <= offset) {
|
||||||
|
RemoveArea(next);
|
||||||
|
free(next);
|
||||||
|
} else {
|
||||||
|
status_t error = ResizeAreaHead(next, next->Size() - offset);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResizeAreaTail(area, newSize);
|
||||||
|
// TODO: In case of error we should undo the change to the reserved
|
||||||
|
// area.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMAddressSpace::ResizeAreaHead(VMArea* area, size_t size)
|
VMAddressSpace::ResizeAreaHead(VMArea* area, size_t size)
|
||||||
{
|
{
|
||||||
@@ -388,6 +445,78 @@ VMAddressSpace::ResizeAreaTail(VMArea* area, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VMAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||||
|
size_t size, uint32 flags)
|
||||||
|
{
|
||||||
|
// check to see if this address space has entered DELETE state
|
||||||
|
if (fDeleting) {
|
||||||
|
// okay, someone is trying to delete this address space now, so we
|
||||||
|
// can't insert the area, let's back out
|
||||||
|
return B_BAD_TEAM_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMArea* area = VMArea::CreateReserved(this, flags);
|
||||||
|
if (area == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t status = InsertArea(_address, addressSpec, size, area);
|
||||||
|
if (status != B_OK) {
|
||||||
|
free(area);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
area->cache_offset = area->Base();
|
||||||
|
// we cache the original base address here
|
||||||
|
|
||||||
|
Get();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VMAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||||
|
{
|
||||||
|
// check to see if this address space has entered DELETE state
|
||||||
|
if (fDeleting) {
|
||||||
|
// okay, someone is trying to delete this address space now, so we can't
|
||||||
|
// insert the area, so back out
|
||||||
|
return B_BAD_TEAM_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();) {
|
||||||
|
// the area must be completely part of the reserved range
|
||||||
|
if (area->Base() + (area->Size() - 1) > endAddress)
|
||||||
|
break;
|
||||||
|
if (area->id == RESERVED_AREA_ID && area->Base() >= (addr_t)address) {
|
||||||
|
// remove reserved range
|
||||||
|
RemoveArea(area);
|
||||||
|
Put();
|
||||||
|
free(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VMAddressSpace::UnreserveAllAddressRanges()
|
||||||
|
{
|
||||||
|
for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator();
|
||||||
|
VMArea* area = it.Next();) {
|
||||||
|
if (area->id == RESERVED_AREA_ID) {
|
||||||
|
RemoveArea(area);
|
||||||
|
Put();
|
||||||
|
free(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMAddressSpace::Dump() const
|
VMAddressSpace::Dump() const
|
||||||
{
|
{
|
||||||
@@ -397,7 +526,7 @@ VMAddressSpace::Dump() const
|
|||||||
kprintf("fault_count: %ld\n", fFaultCount);
|
kprintf("fault_count: %ld\n", fFaultCount);
|
||||||
kprintf("translation_map: %p\n", &fTranslationMap);
|
kprintf("translation_map: %p\n", &fTranslationMap);
|
||||||
kprintf("base: 0x%lx\n", fBase);
|
kprintf("base: 0x%lx\n", fBase);
|
||||||
kprintf("size: 0x%lx\n", fSize);
|
kprintf("end: 0x%lx\n", fEndAddress);
|
||||||
kprintf("change_count: 0x%lx\n", fChangeCount);
|
kprintf("change_count: 0x%lx\n", fChangeCount);
|
||||||
kprintf("area_hint: %p\n", fAreaHint);
|
kprintf("area_hint: %p\n", fAreaHint);
|
||||||
|
|
||||||
@@ -505,7 +634,7 @@ VMAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
|||||||
size, end, addressSpec, area));
|
size, end, addressSpec, area));
|
||||||
|
|
||||||
// do some sanity checking
|
// do some sanity checking
|
||||||
if (start < fBase || size == 0 || end > fBase + fSize - 1
|
if (start < fBase || size == 0 || end > fEndAddress
|
||||||
|| start + (size - 1) > end)
|
|| start + (size - 1) > end)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
@@ -753,7 +882,7 @@ VMAddressSpace::_DumpCommand(int argc, char** argv)
|
|||||||
/*static*/ int
|
/*static*/ int
|
||||||
VMAddressSpace::_DumpListCommand(int argc, char** argv)
|
VMAddressSpace::_DumpListCommand(int argc, char** argv)
|
||||||
{
|
{
|
||||||
kprintf(" address id base size area count "
|
kprintf(" address id base end area count "
|
||||||
" area size\n");
|
" area size\n");
|
||||||
|
|
||||||
AddressSpaceTable::Iterator it = sAddressSpaceTable.GetIterator();
|
AddressSpaceTable::Iterator it = sAddressSpaceTable.GetIterator();
|
||||||
@@ -769,7 +898,7 @@ VMAddressSpace::_DumpListCommand(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
kprintf("%p %6ld %#010lx %#10lx %10ld %10lld\n",
|
kprintf("%p %6ld %#010lx %#10lx %10ld %10lld\n",
|
||||||
space, space->ID(), space->Base(), space->Size(), areaCount,
|
space, space->ID(), space->Base(), space->EndAddress(), areaCount,
|
||||||
areaSize);
|
areaSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-122
@@ -460,30 +460,26 @@ unmap_address_range(VMAddressSpace* addressSpace, addr_t address, addr_t size,
|
|||||||
|
|
||||||
// Check, whether the caller is allowed to modify the concerned areas.
|
// Check, whether the caller is allowed to modify the concerned areas.
|
||||||
if (!kernel) {
|
if (!kernel) {
|
||||||
for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
|
for (VMAddressSpace::AreaIterator it = addressSpace->GetAreaIterator();
|
||||||
VMArea* area = it.Next();) {
|
VMArea* area = it.Next();) {
|
||||||
if (area->id != RESERVED_AREA_ID) {
|
addr_t areaLast = area->Base() + (area->Size() - 1);
|
||||||
addr_t areaLast = area->Base() + (area->Size() - 1);
|
if (area->Base() < lastAddress && address < areaLast) {
|
||||||
if (area->Base() < lastAddress && address < areaLast) {
|
if ((area->protection & B_KERNEL_AREA) != 0)
|
||||||
if ((area->protection & B_KERNEL_AREA) != 0)
|
return B_NOT_ALLOWED;
|
||||||
return B_NOT_ALLOWED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
|
for (VMAddressSpace::AreaIterator it = addressSpace->GetAreaIterator();
|
||||||
VMArea* area = it.Next();) {
|
VMArea* area = it.Next();) {
|
||||||
if (area->id != RESERVED_AREA_ID) {
|
addr_t areaLast = area->Base() + (area->Size() - 1);
|
||||||
addr_t areaLast = area->Base() + (area->Size() - 1);
|
if (area->Base() < lastAddress && address < areaLast) {
|
||||||
if (area->Base() < lastAddress && address < areaLast) {
|
status_t error = cut_area(addressSpace, area, address,
|
||||||
status_t error = cut_area(addressSpace, area, address,
|
lastAddress, NULL, kernel);
|
||||||
lastAddress, NULL, kernel);
|
if (error != B_OK)
|
||||||
if (error != B_OK)
|
return error;
|
||||||
return error;
|
// Failing after already messing with areas is ugly, but we
|
||||||
// Failing after already messing with areas is ugly, but we
|
// can't do anything about it.
|
||||||
// can't do anything about it.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,29 +647,7 @@ vm_unreserve_address_range(team_id team, void* address, addr_t size)
|
|||||||
if (!locker.IsLocked())
|
if (!locker.IsLocked())
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
// check to see if this address space has entered DELETE state
|
return locker.AddressSpace()->UnreserveAddressRange((addr_t)address, size);
|
||||||
if (locker.AddressSpace()->IsBeingDeleted()) {
|
|
||||||
// okay, someone is trying to delete this address space now, so we can't
|
|
||||||
// insert the area, so back out
|
|
||||||
return B_BAD_TEAM_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search area list and remove any matching reserved ranges
|
|
||||||
addr_t endAddress = (addr_t)address + (size - 1);
|
|
||||||
for (VMAddressSpace::Iterator it = locker.AddressSpace()->GetIterator();
|
|
||||||
VMArea* area = it.Next();) {
|
|
||||||
// the area must be completely part of the reserved range
|
|
||||||
if (area->Base() + (area->Size() - 1) > endAddress)
|
|
||||||
break;
|
|
||||||
if (area->id == RESERVED_AREA_ID && area->Base() >= (addr_t)address) {
|
|
||||||
// remove reserved range
|
|
||||||
locker.AddressSpace()->RemoveArea(area);
|
|
||||||
locker.AddressSpace()->Put();
|
|
||||||
free(area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -688,31 +662,8 @@ vm_reserve_address_range(team_id team, void** _address, uint32 addressSpec,
|
|||||||
if (!locker.IsLocked())
|
if (!locker.IsLocked())
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
// check to see if this address space has entered DELETE state
|
return locker.AddressSpace()->ReserveAddressRange(_address, addressSpec,
|
||||||
if (locker.AddressSpace()->IsBeingDeleted()) {
|
size, flags);
|
||||||
// okay, someone is trying to delete this address space now, so we
|
|
||||||
// can't insert the area, let's back out
|
|
||||||
return B_BAD_TEAM_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
VMArea* area = VMArea::CreateReserved(locker.AddressSpace(), flags);
|
|
||||||
if (area == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status_t status = locker.AddressSpace()->InsertArea(_address, addressSpec,
|
|
||||||
size, area);
|
|
||||||
if (status != B_OK) {
|
|
||||||
free(area);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the area is now reserved!
|
|
||||||
|
|
||||||
area->cache_offset = area->Base();
|
|
||||||
// we cache the original base address here
|
|
||||||
|
|
||||||
locker.AddressSpace()->Get();
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2907,16 +2858,7 @@ vm_delete_areas(struct VMAddressSpace* addressSpace)
|
|||||||
addressSpace->WriteLock();
|
addressSpace->WriteLock();
|
||||||
|
|
||||||
// remove all reserved areas in this address space
|
// remove all reserved areas in this address space
|
||||||
|
addressSpace->UnreserveAllAddressRanges();
|
||||||
for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
|
|
||||||
VMArea* area = it.Next();) {
|
|
||||||
if (area->id == RESERVED_AREA_ID) {
|
|
||||||
// just remove it
|
|
||||||
addressSpace->RemoveArea(area);
|
|
||||||
addressSpace->Put();
|
|
||||||
free(area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete all the areas in this address space
|
// delete all the areas in this address space
|
||||||
while (VMArea* area = addressSpace->FirstArea())
|
while (VMArea* area = addressSpace->FirstArea())
|
||||||
@@ -2995,12 +2937,13 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
|||||||
|
|
||||||
map->ops->lock(map);
|
map->ops->lock(map);
|
||||||
|
|
||||||
for (VMAddressSpace::Iterator it = VMAddressSpace::Kernel()->GetIterator();
|
for (VMAddressSpace::AreaIterator it
|
||||||
|
= VMAddressSpace::Kernel()->GetAreaIterator();
|
||||||
VMArea* area = it.Next();) {
|
VMArea* area = it.Next();) {
|
||||||
addr_t areaStart = area->Base();
|
addr_t areaStart = area->Base();
|
||||||
addr_t areaEnd = areaStart + (area->Size() - 1);
|
addr_t areaEnd = areaStart + (area->Size() - 1);
|
||||||
|
|
||||||
if (area->id == RESERVED_AREA_ID || areaEnd < start)
|
if (areaEnd < start)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (areaStart > end) {
|
if (areaStart > end) {
|
||||||
@@ -4251,23 +4194,10 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
|
|
||||||
if (oldSize < newSize) {
|
if (oldSize < newSize) {
|
||||||
// We need to check if all areas of this cache can be resized
|
// We need to check if all areas of this cache can be resized
|
||||||
|
|
||||||
for (VMArea* current = cache->areas; current != NULL;
|
for (VMArea* current = cache->areas; current != NULL;
|
||||||
current = current->cache_next) {
|
current = current->cache_next) {
|
||||||
VMArea* next = current->address_space->NextArea(current);
|
if (!current->address_space->CanResizeArea(current, newSize))
|
||||||
if (next != NULL && next->Base() <= (current->Base() + newSize)) {
|
|
||||||
// If the area was created inside a reserved area, it can
|
|
||||||
// also be resized in that area
|
|
||||||
// TODO: if there is free space after the reserved area, it could
|
|
||||||
// be used as well...
|
|
||||||
if (next->id == RESERVED_AREA_ID
|
|
||||||
&& next->cache_offset <= current->Base()
|
|
||||||
&& next->Base() - 1 + next->Size()
|
|
||||||
>= current->Base() - 1 + newSize)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4282,35 +4212,12 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
|
|
||||||
for (VMArea* current = cache->areas; current != NULL;
|
for (VMArea* current = cache->areas; current != NULL;
|
||||||
current = current->cache_next) {
|
current = current->cache_next) {
|
||||||
VMArea* next = current->address_space->NextArea(current);
|
status = current->address_space->ResizeArea(current, newSize);
|
||||||
if (next != NULL && next->Base() <= (current->Base() + newSize)) {
|
|
||||||
if (next->id == RESERVED_AREA_ID
|
|
||||||
&& next->cache_offset <= current->Base()
|
|
||||||
&& next->Base() - 1 + next->Size()
|
|
||||||
>= current->Base() - 1 + newSize) {
|
|
||||||
// resize reserved area
|
|
||||||
addr_t offset = current->Base() + newSize - next->Base();
|
|
||||||
if (next->Size() <= offset) {
|
|
||||||
next->address_space->RemoveArea(next);
|
|
||||||
free(next);
|
|
||||||
} else {
|
|
||||||
next->address_space->ResizeAreaHead(next,
|
|
||||||
next->Size() - offset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic("resize situation for area %p has changed although we "
|
|
||||||
"should have the address space lock", current);
|
|
||||||
status = B_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status = current->address_space->ResizeAreaTail(current, newSize);
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// We also need to unmap all pages beyond the new size, if the area has
|
// We also need to unmap all pages beyond the new size, if the area has
|
||||||
// shrinked
|
// shrunk
|
||||||
if (newSize < oldSize) {
|
if (newSize < oldSize) {
|
||||||
vm_unmap_pages(current, current->Base() + newSize, oldSize - newSize,
|
vm_unmap_pages(current, current->Base() + newSize, oldSize - newSize,
|
||||||
false);
|
false);
|
||||||
@@ -4326,7 +4233,7 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
// This can fail, too, in which case we're seriously screwed.
|
// This can fail, too, in which case we're seriously screwed.
|
||||||
for (VMArea* current = cache->areas; current != NULL;
|
for (VMArea* current = cache->areas; current != NULL;
|
||||||
current = current->cache_next) {
|
current = current->cache_next) {
|
||||||
if (current->address_space->ResizeAreaTail(current, oldSize)
|
if (current->address_space->ResizeArea(current, oldSize)
|
||||||
!= B_OK) {
|
!= B_OK) {
|
||||||
panic("vm_resize_area(): Failed and not being able to restore "
|
panic("vm_resize_area(): Failed and not being able to restore "
|
||||||
"original state.");
|
"original state.");
|
||||||
@@ -4792,11 +4699,9 @@ _get_next_area_info(team_id team, int32* cookie, area_info* info, size_t size)
|
|||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
VMArea* area;
|
VMArea* area;
|
||||||
for (VMAddressSpace::Iterator it = locker.AddressSpace()->GetIterator();
|
for (VMAddressSpace::AreaIterator it
|
||||||
|
= locker.AddressSpace()->GetAreaIterator();
|
||||||
(area = it.Next()) != NULL;) {
|
(area = it.Next()) != NULL;) {
|
||||||
if (area->id == RESERVED_AREA_ID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (area->Base() > nextBase)
|
if (area->Base() > nextBase)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user