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:
Michael Lotz 2020-05-29 14:25:43 +02:00 committed by waddlesplash
parent 6d9329be05
commit a626bdab77
6 changed files with 31 additions and 9 deletions

View File

@ -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;

View File

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

View File

@ -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,

View File

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

View File

@ -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,

View File

@ -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;
}