kernel/vm: Remove linear search from _get_next_area_info.
This introduces VMAddressSpace::FindClosestArea() that can be used to find the closest area to a given address in either direction. This is now trivial and efficient since both kernel and user address spaces use a binary search tree. Using FindClosestArea() getting multiple area infos is sped up dramatically as it removes the need for a linear search from the first area to the one given in the cookie on each successive invocation. Change-Id: I227da87d915f6f3d3ef88bfeb6be5d4c97c3baaa Reviewed-on: https://review.haiku-os.org/c/haiku/+/2840 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
6d9329be05
commit
a626bdab77
@ -76,6 +76,8 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const = 0;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const = 0;
|
||||
virtual VMArea* FindClosestArea(addr_t address, bool less) const
|
||||
= 0;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection,
|
||||
uint32 allocationFlags) = 0;
|
||||
|
@ -171,6 +171,18 @@ VMKernelAddressSpace::LookupArea(addr_t address) const
|
||||
}
|
||||
|
||||
|
||||
//! You must hold the address space's read lock.
|
||||
VMArea*
|
||||
VMKernelAddressSpace::FindClosestArea(addr_t address, bool less) const
|
||||
{
|
||||
Range* range = fRangeTree.FindClosest(address, less);
|
||||
while (range != NULL && range->type != Range::RANGE_AREA)
|
||||
range = fRangeTree.Next(range);
|
||||
|
||||
return range != NULL ? range->area : 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.
|
||||
|
@ -26,6 +26,8 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const;
|
||||
virtual VMArea* FindClosestArea(addr_t address, bool less)
|
||||
const;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection, uint32 allocationFlags);
|
||||
virtual void DeleteArea(VMArea* area,
|
||||
|
@ -142,6 +142,17 @@ VMUserAddressSpace::LookupArea(addr_t address) const
|
||||
}
|
||||
|
||||
|
||||
//! You must hold the address space's read lock.
|
||||
VMArea*
|
||||
VMUserAddressSpace::FindClosestArea(addr_t address, bool less) const
|
||||
{
|
||||
VMUserArea* area = fAreas.FindClosest(address, less);
|
||||
while (area != NULL && area->id == RESERVED_AREA_ID)
|
||||
area = fAreas.Next(area);
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
/*! 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.
|
||||
|
@ -21,6 +21,8 @@ public:
|
||||
virtual VMArea* NextArea(VMArea* area) const;
|
||||
|
||||
virtual VMArea* LookupArea(addr_t address) const;
|
||||
virtual VMArea* FindClosestArea(addr_t address, bool less)
|
||||
const;
|
||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||
uint32 protection, uint32 allocationFlags);
|
||||
virtual void DeleteArea(VMArea* area,
|
||||
|
@ -6050,21 +6050,14 @@ _get_next_area_info(team_id team, ssize_t* cookie, area_info* info, size_t size)
|
||||
if (!locker.IsLocked())
|
||||
return B_BAD_TEAM_ID;
|
||||
|
||||
VMArea* area;
|
||||
for (VMAddressSpace::AreaIterator it
|
||||
= locker.AddressSpace()->GetAreaIterator();
|
||||
(area = it.Next()) != NULL;) {
|
||||
if (area->Base() > nextBase)
|
||||
break;
|
||||
}
|
||||
|
||||
VMArea* area = locker.AddressSpace()->FindClosestArea(nextBase, false);
|
||||
if (area == NULL) {
|
||||
nextBase = (addr_t)-1;
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
fill_area_info(area, info, size);
|
||||
*cookie = (ssize_t)(area->Base());
|
||||
*cookie = (ssize_t)(area->Base() + 1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user