Kernel: Speed up mmap address space reservation by a lot

Instead of scanning the page table for free range, we not use the
process's mapped regions to find a slot. This speeds up mmap by a lot!
This commit is contained in:
2026-05-20 01:08:08 +03:00
parent 5cb5ae2dfe
commit 4f5f84bb5b
2 changed files with 45 additions and 15 deletions

View File

@@ -278,6 +278,8 @@ namespace Kernel
// You must hold reader end of m_mapped_region_lock when calling this.
size_t find_mapped_region(vaddr_t) const;
BAN::ErrorOr<AddressRange> find_free_address_range(size_t size);
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;

View File

@@ -483,6 +483,26 @@ namespace Kernel
return l;
}
BAN::ErrorOr<AddressRange> Process::find_free_address_range(size_t size)
{
if (auto rem = size % PAGE_SIZE)
size += PAGE_SIZE - rem;
vaddr_t vaddr = m_shared_page_vaddr ? m_shared_page_vaddr + PAGE_SIZE : 0x400000;
for (size_t i = find_mapped_region(vaddr); i < m_mapped_regions.size(); i++)
{
const auto& region = m_mapped_regions[i];
if (!region->overlaps(vaddr, size))
return AddressRange { vaddr, vaddr + size };
vaddr = region->vaddr() + region->size();
if (auto rem = vaddr % PAGE_SIZE)
vaddr += PAGE_SIZE - rem;
}
return BAN::Error::from_errno(ENOMEM);
}
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
{
ASSERT(offset >= 0);
@@ -2470,7 +2490,7 @@ namespace Kernel
RWLockWRGuard _(m_memory_region_lock);
AddressRange address_range { .start = 0x400000, .end = USERSPACE_END };
AddressRange address_range;
if (args.flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))
{
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(args.addr);
@@ -2509,22 +2529,30 @@ namespace Kernel
}
}
}
else if (const vaddr_t vaddr = reinterpret_cast<vaddr_t>(args.addr); vaddr == 0)
;
else if (vaddr % PAGE_SIZE)
;
else if (!PageTable::is_valid_pointer(vaddr))
;
else if (!PageTable::is_valid_pointer(vaddr + args.len))
;
else if (!page_table().is_range_free(vaddr, args.len))
;
else
{
address_range = {
.start = vaddr,
.end = vaddr + args.len,
};
bool use_address_hint = false;
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(args.addr);
if (vaddr == 0 || vaddr % PAGE_SIZE)
;
else if (!PageTable::is_valid_pointer(vaddr))
;
else if (!PageTable::is_valid_pointer(vaddr + args.len))
;
else if (!page_table().is_range_free(vaddr, args.len))
;
else
{
use_address_hint = true;
address_range = {
.start = vaddr,
.end = vaddr + args.len,
};
}
if (!use_address_hint)
address_range = TRY(find_free_address_range(args.len));
}
if (args.flags & MAP_ANONYMOUS)