Author: bonefish Date: 2009-12-04 15:45:08 +0100 (Fri, 04 Dec 2009) New Revision: 34492 Changeset: http://dev.haiku-os.org/changeset/34492/haiku Added: haiku/trunk/src/system/kernel/vm/VMKernelAddressSpace.cpp haiku/trunk/src/system/kernel/vm/VMKernelAddressSpace.h haiku/trunk/src/system/kernel/vm/VMUserAddressSpace.cpp haiku/trunk/src/system/kernel/vm/VMUserAddressSpace.h Modified: haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h haiku/trunk/headers/private/kernel/vm/VMArea.h haiku/trunk/src/system/kernel/vm/Jamfile haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp Log: Made VMAddressSpace an abstract base class and moved the area management into new derived classes VM{Kernel,User}AddressSpace. Currently those are identical, but that will change. Modified: haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h 2009-12-04 13:33:25 UTC (rev 34491) +++ haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h 2009-12-04 14:45:08 UTC (rev 34492) @@ -23,8 +23,8 @@ public: VMAddressSpace(team_id id, addr_t base, - size_t size, bool kernel); - ~VMAddressSpace(); + size_t size, const char* name); + virtual ~VMAddressSpace(); static status_t Init(); static status_t InitPostSem(); @@ -58,26 +58,31 @@ void IncrementChangeCount() { fChangeCount++; } - VMArea* FirstArea() const; + inline AreaIterator GetAreaIterator(); - VMArea* LookupArea(addr_t address) const; - status_t InsertArea(void** _address, uint32 addressSpec, - addr_t size, VMArea* area); - void RemoveArea(VMArea* area); + VMAddressSpace*& HashTableLink() { return fHashTableLink; } - 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 ResizeAreaTail(VMArea* area, size_t size); + virtual VMArea* FirstArea() const = 0; + virtual VMArea* NextArea(VMArea* area) const = 0; - status_t ReserveAddressRange(void** _address, + virtual VMArea* LookupArea(addr_t address) const = 0; + virtual status_t InsertArea(void** _address, uint32 addressSpec, + addr_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 ReserveAddressRange(void** _address, uint32 addressSpec, size_t size, - uint32 flags); - status_t UnreserveAddressRange(addr_t address, - size_t size); - void UnreserveAllAddressRanges(); + uint32 flags) = 0; + virtual status_t UnreserveAddressRange(addr_t address, + size_t size) = 0; + virtual void UnreserveAllAddressRanges() = 0; - inline AreaIterator GetAreaIterator(); + virtual void Dump() const; static status_t Create(team_id teamID, addr_t base, size_t size, bool kernel, @@ -94,26 +99,14 @@ static VMAddressSpace* Get(team_id teamID); - VMAddressSpace*& HashTableLink() { return fHashTableLink; } - - void Dump() const; - -private: - status_t _InsertAreaIntoReservedRegion(addr_t start, - size_t size, VMArea* area); - status_t _InsertAreaSlot(addr_t start, addr_t size, - addr_t end, uint32 addressSpec, - VMArea* area); - +protected: static int _DumpCommand(int argc, char** argv); static int _DumpListCommand(int argc, char** argv); -private: - friend class Iterator; - +protected: struct HashDefinition; -private: +protected: VMAddressSpace* fHashTableLink; addr_t fBase; addr_t fEndAddress; // base + (size - 1) @@ -124,8 +117,6 @@ int32 fFaultCount; int32 fChangeCount; vm_translation_map fTranslationMap; - VMAddressSpaceAreaList fAreas; - mutable VMArea* fAreaHint; bool fDeleting; static VMAddressSpace* sKernelAddressSpace; }; @@ -139,9 +130,9 @@ AreaIterator(VMAddressSpace* addressSpace) : - fIterator(addressSpace->fAreas.GetIterator()) + fAddressSpace(addressSpace), + fNext(addressSpace->FirstArea()) { - _SkipReserved(); } bool HasNext() const @@ -152,40 +143,21 @@ VMArea* Next() { VMArea* result = fNext; - _SkipReserved(); + fNext = fAddressSpace->NextArea(fNext); return result; } void Rewind() { - fIterator.Rewind(); - _SkipReserved(); + fNext = fAddressSpace->FirstArea(); } private: - void _SkipReserved() - { - while ((fNext = fIterator.Next()) != NULL - && fNext->id == RESERVED_AREA_ID) { - } - } - -private: - VMAddressSpaceAreaList::Iterator fIterator; - VMArea* fNext; + VMAddressSpace* fAddressSpace; + VMArea* fNext; }; -inline VMArea* -VMAddressSpace::FirstArea() const -{ - VMArea* area = fAreas.Head(); - while (area != NULL && area->id == RESERVED_AREA_ID) - area = fAreas.GetNext(area); - return area; -} - - inline VMAddressSpace::AreaIterator VMAddressSpace::GetAreaIterator() { Modified: haiku/trunk/headers/private/kernel/vm/VMArea.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/VMArea.h 2009-12-04 13:33:25 UTC (rev 34491) +++ haiku/trunk/headers/private/kernel/vm/VMArea.h 2009-12-04 14:45:08 UTC (rev 34492) @@ -18,6 +18,8 @@ struct VMAddressSpace; struct VMCache; +struct VMKernelAddressSpace; +struct VMUserAddressSpace; struct VMArea { @@ -59,6 +61,8 @@ private: friend class VMAddressSpace; + friend class VMKernelAddressSpace; + friend class VMUserAddressSpace; private: void SetBase(addr_t base) { fBase = base; } Modified: haiku/trunk/src/system/kernel/vm/Jamfile =================================================================== --- haiku/trunk/src/system/kernel/vm/Jamfile 2009-12-04 13:33:25 UTC (rev 34491) +++ haiku/trunk/src/system/kernel/vm/Jamfile 2009-12-04 14:45:08 UTC (rev 34492) @@ -15,8 +15,9 @@ VMArea.cpp VMCache.cpp VMDeviceCache.cpp + VMKernelAddressSpace.cpp VMNullCache.cpp - #vm_tests.c + VMUserAddressSpace.cpp : $(TARGET_KERNEL_PIC_CCFLAGS) ; Modified: haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-04 13:33:25 UTC (rev 34491) +++ haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-04 14:45:08 UTC (rev 34492) @@ -21,7 +21,10 @@ #include <vm/vm.h> #include <vm/VMArea.h> +#include "VMKernelAddressSpace.h" +#include "VMUserAddressSpace.h" + //#define TRACE_VM #ifdef TRACE_VM # define TRACE(x) dprintf x @@ -33,17 +36,6 @@ #define ASPACE_HASH_TABLE_SIZE 1024 -/*! Verifies that an area with the given aligned base and size fits into - the spot defined by base and limit and checks for overflows. -*/ -static inline bool -is_valid_spot(addr_t base, addr_t alignedBase, addr_t size, addr_t limit) -{ - return (alignedBase >= base && alignedBase + (size - 1) > alignedBase - && alignedBase + (size - 1) <= limit); -} - - // #pragma mark - AddressSpaceHashDefinition @@ -84,7 +76,7 @@ VMAddressSpace::VMAddressSpace(team_id id, addr_t base, size_t size, - bool kernel) + const char* name) : fBase(base), fEndAddress(base + (size - 1)), @@ -93,18 +85,15 @@ fRefCount(1), fFaultCount(0), fChangeCount(0), - fAreaHint(NULL), fDeleting(false) { - rw_lock_init(&fLock, kernel ? "kernel address space" : "address space"); + rw_lock_init(&fLock, name); +// rw_lock_init(&fLock, kernel ? "kernel address space" : "address space"); } VMAddressSpace::~VMAddressSpace() { - if (this == sKernelAddressSpace) - panic("deleting the kernel aspace!\n"); - TRACE(("VMAddressSpace::~VMAddressSpace: called on aspace %" B_PRId32 "\n", ID())); @@ -192,12 +181,27 @@ } +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("translation_map: %p\n", &fTranslationMap); + kprintf("base: 0x%lx\n", fBase); + kprintf("end: 0x%lx\n", fEndAddress); + kprintf("change_count: 0x%lx\n", fChangeCount); +} + + /*static*/ status_t VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel, VMAddressSpace** _addressSpace) { - VMAddressSpace* addressSpace = new(nogrow) VMAddressSpace(teamID, base, - size, kernel); + VMAddressSpace* addressSpace = kernel + ? (VMAddressSpace*)new(nogrow) VMKernelAddressSpace(teamID, base, size) + : (VMAddressSpace*)new(nogrow) VMUserAddressSpace(teamID, base, size); if (addressSpace == NULL) return B_NO_MEMORY; @@ -273,585 +277,6 @@ } -//! You must hold the address space's read lock. -VMArea* -VMAddressSpace::LookupArea(addr_t address) const -{ - // check the area hint first - if (fAreaHint != NULL && fAreaHint->ContainsAddress(address)) - return fAreaHint; - - for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator(); - VMArea* area = it.Next();) { - if (area->id == RESERVED_AREA_ID) - continue; - - if (area->ContainsAddress(address)) { - fAreaHint = area; - return area; - } - } - - return NULL; -} - - -/*! This inserts the area you pass into the address space. - It will also set the "_address" argument to its base address when - the call succeeds. - You need to hold the VMAddressSpace write lock. -*/ -status_t -VMAddressSpace::InsertArea(void** _address, uint32 addressSpec, addr_t size, - VMArea* area) -{ - addr_t searchBase, searchEnd; - status_t status; - - switch (addressSpec) { - case B_EXACT_ADDRESS: - searchBase = (addr_t)*_address; - searchEnd = (addr_t)*_address + (size - 1); - break; - - case B_BASE_ADDRESS: - searchBase = (addr_t)*_address; - searchEnd = fEndAddress; - break; - - case B_ANY_ADDRESS: - case B_ANY_KERNEL_ADDRESS: - case B_ANY_KERNEL_BLOCK_ADDRESS: - searchBase = fBase; - // TODO: remove this again when vm86 mode is moved into the kernel - // completely (currently needs a userland address space!) - if (searchBase == USER_BASE) - searchBase = USER_BASE_ANY; - searchEnd = fEndAddress; - break; - - default: - return B_BAD_VALUE; - } - - status = _InsertAreaSlot(searchBase, size, searchEnd, addressSpec, area); - if (status == B_OK) { - *_address = (void*)area->Base(); - fFreeSpace -= area->Size(); - } - - return status; -} - - -//! You must hold the address space's write lock. -void -VMAddressSpace::RemoveArea(VMArea* area) -{ - fAreas.Remove(area); - - if (area->id != RESERVED_AREA_ID) { - IncrementChangeCount(); - fFreeSpace += area->Size(); - - if (area == fAreaHint) - fAreaHint = NULL; - } -} - - -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 -VMAddressSpace::ResizeAreaHead(VMArea* area, size_t size) -{ - size_t oldSize = area->Size(); - if (size == oldSize) - return B_OK; - - area->SetBase(area->Base() + oldSize - size); - area->SetSize(size); - - return B_OK; -} - - -status_t -VMAddressSpace::ResizeAreaTail(VMArea* area, size_t size) -{ - size_t oldSize = area->Size(); - if (size == oldSize) - return B_OK; - - area->SetSize(size); - - return B_OK; -} - - -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 -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("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("area_hint: %p\n", fAreaHint); - - kprintf("area_list:\n"); - - for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator(); - VMArea* area = it.Next();) { - kprintf(" area 0x%lx: ", area->id); - kprintf("base_addr = 0x%lx ", area->Base()); - kprintf("size = 0x%lx ", area->Size()); - kprintf("name = '%s' ", area->name); - kprintf("protection = 0x%lx\n", area->protection); - } -} - - -/*! Finds a reserved area that covers the region spanned by \a start and - \a size, inserts the \a area into that region and makes sure that - there are reserved regions for the remaining parts. -*/ -status_t -VMAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size, - VMArea* area) -{ - VMArea* next; - - for (VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator(); - (next = it.Next()) != NULL;) { - if (next->Base() <= start - && next->Base() + (next->Size() - 1) >= start + (size - 1)) { - // This area covers the requested range - if (next->id != RESERVED_AREA_ID) { - // but it's not reserved space, it's a real area - return B_BAD_VALUE; - } - - break; - } - } - - if (next == NULL) - return B_ENTRY_NOT_FOUND; - - // Now we have to transfer the requested part of the reserved - // range to the new area - and remove, resize or split the old - // reserved area. - - if (start == next->Base()) { - // the area starts at the beginning of the reserved range - fAreas.Insert(next, area); - - if (size == next->Size()) { - // the new area fully covers the reversed range - fAreas.Remove(next); - Put(); - free(next); - } else { - // resize the reserved range behind the area - next->SetBase(next->Base() + size); - next->SetSize(next->Size() - size); - } - } else if (start + size == next->Base() + next->Size()) { - // the area is at the end of the reserved range - fAreas.Insert(fAreas.GetNext(next), area); - - // resize the reserved range before the area - next->SetSize(start - next->Base()); - } 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); - if (reserved == NULL) - return B_NO_MEMORY; - - Get(); - fAreas.Insert(fAreas.GetNext(next), reserved); - fAreas.Insert(reserved, area); - - // resize regions - reserved->SetSize(next->Base() + next->Size() - start - size); - next->SetSize(start - next->Base()); - reserved->SetBase(start + size); - reserved->cache_offset = next->cache_offset; - } - - area->SetBase(start); - area->SetSize(size); - IncrementChangeCount(); - - return B_OK; -} - - -/*! Must be called with this address space's write lock held */ -status_t -VMAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end, - uint32 addressSpec, VMArea* area) -{ - VMArea* last = NULL; - VMArea* next; - bool foundSpot = false; - - TRACE(("VMAddressSpace::InsertAreaSlot: address space %p, start 0x%lx, " - "size %ld, end 0x%lx, addressSpec %ld, area %p\n", this, start, - size, end, addressSpec, area)); - - // do some sanity checking - if (start < fBase || size == 0 || end > fEndAddress - || start + (size - 1) > end) - return B_BAD_ADDRESS; - - if (addressSpec == B_EXACT_ADDRESS && area->id != RESERVED_AREA_ID) { - // search for a reserved area - status_t status = _InsertAreaIntoReservedRegion(start, size, area); - if (status == B_OK || status == B_BAD_VALUE) - return status; - - // There was no reserved area, and the slot doesn't seem to be used - // already - // TODO: this could be further optimized. - } - - size_t alignment = B_PAGE_SIZE; - if (addressSpec == B_ANY_KERNEL_BLOCK_ADDRESS) { - // align the memory to the next power of two of the size - while (alignment < size) - alignment <<= 1; - } - - start = ROUNDUP(start, alignment); - - // walk up to the spot where we should start searching -second_chance: - VMAddressSpaceAreaList::Iterator it = fAreas.GetIterator(); - while ((next = it.Next()) != NULL) { - if (next->Base() > start + (size - 1)) { - // we have a winner - break; - } - - last = next; - } - - // find the right spot depending on the address specification - the area - // will be inserted directly after "last" ("next" is not referenced anymore) - - switch (addressSpec) { - case B_ANY_ADDRESS: - case B_ANY_KERNEL_ADDRESS: - case B_ANY_KERNEL_BLOCK_ADDRESS: - { - // find a hole big enough for a new area - if (last == NULL) { - // see if we can build it at the beginning of the virtual map - addr_t alignedBase = ROUNDUP(fBase, alignment); - if (is_valid_spot(fBase, alignedBase, size, - next == NULL ? end : next->Base())) { - foundSpot = true; - area->SetBase(alignedBase); - break; - } - - last = next; - next = it.Next(); - } - - // keep walking - while (next != NULL) { - addr_t alignedBase = ROUNDUP(last->Base() + last->Size(), - alignment); - if (is_valid_spot(last->Base() + (last->Size() - 1), - alignedBase, size, next->Base())) { - foundSpot = true; - area->SetBase(alignedBase); - break; - } - - last = next; - next = it.Next(); - } - - if (foundSpot) - break; - - addr_t alignedBase = ROUNDUP(last->Base() + last->Size(), - alignment); - if (is_valid_spot(last->Base() + (last->Size() - 1), alignedBase, - size, end)) { - // got a spot - foundSpot = true; - area->SetBase(alignedBase); - break; - } else if (area->id != RESERVED_AREA_ID) { - // We didn't find a free spot - if there are any reserved areas, - // we can now test those for free space - // TODO: it would make sense to start with the biggest of them - it.Rewind(); - next = it.Next(); - for (last = NULL; next != NULL; next = it.Next()) { - if (next->id != RESERVED_AREA_ID) { - last = next; - continue; - } - - // TODO: take free space after the reserved area into - // account! - addr_t alignedBase = ROUNDUP(next->Base(), alignment); - if (next->Base() == alignedBase && next->Size() == size) { - // The reserved area is entirely covered, and thus, - // removed - fAreas.Remove(next); - - foundSpot = true; - area->SetBase(alignedBase); - free(next); - break; - } - - if ((next->protection & RESERVED_AVOID_BASE) == 0 - && alignedBase == next->Base() - && next->Size() >= size) { - // The new area will be placed at the beginning of the - // reserved area and the reserved area will be offset - // and resized - foundSpot = true; - next->SetBase(next->Base() + size); - next->SetSize(next->Size() - size); - area->SetBase(alignedBase); - break; - } - - if (is_valid_spot(next->Base(), alignedBase, size, - next->Base() + (next->Size() - 1))) { - // The new area will be placed at the end of the - // reserved area, and the reserved area will be resized - // to make space - alignedBase = ROUNDDOWN( - next->Base() + next->Size() - size, alignment); - - foundSpot = true; - next->SetSize(alignedBase - next->Base()); - area->SetBase(alignedBase); - last = next; - break; - } - - last = next; - } - } - break; - } - - case B_BASE_ADDRESS: - { - // find a hole big enough for a new area beginning with "start" - if (last == NULL) { - // see if we can build it at the beginning of the specified - // start - if (next == NULL || next->Base() > start + (size - 1)) { - foundSpot = true; - area->SetBase(start); - break; - } - - last = next; - next = it.Next(); - } - - // keep walking - while (next != NULL) { - if (next->Base() - (last->Base() + last->Size()) >= size) { - // we found a spot (it'll be filled up below) - break; - } - - last = next; - next = it.Next(); - } - - addr_t lastEnd = last->Base() + (last->Size() - 1); - if (next != NULL || end - lastEnd >= size) { - // got a spot - foundSpot = true; - if (lastEnd < start) - area->SetBase(start); - else - area->SetBase(lastEnd + 1); - break; - } - - // we didn't find a free spot in the requested range, so we'll - // try again without any restrictions - start = fBase; - addressSpec = B_ANY_ADDRESS; - last = NULL; - goto second_chance; - } - - case B_EXACT_ADDRESS: - // see if we can create it exactly here - if ((last == NULL || last->Base() + (last->Size() - 1) < start) - && (next == NULL || next->Base() > start + (size - 1))) { - foundSpot = true; - area->SetBase(start); - break; - } - break; - default: - return B_BAD_VALUE; - } - - if (!foundSpot) - return addressSpec == B_EXACT_ADDRESS ? B_BAD_VALUE : B_NO_MEMORY; - - area->SetSize(size); - if (last) - fAreas.Insert(fAreas.GetNext(last), area); - else - fAreas.Insert(fAreas.Head(), area); - - IncrementChangeCount(); - return B_OK; -} - - /*static*/ int VMAddressSpace::_DumpCommand(int argc, char** argv) { @@ -889,10 +314,9 @@ while (VMAddressSpace* space = it.Next()) { int32 areaCount = 0; off_t areaSize = 0; - for (VMAddressSpaceAreaList::Iterator it = space->fAreas.GetIterator(); - VMArea* area = it.Next();) { - if (area->id != RESERVED_AREA_ID - && area->cache->type != CACHE_TYPE_NULL) { + for (VMAddressSpace::AreaIterator areaIt = space->GetAreaIterator(); + VMArea* area = areaIt.Next();) { + if (area->cache->type != CACHE_TYPE_NULL) { areaCount++; areaSize += area->Size(); } Copied: haiku/trunk/src/system/kernel/vm/VMKernelAddressSpace.cpp (from rev 34491, haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp) =================================================================== --- haiku/trunk/src/system/kernel/vm/VMKernelAddressSpace.cpp (rev 0) +++ haiku/trunk/src/system/kernel/vm/VMKernelAddressSpace.cpp 2009-12-04 14:45:08 UTC (rev 34492) @@ -0,0 +1,645 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + + +#include "VMKernelAddressSpace.h" + +#include <stdlib.h> + +#include <KernelExport.h> + +#include <heap.h> +#include <thread.h> +#include <vm/vm.h> +#include <vm/VMArea.h> + + +//#define TRACE_VM +#ifdef TRACE_VM +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +/*! Verifies that an area with the given aligned base and size fits into + the spot defined by base and limit and checks for overflows. +*/ +static inline bool +is_valid_spot(addr_t base, addr_t alignedBase, addr_t size, addr_t limit) +{ + return (alignedBase >= base && alignedBase + (size - 1) > alignedBase + && alignedBase + (size - 1) <= limit); +} + + +VMKernelAddressSpace::VMKernelAddressSpace(team_id id, addr_t base, size_t size) + : + VMAddressSpace(id, base, size, "kernel address space"), + fAreaHint(NULL) +{ +} + + +VMKernelAddressSpace::~VMKernelAddressSpace() +{ + panic("deleting the kernel aspace!\n"); +} + + +inline VMArea* +VMKernelAddressSpace::FirstArea() const +{ + VMArea* area = fAreas.Head(); + while (area != NULL && area->id == RESERVED_AREA_ID) + area = fAreas.GetNext(area); + return area; +} + + +inline VMArea* +VMKernelAddressSpace::NextArea(VMArea* area) const +{ + area = fAreas.GetNext(area); + while (area != NULL && area->id == RESERVED_AREA_ID) + area = fAreas.GetNext(area); + return area; +} + + +//! You must hold the address space's read lock. +VMArea* +VMKernelAddressSpace::LookupArea(addr_t address) const +{ + // check the area hint first + if (fAreaHint != NULL && fAreaHint->ContainsAddress(address)) + return fAreaHint; + + for (VMAddressSpaceAreaList::ConstIterator it = fAreas.GetIterator(); + VMArea* area = it.Next();) { + if (area->id == RESERVED_AREA_ID) + continue; + + if (area->ContainsAddress(address)) { + fAreaHint = area; + return area; + } + } + + return NULL; +} + + +/*! This inserts the area you pass into the address space. + It will also set the "_address" argument to its base address when + the call succeeds. + You need to hold the VMAddressSpace write lock. +*/ [... truncated: 1320 lines follow ...]