mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:47:45 +00:00
Kernel: Simplify the File memory-mapping API
Before this change, we had File::mmap() which did all the work of setting up a VMObject, and then creating a Region in the current process's address space. This patch simplifies the interface by removing the region part. Files now only have to return a suitable VMObject from vmobject_for_mmap(), and then sys$mmap() itself will take care of actually mapping it into the address space. This fixes an issue where we'd try to block on I/O (for inode metadata lookup) while holding the address space spinlock. It also reduces time spent holding the address space lock.
This commit is contained in:
parent
cf16b2c8e6
commit
30861daa93
15 changed files with 49 additions and 58 deletions
|
@ -190,10 +190,17 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use
|
|||
if (map_stack && (!map_private || !map_anonymous))
|
||||
return EINVAL;
|
||||
|
||||
Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size };
|
||||
if (addr && !(map_fixed || map_fixed_noreplace)) {
|
||||
// If there's an address but MAP_FIXED wasn't specified, the address is just a hint.
|
||||
requested_range = { {}, rounded_size };
|
||||
}
|
||||
|
||||
Memory::Region* region = nullptr;
|
||||
|
||||
LockRefPtr<OpenFileDescription> description;
|
||||
LockRefPtr<Memory::AnonymousVMObject> vmobject;
|
||||
LockRefPtr<Memory::VMObject> vmobject;
|
||||
u64 used_offset = 0;
|
||||
|
||||
if (map_anonymous) {
|
||||
auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve;
|
||||
|
@ -206,6 +213,7 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use
|
|||
} else {
|
||||
if (offset < 0)
|
||||
return EINVAL;
|
||||
used_offset = static_cast<u64>(offset);
|
||||
if (static_cast<size_t>(offset) & ~PAGE_MASK)
|
||||
return EINVAL;
|
||||
description = TRY(open_file_description(fd));
|
||||
|
@ -220,6 +228,8 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use
|
|||
}
|
||||
if (description->inode())
|
||||
TRY(validate_inode_mmap_prot(prot, *description->inode(), map_shared));
|
||||
|
||||
vmobject = TRY(description->vmobject_for_mmap(*this, requested_range, used_offset, map_shared));
|
||||
}
|
||||
|
||||
return address_space().with([&](auto& space) -> ErrorOr<FlatPtr> {
|
||||
|
@ -227,17 +237,16 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<Syscall::SC_mmap_params const*> use
|
|||
if (map_fixed)
|
||||
TRY(space->unmap_mmap_range(VirtualAddress(addr), size));
|
||||
|
||||
Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size };
|
||||
if (addr && !(map_fixed || map_fixed_noreplace)) {
|
||||
// If there's an address but MAP_FIXED wasn't specified, the address is just a hint.
|
||||
requested_range = { {}, rounded_size };
|
||||
}
|
||||
|
||||
if (map_anonymous) {
|
||||
region = TRY(space->allocate_region_with_vmobject(map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No, requested_range.base(), requested_range.size(), alignment, vmobject.release_nonnull(), 0, {}, prot, map_shared));
|
||||
} else {
|
||||
region = TRY(description->mmap(*this, *space, requested_range, static_cast<u64>(offset), prot, map_shared));
|
||||
}
|
||||
region = TRY(space->allocate_region_with_vmobject(
|
||||
map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No,
|
||||
requested_range.base(),
|
||||
requested_range.size(),
|
||||
alignment,
|
||||
vmobject.release_nonnull(),
|
||||
used_offset,
|
||||
{},
|
||||
prot,
|
||||
map_shared));
|
||||
|
||||
if (!region)
|
||||
return ENOMEM;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue