1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-08 20:17:34 +00:00

Kernel: Use AddressSpace region tree for range allocation

This patch stops using VirtualRangeAllocator in AddressSpace and instead
looks for holes in the region tree when allocating VM space.

There are many benefits:

- VirtualRangeAllocator is non-intrusive and would call kmalloc/kfree
  when used. This new solution is allocation-free. This was a source
  of unpleasant MM/kmalloc deadlocks.

- We consolidate authority on what the address space looks like in a
  single place. Previously, we had both the range allocator *and* the
  region tree both being used to determine if an address was valid.
  Now there is only the region tree.

- Deallocation of VM when splitting regions is no longer complicated,
  as we don't need to keep two separate trees in sync.
This commit is contained in:
Andreas Kling 2022-04-02 20:01:29 +02:00
parent 90a7b9e5b4
commit 02a95a196f
10 changed files with 158 additions and 30 deletions

View file

@ -34,21 +34,10 @@ UNMAP_AFTER_INIT NonnullRefPtr<PageDirectory> PageDirectory::must_create_kernel_
return directory;
}
ErrorOr<NonnullRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace(VirtualRangeAllocator const* parent_range_allocator)
ErrorOr<NonnullRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace()
{
constexpr FlatPtr userspace_range_base = USER_RANGE_BASE;
FlatPtr const userspace_range_ceiling = USER_RANGE_CEILING;
auto directory = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) PageDirectory));
if (parent_range_allocator) {
TRY(directory->m_range_allocator.initialize_from_parent(*parent_range_allocator));
} else {
size_t random_offset = (get_fast_random<u8>() % 32 * MiB) & PAGE_MASK;
u32 base = userspace_range_base + random_offset;
TRY(directory->m_range_allocator.initialize_with_range(VirtualAddress(base), userspace_range_ceiling - base));
}
// NOTE: Take the MM lock since we need it for quickmap.
SpinlockLocker lock(s_mm_lock);