1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 07:27:45 +00:00

Kernel: Merge PurgeableVMObject into AnonymousVMObject

This implements memory commitments and lazy-allocation of committed
memory.
This commit is contained in:
Tom 2020-09-05 15:52:14 -06:00 committed by Andreas Kling
parent b2a52f6208
commit 476f17b3f1
35 changed files with 937 additions and 564 deletions

View file

@ -33,6 +33,7 @@
#include <Kernel/Profiling.h>
#include <Kernel/Random.h>
#include <Kernel/Time/TimeManagement.h>
#include <Kernel/VM/AllocationStrategy.h>
#include <Kernel/VM/MemoryManager.h>
#include <Kernel/VM/PageDirectory.h>
#include <Kernel/VM/Region.h>
@ -172,7 +173,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
return IterationDecision::Break;
}
master_tls_region = allocate_region({}, program_header.size_in_memory(), String::formatted("{} (master-tls)", elf_name), PROT_READ | PROT_WRITE);
master_tls_region = allocate_region({}, program_header.size_in_memory(), String::formatted("{} (master-tls)", elf_name), PROT_READ | PROT_WRITE, AllocationStrategy::Reserve);
if (!master_tls_region) {
ph_load_result = KResult(-ENOMEM);
return IterationDecision::Break;
@ -206,7 +207,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
if (program_header.is_writable())
prot |= PROT_WRITE;
auto region_name = String::formatted("{} (data-{}{})", elf_name, program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "");
auto* region = allocate_region(program_header.vaddr().offset(load_offset), program_header.size_in_memory(), move(region_name), prot);
auto* region = allocate_region(program_header.vaddr().offset(load_offset), program_header.size_in_memory(), move(region_name), prot, AllocationStrategy::Reserve);
if (!region) {
ph_load_result = KResult(-ENOMEM);
return IterationDecision::Break;
@ -259,7 +260,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_
return KResult(-ENOEXEC);
}
auto* stack_region = allocate_region(VirtualAddress(), Thread::default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, false);
auto* stack_region = allocate_region(VirtualAddress(), Thread::default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, AllocationStrategy::Reserve);
if (!stack_region)
return KResult(-ENOMEM);
stack_region->set_stack(true);

View file

@ -104,13 +104,17 @@ pid_t Process::sys$fork(RegisterState& regs)
ScopedSpinLock processes_lock(g_processes_lock);
g_processes->prepend(child);
child->ref(); // This reference will be dropped by Process::reap
}
ScopedSpinLock lock(g_scheduler_lock);
child_first_thread->set_affinity(Thread::current()->affinity());
child_first_thread->set_state(Thread::State::Runnable);
return child->pid().value();
auto child_pid = child->pid().value();
// We need to leak one reference so we don't destroy the Process,
// which will be dropped by Process::reap
(void)child.leak_ref();
return child_pid;
}
}

View file

@ -29,7 +29,6 @@
#include <Kernel/Process.h>
#include <Kernel/VM/PageDirectory.h>
#include <Kernel/VM/PrivateInodeVMObject.h>
#include <Kernel/VM/PurgeableVMObject.h>
#include <Kernel/VM/Region.h>
#include <Kernel/VM/SharedInodeVMObject.h>
#include <LibC/limits.h>
@ -142,9 +141,10 @@ void* Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> user_params)
}
if (map_anonymous) {
region = allocate_region(range.value(), !name.is_null() ? name : "mmap", prot, !map_noreserve);
auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve;
region = allocate_region(range.value(), !name.is_null() ? name : "mmap", prot, strategy);
if (!region && (!map_fixed && addr != 0))
region = allocate_region(allocate_range({}, size), !name.is_null() ? name : "mmap", prot, !map_noreserve);
region = allocate_region(allocate_range({}, size), !name.is_null() ? name : "mmap", prot, strategy);
} else {
if (offset < 0)
return (void*)-EINVAL;
@ -280,7 +280,7 @@ int Process::sys$madvise(void* address, size_t size, int advice)
if (set_volatile && set_nonvolatile)
return -EINVAL;
if (set_volatile || set_nonvolatile) {
if (!region->vmobject().is_purgeable())
if (!region->vmobject().is_anonymous())
return -EPERM;
bool was_purged = false;
switch (region->set_volatile(VirtualAddress(address), size, set_volatile, was_purged)) {
@ -296,7 +296,7 @@ int Process::sys$madvise(void* address, size_t size, int advice)
return 0;
}
if (advice & MADV_GET_VOLATILE) {
if (!region->vmobject().is_purgeable())
if (!region->vmobject().is_anonymous())
return -EPERM;
return region->is_volatile(VirtualAddress(address), size) ? 0 : 1;
}

View file

@ -26,9 +26,9 @@
#include <AK/NonnullRefPtrVector.h>
#include <Kernel/Process.h>
#include <Kernel/VM/AnonymousVMObject.h>
#include <Kernel/VM/InodeVMObject.h>
#include <Kernel/VM/MemoryManager.h>
#include <Kernel/VM/PurgeableVMObject.h>
namespace Kernel {
@ -39,12 +39,11 @@ int Process::sys$purge(int mode)
return -EPERM;
int purged_page_count = 0;
if (mode & PURGE_ALL_VOLATILE) {
NonnullRefPtrVector<PurgeableVMObject> vmobjects;
NonnullRefPtrVector<AnonymousVMObject> vmobjects;
{
InterruptDisabler disabler;
MM.for_each_vmobject([&](auto& vmobject) {
if (vmobject.is_purgeable())
vmobjects.append(static_cast<PurgeableVMObject&>(vmobject));
vmobjects.append(vmobject);
return IterationDecision::Continue;
});
}

View file

@ -52,7 +52,7 @@ int Process::sys$shbuf_create(int size, void** buffer)
return -EINVAL;
size = PAGE_ROUND_UP(size);
auto vmobject = PurgeableVMObject::create_with_size(size);
auto vmobject = AnonymousVMObject::create_with_size(size, AllocationStrategy::Reserve);
if (!vmobject)
return -ENOMEM;

View file

@ -61,6 +61,10 @@ int Process::sys$create_thread(void* (*entry)(void*), Userspace<const Syscall::S
// FIXME: Do something with guard pages?
auto thread = adopt(*new Thread(*this));
if (!thread->was_created()) {
// Could not fully create a thread
return -ENOMEM;
}
// We know this thread is not the main_thread,
// So give it a unique name until the user calls $set_thread_name on it