summaryrefslogtreecommitdiff
path: root/Kernel/Syscalls/mmap.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-08-23 18:51:18 +0200
committerAndreas Kling <kling@serenityos.org>2022-08-24 14:57:51 +0200
commit30861daa93c06280cff4e355b31d11ecbf8079ec (patch)
treefdb41ebda018893cf9498a11126194cf71e9395a /Kernel/Syscalls/mmap.cpp
parentcf16b2c8e64709d570c5f54a981017d217e95ed0 (diff)
downloadserenity-30861daa93c06280cff4e355b31d11ecbf8079ec.zip
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.
Diffstat (limited to 'Kernel/Syscalls/mmap.cpp')
-rw-r--r--Kernel/Syscalls/mmap.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp
index 0d5ebba9bd..1e5be912ab 100644
--- a/Kernel/Syscalls/mmap.cpp
+++ b/Kernel/Syscalls/mmap.cpp
@@ -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;