* Renamed VMAddressSpace::ResizeArea{Head,Tail}() to ShrinkArea{Head,Tail}()
to clarify that they never enlarge the area.
* Reimplemented VMKernelAddressSpace. It is somewhat inspired by Bonwick's
vmem resource allocator (though we have different requirements):
- We consider the complete address space to be divided into contiguous
ranges of type free, reserved, or area, each range being represented by
a VMKernelAddressRange object.
- The range objects are managed in an AVL tree and a doubly linked list
(the latter only for faster iteration) sorted by address. This provides
O(log(n)) lookup, insertion and removal.
- For each power of two size we maintain a list of free ranges of at least
that size. Thus for the most common case of B_ANY*_ADDRESS area
allocation, we find a free range in constant time (the rest of the
processing being O(log(n))) with a rather good fit. This should also
help avoiding address space fragmentation.
While the new implementation should be faster, particularly with an
increasing number of areas, I couldn't measure any difference in the -j2
haiku build. From a cursory test the -j8 build hasn't tangibly benefitted
either.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34528 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -62,6 +62,8 @@ public:
|
||||
|
||||
VMAddressSpace*& HashTableLink() { return fHashTableLink; }
|
||||
|
||||
virtual status_t InitObject();
|
||||
|
||||
virtual VMArea* FirstArea() const = 0;
|
||||
virtual VMArea* NextArea(VMArea* area) const = 0;
|
||||
|
||||
@@ -70,13 +72,15 @@ public:
|
||||
uint32 protection) = 0;
|
||||
virtual void DeleteArea(VMArea* area) = 0;
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area) = 0;
|
||||
size_t size, VMArea* area) = 0;
|
||||
virtual void RemoveArea(VMArea* area) = 0;
|
||||
|
||||
virtual bool CanResizeArea(VMArea* area, size_t newSize) = 0;
|
||||
virtual status_t ResizeArea(VMArea* area, size_t newSize) = 0;
|
||||
virtual status_t ResizeAreaHead(VMArea* area, size_t size) = 0;
|
||||
virtual status_t ResizeAreaTail(VMArea* area, size_t size) = 0;
|
||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize)
|
||||
= 0;
|
||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize)
|
||||
= 0;
|
||||
|
||||
virtual status_t ReserveAddressRange(void** _address,
|
||||
uint32 addressSpec, size_t size,
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
@@ -181,17 +183,24 @@ VMAddressSpace::RemoveAndPut()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VMAddressSpace::InitObject()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VMAddressSpace::Dump() const
|
||||
{
|
||||
kprintf("dump of address space at %p:\n", this);
|
||||
kprintf("id: 0x%lx\n", fID);
|
||||
kprintf("ref_count: %ld\n", fRefCount);
|
||||
kprintf("fault_count: %ld\n", fFaultCount);
|
||||
kprintf("id: %" B_PRId32 "\n", fID);
|
||||
kprintf("ref_count: %" B_PRId32 "\n", fRefCount);
|
||||
kprintf("fault_count: %" B_PRId32 "\n", fFaultCount);
|
||||
kprintf("translation_map: %p\n", &fTranslationMap);
|
||||
kprintf("base: 0x%lx\n", fBase);
|
||||
kprintf("end: 0x%lx\n", fEndAddress);
|
||||
kprintf("change_count: 0x%lx\n", fChangeCount);
|
||||
kprintf("base: %#" B_PRIxADDR "\n", fBase);
|
||||
kprintf("end: %#" B_PRIxADDR "\n", fEndAddress);
|
||||
kprintf("change_count: %" B_PRId32 "\n", fChangeCount);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,11 +214,17 @@ VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel,
|
||||
if (addressSpace == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = addressSpace->InitObject();
|
||||
if (status != B_OK) {
|
||||
delete addressSpace;
|
||||
return status;
|
||||
}
|
||||
|
||||
TRACE(("vm_create_aspace: team %ld (%skernel): %#lx bytes starting at "
|
||||
"%#lx => %p\n", id, kernel ? "!" : "", size, base, addressSpace));
|
||||
|
||||
// initialize the corresponding translation map
|
||||
status_t status = arch_vm_translation_map_init_map(
|
||||
status = arch_vm_translation_map_init_map(
|
||||
&addressSpace->fTranslationMap, kernel);
|
||||
if (status != B_OK) {
|
||||
delete addressSpace;
|
||||
@@ -321,9 +336,9 @@ VMAddressSpace::_DumpListCommand(int argc, char** argv)
|
||||
areaSize += area->Size();
|
||||
}
|
||||
}
|
||||
kprintf("%p %6ld %#010lx %#10lx %10ld %10lld\n",
|
||||
space, space->ID(), space->Base(), space->EndAddress(), areaCount,
|
||||
areaSize);
|
||||
kprintf("%p %6" B_PRId32 " %#010" B_PRIxADDR " %#10" B_PRIxADDR
|
||||
" %10" B_PRId32 " %10" B_PRIdOFF "\n", space, space->ID(),
|
||||
space->Base(), space->EndAddress(), areaCount, areaSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <heap.h>
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* 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 VM_KERNEL_ADDRESS_SPACE_H
|
||||
#define VM_KERNEL_ADDRESS_SPACE_H
|
||||
@@ -21,6 +17,8 @@ public:
|
||||
size_t size);
|
||||
virtual ~VMKernelAddressSpace();
|
||||
|
||||
virtual status_t InitObject();
|
||||
|
||||
virtual VMArea* FirstArea() const;
|
||||
virtual VMArea* NextArea(VMArea* area) const;
|
||||
|
||||
@@ -29,13 +27,13 @@ public:
|
||||
uint32 protection);
|
||||
virtual void DeleteArea(VMArea* area);
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area);
|
||||
size_t size, VMArea* area);
|
||||
virtual void RemoveArea(VMArea* area);
|
||||
|
||||
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
||||
virtual status_t ResizeArea(VMArea* area, size_t newSize);
|
||||
virtual status_t ResizeAreaHead(VMArea* area, size_t size);
|
||||
virtual status_t ResizeAreaTail(VMArea* area, size_t size);
|
||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize);
|
||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize);
|
||||
|
||||
virtual status_t ReserveAddressRange(void** _address,
|
||||
uint32 addressSpec, size_t size,
|
||||
@@ -47,15 +45,37 @@ public:
|
||||
virtual void Dump() const;
|
||||
|
||||
private:
|
||||
status_t _InsertAreaIntoReservedRegion(addr_t start,
|
||||
size_t size, VMKernelArea* area);
|
||||
status_t _InsertAreaSlot(addr_t start, addr_t size,
|
||||
addr_t end, uint32 addressSpec,
|
||||
VMKernelArea* area);
|
||||
typedef VMKernelAddressRange Range;
|
||||
typedef VMKernelAddressRangeTree RangeTree;
|
||||
typedef DoublyLinkedList<Range,
|
||||
DoublyLinkedListMemberGetLink<Range, &Range::listLink> >
|
||||
RangeList;
|
||||
typedef DoublyLinkedList<Range, VMKernelAddressRangeGetFreeListLink>
|
||||
RangeFreeList;
|
||||
|
||||
private:
|
||||
VMKernelAreaList fAreas;
|
||||
mutable VMArea* fAreaHint;
|
||||
inline void _FreeListInsertRange(Range* range, size_t size);
|
||||
inline void _FreeListRemoveRange(Range* range, size_t size);
|
||||
|
||||
void _InsertRange(Range* range);
|
||||
void _RemoveRange(Range* range);
|
||||
|
||||
status_t _AllocateRange(addr_t address,
|
||||
uint32 addressSpec, size_t size,
|
||||
bool allowReservedRange, Range*& _range);
|
||||
Range* _FindFreeRange(addr_t start, size_t size,
|
||||
size_t alignment, uint32 addressSpec,
|
||||
bool allowReservedRange,
|
||||
addr_t& _foundAddress);
|
||||
void _FreeRange(Range* range);
|
||||
|
||||
void _CheckStructures() const;
|
||||
|
||||
private:
|
||||
RangeTree fRangeTree;
|
||||
RangeList fRangeList;
|
||||
RangeFreeList* fFreeLists;
|
||||
int fFreeListCount;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -39,13 +39,3 @@ VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,109 @@
|
||||
#define VM_KERNEL_AREA_H
|
||||
|
||||
|
||||
#include <util/AVLTree.h>
|
||||
|
||||
#include <vm/VMArea.h>
|
||||
|
||||
|
||||
struct VMKernelAddressSpace;
|
||||
struct VMKernelArea;
|
||||
|
||||
|
||||
struct VMKernelArea : VMArea {
|
||||
struct VMKernelAddressRange : AVLTreeNode {
|
||||
public:
|
||||
// range types
|
||||
enum {
|
||||
RANGE_FREE,
|
||||
RANGE_RESERVED,
|
||||
RANGE_AREA
|
||||
};
|
||||
|
||||
public:
|
||||
DoublyLinkedListLink<VMKernelAddressRange> listLink;
|
||||
addr_t base;
|
||||
size_t size;
|
||||
union {
|
||||
VMKernelArea* area;
|
||||
struct {
|
||||
addr_t base;
|
||||
uint32 flags;
|
||||
} reserved;
|
||||
DoublyLinkedListLink<VMKernelAddressRange> freeListLink;
|
||||
};
|
||||
int type;
|
||||
|
||||
public:
|
||||
VMKernelAddressRange(addr_t base, size_t size, int type)
|
||||
:
|
||||
base(base),
|
||||
size(size),
|
||||
type(type)
|
||||
{
|
||||
}
|
||||
|
||||
VMKernelAddressRange(addr_t base, size_t size,
|
||||
const VMKernelAddressRange* other)
|
||||
:
|
||||
base(base),
|
||||
size(size),
|
||||
type(other->type)
|
||||
{
|
||||
if (type == RANGE_RESERVED) {
|
||||
reserved.base = other->reserved.base;
|
||||
reserved.flags = other->reserved.flags;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct VMKernelAddressRangeTreeDefinition {
|
||||
typedef addr_t Key;
|
||||
typedef VMKernelAddressRange Value;
|
||||
|
||||
AVLTreeNode* GetAVLTreeNode(Value* value) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
Value* GetValue(AVLTreeNode* node) const
|
||||
{
|
||||
return static_cast<Value*>(node);
|
||||
}
|
||||
|
||||
int Compare(addr_t a, const Value* _b) const
|
||||
{
|
||||
addr_t b = _b->base;
|
||||
if (a == b)
|
||||
return 0;
|
||||
return a < b ? -1 : 1;
|
||||
}
|
||||
|
||||
int Compare(const Value* a, const Value* b) const
|
||||
{
|
||||
return Compare(a->base, b);
|
||||
}
|
||||
};
|
||||
|
||||
typedef AVLTree<VMKernelAddressRangeTreeDefinition> VMKernelAddressRangeTree;
|
||||
|
||||
|
||||
struct VMKernelAddressRangeGetFreeListLink {
|
||||
typedef DoublyLinkedListLink<VMKernelAddressRange> Link;
|
||||
|
||||
inline Link* operator()(VMKernelAddressRange* range) const
|
||||
{
|
||||
return &range->freeListLink;
|
||||
}
|
||||
|
||||
inline const Link* operator()(const VMKernelAddressRange* range) const
|
||||
{
|
||||
return &range->freeListLink;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct VMKernelArea : VMArea, AVLTreeNode {
|
||||
VMKernelArea(VMAddressSpace* addressSpace,
|
||||
uint32 wiring, uint32 protection);
|
||||
~VMKernelArea();
|
||||
@@ -20,34 +116,15 @@ struct VMKernelArea : VMArea {
|
||||
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; }
|
||||
VMKernelAddressRange* Range() const
|
||||
{ return fRange; }
|
||||
void SetRange(VMKernelAddressRange* range)
|
||||
{ fRange = range; }
|
||||
|
||||
private:
|
||||
DoublyLinkedListLink<VMKernelArea> fAddressSpaceLink;
|
||||
VMKernelAddressRange* fRange;
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -41,7 +41,7 @@ is_valid_spot(addr_t base, addr_t alignedBase, addr_t size, addr_t limit)
|
||||
|
||||
VMUserAddressSpace::VMUserAddressSpace(team_id id, addr_t base, size_t size)
|
||||
:
|
||||
VMAddressSpace(id, base, size, "kernel address space"),
|
||||
VMAddressSpace(id, base, size, "address space"),
|
||||
fAreaHint(NULL)
|
||||
{
|
||||
}
|
||||
@@ -118,7 +118,7 @@ VMUserAddressSpace::LookupArea(addr_t address) const
|
||||
*/
|
||||
status_t
|
||||
VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* _area)
|
||||
size_t size, VMArea* _area)
|
||||
{
|
||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||
|
||||
@@ -225,22 +225,21 @@ VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
||||
addr_t offset = area->Base() + newSize - next->Base();
|
||||
if (next->Size() <= offset) {
|
||||
RemoveArea(next);
|
||||
free(next);
|
||||
delete next;
|
||||
} else {
|
||||
status_t error = ResizeAreaHead(next, next->Size() - offset);
|
||||
status_t error = ShrinkAreaHead(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.
|
||||
area->SetSize(newSize);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VMUserAddressSpace::ResizeAreaHead(VMArea* area, size_t size)
|
||||
VMUserAddressSpace::ShrinkAreaHead(VMArea* area, size_t size)
|
||||
{
|
||||
size_t oldSize = area->Size();
|
||||
if (size == oldSize)
|
||||
@@ -254,7 +253,7 @@ VMUserAddressSpace::ResizeAreaHead(VMArea* area, size_t size)
|
||||
|
||||
|
||||
status_t
|
||||
VMUserAddressSpace::ResizeAreaTail(VMArea* area, size_t size)
|
||||
VMUserAddressSpace::ShrinkAreaTail(VMArea* area, size_t size)
|
||||
{
|
||||
size_t oldSize = area->Size();
|
||||
if (size == oldSize)
|
||||
@@ -283,7 +282,7 @@ VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||
|
||||
status_t status = InsertArea(_address, addressSpec, size, area);
|
||||
if (status != B_OK) {
|
||||
free(area);
|
||||
delete area;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -316,7 +315,7 @@ VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
||||
// remove reserved range
|
||||
RemoveArea(area);
|
||||
Put();
|
||||
free(area);
|
||||
delete area;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +331,7 @@ VMUserAddressSpace::UnreserveAllAddressRanges()
|
||||
if (area->id == RESERVED_AREA_ID) {
|
||||
RemoveArea(area);
|
||||
Put();
|
||||
free(area);
|
||||
delete area;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,7 +395,7 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||
// the new area fully covers the reversed range
|
||||
fAreas.Remove(next);
|
||||
Put();
|
||||
free(next);
|
||||
delete next;
|
||||
} else {
|
||||
// resize the reserved range behind the area
|
||||
next->SetBase(next->Base() + size);
|
||||
@@ -556,7 +555,7 @@ second_chance:
|
||||
|
||||
foundSpot = true;
|
||||
area->SetBase(alignedBase);
|
||||
free(next);
|
||||
delete next;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* 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 VM_USER_ADDRESS_SPACE_H
|
||||
#define VM_USER_ADDRESS_SPACE_H
|
||||
@@ -29,13 +25,13 @@ public:
|
||||
uint32 protection);
|
||||
virtual void DeleteArea(VMArea* area);
|
||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||
addr_t size, VMArea* area);
|
||||
size_t size, VMArea* area);
|
||||
virtual void RemoveArea(VMArea* area);
|
||||
|
||||
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
||||
virtual status_t ResizeArea(VMArea* area, size_t newSize);
|
||||
virtual status_t ResizeAreaHead(VMArea* area, size_t size);
|
||||
virtual status_t ResizeAreaTail(VMArea* area, size_t size);
|
||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize);
|
||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize);
|
||||
|
||||
virtual status_t ReserveAddressRange(void** _address,
|
||||
uint32 addressSpec, size_t size,
|
||||
|
||||
@@ -45,7 +45,9 @@ VMUserArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||
VMUserArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags)
|
||||
{
|
||||
VMUserArea* area = new(nogrow) VMUserArea(addressSpace, 0, 0);
|
||||
if (area != NULL)
|
||||
if (area != NULL) {
|
||||
area->id = RESERVED_AREA_ID;
|
||||
area->protection = flags;
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
||||
size_t oldSize = area->Size();
|
||||
size_t newSize = address - area->Base();
|
||||
|
||||
status_t error = addressSpace->ResizeAreaTail(area, newSize);
|
||||
status_t error = addressSpace->ShrinkAreaTail(area, newSize);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -350,7 +350,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
||||
&& list_is_empty(&cache->consumers)) {
|
||||
error = cache->Resize(cache->virtual_base + newSize);
|
||||
if (error != B_OK) {
|
||||
addressSpace->ResizeAreaTail(area, oldSize);
|
||||
addressSpace->ShrinkAreaTail(area, oldSize);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@@ -368,7 +368,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
||||
vm_unmap_pages(area, oldBase, newBase - oldBase, false);
|
||||
|
||||
// resize the area
|
||||
status_t error = addressSpace->ResizeAreaHead(area, newSize);
|
||||
status_t error = addressSpace->ShrinkAreaHead(area, newSize);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -392,7 +392,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
||||
|
||||
// resize the area
|
||||
addr_t oldSize = area->Size();
|
||||
status_t error = addressSpace->ResizeAreaTail(area, firstNewSize);
|
||||
status_t error = addressSpace->ShrinkAreaTail(area, firstNewSize);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -408,7 +408,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
||||
B_EXACT_ADDRESS, area->wiring, area->protection, REGION_NO_PRIVATE_MAP,
|
||||
&secondArea, area->name, false, kernel);
|
||||
if (error != B_OK) {
|
||||
addressSpace->ResizeAreaTail(area, oldSize);
|
||||
addressSpace->ShrinkAreaTail(area, oldSize);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user