diff --git a/headers/private/kernel/vm/VMAddressSpace.h b/headers/private/kernel/vm/VMAddressSpace.h index 2b4a1c5c48..649359b49a 100644 --- a/headers/private/kernel/vm/VMAddressSpace.h +++ b/headers/private/kernel/vm/VMAddressSpace.h @@ -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; diff --git a/headers/private/kernel/vm/VMArea.h b/headers/private/kernel/vm/VMArea.h index 3b910f7d26..9d57968b3f 100644 --- a/headers/private/kernel/vm/VMArea.h +++ b/headers/private/kernel/vm/VMArea.h @@ -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& AddressSpaceLink() - { return fAddressSpaceLink; } - const DoublyLinkedListLink& 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 fAddressSpaceLink; +protected: addr_t fBase; size_t fSize; }; -struct VMAddressSpaceAreaGetLink { - inline DoublyLinkedListLink* operator()(VMArea* area) const - { - return &area->AddressSpaceLink(); - } - - inline const DoublyLinkedListLink* operator()( - const VMArea* area) const - { - return &area->AddressSpaceLink(); - } -}; - -typedef DoublyLinkedList - VMAddressSpaceAreaList; - - struct VMAreaHashDefinition { typedef area_id KeyType; typedef VMArea ValueType; diff --git a/src/system/kernel/vm/Jamfile b/src/system/kernel/vm/Jamfile index 90759e498d..78f5cf8980 100644 --- a/src/system/kernel/vm/Jamfile +++ b/src/system/kernel/vm/Jamfile @@ -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) ; diff --git a/src/system/kernel/vm/VMArea.cpp b/src/system/kernel/vm/VMArea.cpp index e74854a7c1..2f702c76d2 100644 --- a/src/system/kernel/vm/VMArea.cpp +++ b/src/system/kernel/vm/VMArea.cpp @@ -11,7 +11,6 @@ #include #include -#include #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; diff --git a/src/system/kernel/vm/VMKernelAddressSpace.cpp b/src/system/kernel/vm/VMKernelAddressSpace.cpp index 93d8662729..29c1342f7c 100644 --- a/src/system/kernel/vm/VMKernelAddressSpace.cpp +++ b/src/system/kernel/vm/VMKernelAddressSpace.cpp @@ -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(_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(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(_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(_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(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(_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 diff --git a/src/system/kernel/vm/VMKernelAddressSpace.h b/src/system/kernel/vm/VMKernelAddressSpace.h index 6374ab2d5f..5655d3501b 100644 --- a/src/system/kernel/vm/VMKernelAddressSpace.h +++ b/src/system/kernel/vm/VMKernelAddressSpace.h @@ -12,6 +12,8 @@ #include +#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; }; diff --git a/src/system/kernel/vm/VMKernelArea.cpp b/src/system/kernel/vm/VMKernelArea.cpp new file mode 100644 index 0000000000..76dac2a591 --- /dev/null +++ b/src/system/kernel/vm/VMKernelArea.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the NewOS License. + */ + + +#include "VMKernelArea.h" + +#include +#include + + +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; +} diff --git a/src/system/kernel/vm/VMKernelArea.h b/src/system/kernel/vm/VMKernelArea.h new file mode 100644 index 0000000000..cf9f519238 --- /dev/null +++ b/src/system/kernel/vm/VMKernelArea.h @@ -0,0 +1,53 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the NewOS License. + */ +#ifndef VM_KERNEL_AREA_H +#define VM_KERNEL_AREA_H + + +#include + + +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& AddressSpaceLink() + { return fAddressSpaceLink; } + const DoublyLinkedListLink& AddressSpaceLink() const + { return fAddressSpaceLink; } + +private: + DoublyLinkedListLink fAddressSpaceLink; +}; + + +struct VMKernelAreaGetLink { + inline DoublyLinkedListLink* operator()( + VMKernelArea* area) const + { + return &area->AddressSpaceLink(); + } + + inline const DoublyLinkedListLink* operator()( + const VMKernelArea* area) const + { + return &area->AddressSpaceLink(); + } +}; + +typedef DoublyLinkedList VMKernelAreaList; + + +#endif // VM_KERNEL_AREA_H diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp b/src/system/kernel/vm/VMUserAddressSpace.cpp index f5ad0e4796..0f879343d6 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.cpp +++ b/src/system/kernel/vm/VMUserAddressSpace.cpp @@ -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(_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(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(_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(_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(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(_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 diff --git a/src/system/kernel/vm/VMUserAddressSpace.h b/src/system/kernel/vm/VMUserAddressSpace.h index e30ed12763..11922831a1 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.h +++ b/src/system/kernel/vm/VMUserAddressSpace.h @@ -12,6 +12,8 @@ #include +#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; }; diff --git a/src/system/kernel/vm/VMUserArea.cpp b/src/system/kernel/vm/VMUserArea.cpp new file mode 100644 index 0000000000..5cf35d1451 --- /dev/null +++ b/src/system/kernel/vm/VMUserArea.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the NewOS License. + */ + + +#include "VMUserArea.h" + +#include +#include + + +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; +} diff --git a/src/system/kernel/vm/VMUserArea.h b/src/system/kernel/vm/VMUserArea.h new file mode 100644 index 0000000000..fca6951442 --- /dev/null +++ b/src/system/kernel/vm/VMUserArea.h @@ -0,0 +1,53 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the NewOS License. + */ +#ifndef VM_USER_AREA_H +#define VM_USER_AREA_H + + +#include + + +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& AddressSpaceLink() + { return fAddressSpaceLink; } + const DoublyLinkedListLink& AddressSpaceLink() const + { return fAddressSpaceLink; } + +private: + DoublyLinkedListLink fAddressSpaceLink; +}; + + +struct VMUserAreaGetLink { + inline DoublyLinkedListLink* operator()( + VMUserArea* area) const + { + return &area->AddressSpaceLink(); + } + + inline const DoublyLinkedListLink* operator()( + const VMUserArea* area) const + { + return &area->AddressSpaceLink(); + } +}; + +typedef DoublyLinkedList VMUserAreaList; + + +#endif // VM_USER_AREA_H diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index b9efce05c4..7dfc4a421f 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -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); }