[haiku-commits] r34492 - in haiku/trunk: headers/private/kernel/vm src/system/kernel/vm

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 4 Dec 2009 15:45:08 +0100 (CET)

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 ...]

Other related posts:

  • » [haiku-commits] r34492 - in haiku/trunk: headers/private/kernel/vm src/system/kernel/vm - ingo_weinhold