1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:58:11 +00:00

Kernel: Add MAP_NORESERVE support to mmap

Rather than lazily committing regions by default, we now commit
the entire region unless MAP_NORESERVE is specified.

This solves random crashes in low-memory situations where e.g. the
malloc heap allocated memory, but using pages that haven't been
used before triggers a crash when no more physical memory is available.

Use this flag to create large regions without actually committing
the backing memory. madvise() can be used to commit arbitrary areas
of such regions after creating them.
This commit is contained in:
Tom 2020-09-03 15:06:25 -06:00 committed by Andreas Kling
parent bc5d6992a4
commit c3451899bc
7 changed files with 30 additions and 15 deletions

View file

@ -146,8 +146,9 @@ Region* Process::allocate_region(const Range& range, const String& name, int pro
ASSERT(range.is_valid());
auto vmobject = AnonymousVMObject::create_with_size(range.size());
auto region = Region::create_user_accessible(this, range, vmobject, 0, name, prot_to_region_access_flags(prot));
region->map(page_directory());
if (should_commit && !region->commit())
if (!region->map(page_directory()))
return nullptr;
if (should_commit && region->can_commit() && !region->commit())
return nullptr;
return &add_region(move(region));
}
@ -160,7 +161,7 @@ Region* Process::allocate_region(VirtualAddress vaddr, size_t size, const String
return allocate_region(range, name, prot, should_commit);
}
Region* Process::allocate_region_with_vmobject(const Range& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot)
Region* Process::allocate_region_with_vmobject(const Range& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot, bool should_commit)
{
ASSERT(range.is_valid());
size_t end_in_vmobject = offset_in_vmobject + range.size();
@ -178,16 +179,19 @@ Region* Process::allocate_region_with_vmobject(const Range& range, NonnullRefPtr
}
offset_in_vmobject &= PAGE_MASK;
auto& region = add_region(Region::create_user_accessible(this, range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot)));
region.map(page_directory());
if (!region.map(page_directory()))
return nullptr;
if (should_commit && region.can_commit() && !region.commit())
return nullptr;
return &region;
}
Region* Process::allocate_region_with_vmobject(VirtualAddress vaddr, size_t size, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot)
Region* Process::allocate_region_with_vmobject(VirtualAddress vaddr, size_t size, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot, bool should_commit)
{
auto range = allocate_range(vaddr, size);
if (!range.is_valid())
return nullptr;
return allocate_region_with_vmobject(range, move(vmobject), offset_in_vmobject, name, prot);
return allocate_region_with_vmobject(range, move(vmobject), offset_in_vmobject, name, prot, should_commit);
}
bool Process::deallocate_region(Region& region)