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

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 4 Dec 2009 14:33:25 +0100 (CET)

Author: bonefish
Date: 2009-12-04 14:33:25 +0100 (Fri, 04 Dec 2009)
New Revision: 34491
Changeset: http://dev.haiku-os.org/changeset/34491/haiku

Modified:
   haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h
   haiku/trunk/src/system/kernel/elf.cpp
   haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp
   haiku/trunk/src/system/kernel/vm/vm.cpp
Log:
Moved all knowledge of reserved areas from vm.cpp to VMAddressSpace. It's a
pure address space feature, so it should be handled there.


Modified: haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h
===================================================================
--- haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h      2009-12-04 
13:15:48 UTC (rev 34490)
+++ haiku/trunk/headers/private/kernel/vm/VMAddressSpace.h      2009-12-04 
13:33:25 UTC (rev 34491)
@@ -12,13 +12,14 @@
 
 #include <OS.h>
 
+#include <vm/vm_priv.h>
 #include <vm/vm_translation_map.h>
 #include <vm/VMArea.h>
 
 
 struct VMAddressSpace {
 public:
-                       class Iterator;
+                       class AreaIterator;
 
 public:
                                                                
VMAddressSpace(team_id id, addr_t base,
@@ -30,7 +31,7 @@
 
                        team_id                         ID() const              
                { return fID; }
                        addr_t                          Base() const            
        { return fBase; }
-                       size_t                          Size() const            
        { return fSize; }
+                       addr_t                          EndAddress() const      
        { return fEndAddress; }
                        size_t                          FreeSpace() const       
        { return fFreeSpace; }
                        bool                            IsBeingDeleted() const  
{ return fDeleting; }
 
@@ -57,20 +58,27 @@
                        void                            IncrementChangeCount()
                                                                        { 
fChangeCount++; }
 
-                       VMArea*                         FirstArea() const
-                                                                       { 
return fAreas.Head(); }
-                       VMArea*                         NextArea(VMArea* area) 
const
-                                                                       { 
return fAreas.GetNext(area); }
+                       VMArea*                         FirstArea() const;
 
                        VMArea*                         LookupArea(addr_t 
address) const;
                        status_t                        InsertArea(void** 
_address, uint32 addressSpec,
                                                                        addr_t 
size, VMArea* area);
                        void                            RemoveArea(VMArea* 
area);
+
+                       bool                            CanResizeArea(VMArea* 
area, size_t newSize);
+                       status_t                        ResizeArea(VMArea* 
area, size_t newSize);
                        status_t                        ResizeAreaHead(VMArea* 
area, size_t size);
                        status_t                        ResizeAreaTail(VMArea* 
area, size_t size);
 
-       inline  Iterator                        GetIterator();
+                       status_t                        
ReserveAddressRange(void** _address,
+                                                                       uint32 
addressSpec, size_t size,
+                                                                       uint32 
flags);
+                       status_t                        
UnreserveAddressRange(addr_t address,
+                                                                       size_t 
size);
+                       void                            
UnreserveAllAddressRanges();
 
+       inline  AreaIterator            GetAreaIterator();
+
        static  status_t                        Create(team_id teamID, addr_t 
base, size_t size,
                                                                        bool 
kernel,
                                                                        
VMAddressSpace** _addressSpace);
@@ -108,7 +116,7 @@
 private:
                        VMAddressSpace*         fHashTableLink;
                        addr_t                          fBase;
-                       size_t                          fSize;
+                       addr_t                          fEndAddress;            
// base + (size - 1)
                        size_t                          fFreeSpace;
                        rw_lock                         fLock;
                        team_id                         fID;
@@ -123,45 +131,68 @@
 };
 
 
-class VMAddressSpace::Iterator {
+class VMAddressSpace::AreaIterator {
 public:
-       Iterator()
+       AreaIterator()
        {
        }
 
-       Iterator(VMAddressSpace* addressSpace)
+       AreaIterator(VMAddressSpace* addressSpace)
                :
                fIterator(addressSpace->fAreas.GetIterator())
        {
+               _SkipReserved();
        }
 
        bool HasNext() const
        {
-               return fIterator.HasNext();
+               return fNext != NULL;
        }
 
        VMArea* Next()
        {
-               return fIterator.Next();
+               VMArea* result = fNext;
+               _SkipReserved();
+               return result;
        }
 
        void Rewind()
        {
                fIterator.Rewind();
+               _SkipReserved();
        }
 
 private:
-       VMAddressSpaceAreaList::Iterator fIterator;
+       void _SkipReserved()
+       {
+               while ((fNext = fIterator.Next()) != NULL
+                       && fNext->id == RESERVED_AREA_ID) {
+               }
+       }
+
+private:
+       VMAddressSpaceAreaList::Iterator        fIterator;
+       VMArea*                                                         fNext;
 };
 
 
-inline VMAddressSpace::Iterator
-VMAddressSpace::GetIterator()
+inline VMArea*
+VMAddressSpace::FirstArea() const
 {
-       return Iterator(this);
+       VMArea* area = fAreas.Head();
+       while (area != NULL && area->id == RESERVED_AREA_ID)
+               area = fAreas.GetNext(area);
+       return area;
 }
 
 
+inline VMAddressSpace::AreaIterator
+VMAddressSpace::GetAreaIterator()
+{
+       return AreaIterator(this);
+}
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif

Modified: haiku/trunk/src/system/kernel/elf.cpp
===================================================================
--- haiku/trunk/src/system/kernel/elf.cpp       2009-12-04 13:15:48 UTC (rev 
34490)
+++ haiku/trunk/src/system/kernel/elf.cpp       2009-12-04 13:33:25 UTC (rev 
34491)
@@ -1304,7 +1304,8 @@
        {
                // find the runtime loader debug area
                VMArea* area;
-               for (VMAddressSpace::Iterator it = 
team->address_space->GetIterator();
+               for (VMAddressSpace::AreaIterator it
+                                       = 
team->address_space->GetAreaIterator();
                                (area = it.Next()) != NULL;) {
                        if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) 
== 0)
                                break;

Modified: haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp
===================================================================
--- haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-04 13:15:48 UTC 
(rev 34490)
+++ haiku/trunk/src/system/kernel/vm/VMAddressSpace.cpp 2009-12-04 13:33:25 UTC 
(rev 34491)
@@ -19,7 +19,6 @@
 #include <heap.h>
 #include <thread.h>
 #include <vm/vm.h>
-#include <vm/vm_priv.h>
 #include <vm/VMArea.h>
 
 
@@ -88,7 +87,7 @@
        bool kernel)
        :
        fBase(base),
-       fSize(size),
+       fEndAddress(base + (size - 1)),
        fFreeSpace(size),
        fID(id),
        fRefCount(1),
@@ -317,7 +316,7 @@
 
                case B_BASE_ADDRESS:
                        searchBase = (addr_t)*_address;
-                       searchEnd = fBase + (fSize - 1);
+                       searchEnd = fEndAddress;
                        break;
 
                case B_ANY_ADDRESS:
@@ -328,7 +327,7 @@
                        // completely (currently needs a userland address 
space!)
                        if (searchBase == USER_BASE)
                                searchBase = USER_BASE_ANY;
-                       searchEnd = fBase + (fSize - 1);
+                       searchEnd = fEndAddress;
                        break;
 
                default:
@@ -361,7 +360,65 @@
 }
 
 
+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();
@@ -388,7 +445,79 @@
 }
 
 
+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);
@@ -397,7 +526,7 @@
        kprintf("fault_count: %ld\n", fFaultCount);
        kprintf("translation_map: %p\n", &fTranslationMap);
        kprintf("base: 0x%lx\n", fBase);
-       kprintf("size: 0x%lx\n", fSize);
+       kprintf("end: 0x%lx\n", fEndAddress);
        kprintf("change_count: 0x%lx\n", fChangeCount);
        kprintf("area_hint: %p\n", fAreaHint);
 
@@ -505,7 +634,7 @@
                size, end, addressSpec, area));
 
        // do some sanity checking
-       if (start < fBase || size == 0 || end > fBase + fSize - 1
+       if (start < fBase || size == 0 || end > fEndAddress
                || start + (size - 1) > end)
                return B_BAD_ADDRESS;
 
@@ -753,7 +882,7 @@
 /*static*/ int
 VMAddressSpace::_DumpListCommand(int argc, char** argv)
 {
-       kprintf("   address      id         base         size   area count   "
+       kprintf("   address      id         base          end   area count   "
                " area size\n");
 
        AddressSpaceTable::Iterator it = sAddressSpaceTable.GetIterator();
@@ -769,7 +898,7 @@
                        }
                }
                kprintf("%p  %6ld   %#010lx   %#10lx   %10ld   %10lld\n",
-                       space, space->ID(), space->Base(), space->Size(), 
areaCount,
+                       space, space->ID(), space->Base(), space->EndAddress(), 
areaCount,
                        areaSize);
        }
 

Modified: haiku/trunk/src/system/kernel/vm/vm.cpp
===================================================================
--- haiku/trunk/src/system/kernel/vm/vm.cpp     2009-12-04 13:15:48 UTC (rev 
34490)
+++ haiku/trunk/src/system/kernel/vm/vm.cpp     2009-12-04 13:33:25 UTC (rev 
34491)
@@ -460,30 +460,26 @@
 
        // Check, whether the caller is allowed to modify the concerned areas.
        if (!kernel) {
-               for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
+               for (VMAddressSpace::AreaIterator it = 
addressSpace->GetAreaIterator();
                                VMArea* area = it.Next();) {
-                       if (area->id != RESERVED_AREA_ID) {
-                               addr_t areaLast = area->Base() + (area->Size() 
- 1);
-                               if (area->Base() < lastAddress && address < 
areaLast) {
-                                       if ((area->protection & B_KERNEL_AREA) 
!= 0)
-                                               return B_NOT_ALLOWED;
-                               }
+                       addr_t areaLast = area->Base() + (area->Size() - 1);
+                       if (area->Base() < lastAddress && address < areaLast) {
+                               if ((area->protection & B_KERNEL_AREA) != 0)
+                                       return B_NOT_ALLOWED;
                        }
                }
        }
 
-       for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
+       for (VMAddressSpace::AreaIterator it = addressSpace->GetAreaIterator();
                        VMArea* area = it.Next();) {
-               if (area->id != RESERVED_AREA_ID) {
-                       addr_t areaLast = area->Base() + (area->Size() - 1);
-                       if (area->Base() < lastAddress && address < areaLast) {
-                               status_t error = cut_area(addressSpace, area, 
address,
-                                       lastAddress, NULL, kernel);
-                               if (error != B_OK)
-                                       return error;
-                                       // Failing after already messing with 
areas is ugly, but we
-                                       // can't do anything about it.
-                       }
+               addr_t areaLast = area->Base() + (area->Size() - 1);
+               if (area->Base() < lastAddress && address < areaLast) {
+                       status_t error = cut_area(addressSpace, area, address,
+                               lastAddress, NULL, kernel);
+                       if (error != B_OK)
+                               return error;
+                               // Failing after already messing with areas is 
ugly, but we
+                               // can't do anything about it.
                }
        }
 
@@ -651,29 +647,7 @@
        if (!locker.IsLocked())
                return B_BAD_TEAM_ID;
 
-       // check to see if this address space has entered DELETE state
-       if (locker.AddressSpace()->IsBeingDeleted()) {
-               // okay, someone is trying to delete this address space now, so 
we can't
-               // insert the area, so back out
-               return B_BAD_TEAM_ID;
-       }
-
-       // search area list and remove any matching reserved ranges
-       addr_t endAddress = (addr_t)address + (size - 1);
-       for (VMAddressSpace::Iterator it = locker.AddressSpace()->GetIterator();
-                       VMArea* area = it.Next();) {
-               // the area must be completely part of the reserved range
-               if (area->Base() + (area->Size() - 1) > endAddress)
-                       break;
-               if (area->id == RESERVED_AREA_ID && area->Base() >= 
(addr_t)address) {
-                       // remove reserved range
-                       locker.AddressSpace()->RemoveArea(area);
-                       locker.AddressSpace()->Put();
-                       free(area);
-               }
-       }
-
-       return B_OK;
+       return locker.AddressSpace()->UnreserveAddressRange((addr_t)address, 
size);
 }
 
 
@@ -688,31 +662,8 @@
        if (!locker.IsLocked())
                return B_BAD_TEAM_ID;
 
-       // check to see if this address space has entered DELETE state
-       if (locker.AddressSpace()->IsBeingDeleted()) {
-               // okay, someone is trying to delete this address space now, so 
we
-               // can't insert the area, let's back out
-               return B_BAD_TEAM_ID;
-       }
-
-       VMArea* area = VMArea::CreateReserved(locker.AddressSpace(), flags);
-       if (area == NULL)
-               return B_NO_MEMORY;
-
-       status_t status = locker.AddressSpace()->InsertArea(_address, 
addressSpec,
-               size, area);
-       if (status != B_OK) {
-               free(area);
-               return status;
-       }
-
-       // the area is now reserved!
-
-       area->cache_offset = area->Base();
-               // we cache the original base address here
-
-       locker.AddressSpace()->Get();
-       return B_OK;
+       return locker.AddressSpace()->ReserveAddressRange(_address, addressSpec,
+               size, flags);
 }
 
 
@@ -2907,17 +2858,8 @@
        addressSpace->WriteLock();
 
        // remove all reserved areas in this address space
+       addressSpace->UnreserveAllAddressRanges();
 
-       for (VMAddressSpace::Iterator it = addressSpace->GetIterator();
-                       VMArea* area = it.Next();) {
-               if (area->id == RESERVED_AREA_ID) {
-                       // just remove it
-                       addressSpace->RemoveArea(area);
-                       addressSpace->Put();
-                       free(area);
-               }
-       }
-
        // delete all the areas in this address space
        while (VMArea* area = addressSpace->FirstArea())
                delete_area(addressSpace, area);
@@ -2995,12 +2937,13 @@
 
        map->ops->lock(map);
 
-       for (VMAddressSpace::Iterator it = 
VMAddressSpace::Kernel()->GetIterator();
+       for (VMAddressSpace::AreaIterator it
+                               = VMAddressSpace::Kernel()->GetAreaIterator();
                        VMArea* area = it.Next();) {
                addr_t areaStart = area->Base();
                addr_t areaEnd = areaStart + (area->Size() - 1);
 
-               if (area->id == RESERVED_AREA_ID || areaEnd < start)
+               if (areaEnd < start)
                        continue;
 
                if (areaStart > end) {
@@ -4251,23 +4194,10 @@
 
        if (oldSize < newSize) {
                // We need to check if all areas of this cache can be resized
-
                for (VMArea* current = cache->areas; current != NULL;
                                current = current->cache_next) {
-                       VMArea* next = 
current->address_space->NextArea(current);
-                       if (next != NULL && next->Base() <= (current->Base() + 
newSize)) {
-                               // If the area was created inside a reserved 
area, it can
-                               // also be resized in that area
-                               // TODO: if there is free space after the 
reserved area, it could
-                               // be used as well...
-                               if (next->id == RESERVED_AREA_ID
-                                       && next->cache_offset <= current->Base()
-                                       && next->Base() - 1 + next->Size()
-                                               >= current->Base() - 1 + 
newSize)
-                                       continue;
-
+                       if (!current->address_space->CanResizeArea(current, 
newSize))
                                return B_ERROR;
-                       }
                }
        }
 
@@ -4282,35 +4212,12 @@
 
        for (VMArea* current = cache->areas; current != NULL;
                        current = current->cache_next) {
-               VMArea* next = current->address_space->NextArea(current);
-               if (next != NULL && next->Base() <= (current->Base() + 
newSize)) {
-                       if (next->id == RESERVED_AREA_ID
-                               && next->cache_offset <= current->Base()
-                               && next->Base() - 1 + next->Size()
-                                       >= current->Base() - 1 + newSize) {
-                               // resize reserved area
-                               addr_t offset = current->Base() + newSize - 
next->Base();
-                               if (next->Size() <= offset) {
-                                       next->address_space->RemoveArea(next);
-                                       free(next);
-                               } else {
-                                       
next->address_space->ResizeAreaHead(next,
-                                               next->Size() - offset);
-                               }
-                       } else {
-                               panic("resize situation for area %p has changed 
although we "
-                                       "should have the address space lock", 
current);
-                               status = B_ERROR;
-                               break;
-                       }
-               }
-
-               status = current->address_space->ResizeAreaTail(current, 
newSize);
+               status = current->address_space->ResizeArea(current, newSize);
                if (status != B_OK)
                        break;
 
                // We also need to unmap all pages beyond the new size, if the 
area has
-               // shrinked
+               // shrunk
                if (newSize < oldSize) {
                        vm_unmap_pages(current, current->Base() + newSize, 
oldSize - newSize,
                                false);
@@ -4326,7 +4233,7 @@
                // This can fail, too, in which case we're seriously screwed.
                for (VMArea* current = cache->areas; current != NULL;
                                current = current->cache_next) {
-                       if (current->address_space->ResizeAreaTail(current, 
oldSize)
+                       if (current->address_space->ResizeArea(current, oldSize)
                                        != B_OK) {
                                panic("vm_resize_area(): Failed and not being 
able to restore "
                                        "original state.");
@@ -4792,11 +4699,9 @@
                return B_BAD_TEAM_ID;
 
        VMArea* area;
-       for (VMAddressSpace::Iterator it = locker.AddressSpace()->GetIterator();
+       for (VMAddressSpace::AreaIterator it
+                               = locker.AddressSpace()->GetAreaIterator();
                        (area = it.Next()) != NULL;) {
-               if (area->id == RESERVED_AREA_ID)
-                       continue;
-
                if (area->Base() > nextBase)
                        break;
        }


Other related posts:

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