summaryrefslogtreecommitdiff
path: root/Kernel/VM/Region.cpp
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-09-03 15:06:25 -0600
committerAndreas Kling <kling@serenityos.org>2021-01-01 23:43:44 +0100
commitc3451899bcbdb1b268ff862ae37263d6ee99a423 (patch)
treebd277d683e7cc89f9e5b6be35f394b7e97229d7b /Kernel/VM/Region.cpp
parentbc5d6992a44be838c225bfd88be0aa4f978ddd66 (diff)
downloadserenity-c3451899bcbdb1b268ff862ae37263d6ee99a423.zip
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.
Diffstat (limited to 'Kernel/VM/Region.cpp')
-rw-r--r--Kernel/VM/Region.cpp13
1 files changed, 11 insertions, 2 deletions
diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp
index 22d49c60a1..5f40c88b8e 100644
--- a/Kernel/VM/Region.cpp
+++ b/Kernel/VM/Region.cpp
@@ -187,13 +187,18 @@ auto Region::set_volatile(VirtualAddress vaddr, size_t size, bool is_volatile, b
// Attempt to remap the page range. We want to make sure we have
// enough memory, if not we need to inform the caller of that
// fact
- if (!remap_page_range(first_page_index, last_page_index - first_page_index))
+ if (!remap_page_range(first_page_index, last_page_index - first_page_index, true))
return SetVolatileError::OutOfMemory;
}
}
return SetVolatileError::Success;
}
+bool Region::can_commit() const
+{
+ return vmobject().is_anonymous() || vmobject().is_purgeable();
+}
+
bool Region::commit()
{
ScopedSpinLock lock(s_mm_lock);
@@ -339,7 +344,7 @@ bool Region::map_individual_page_impl(size_t page_index)
return true;
}
-bool Region::remap_page_range(size_t page_index, size_t page_count)
+bool Region::remap_page_range(size_t page_index, size_t page_count, bool do_commit)
{
bool success = true;
ScopedSpinLock lock(s_mm_lock);
@@ -347,6 +352,10 @@ bool Region::remap_page_range(size_t page_index, size_t page_count)
ScopedSpinLock page_lock(m_page_directory->get_lock());
size_t index = page_index;
while (index < page_index + page_count) {
+ if (do_commit && !commit(index)) {
+ success = false;
+ break;
+ }
if (!map_individual_page_impl(index)) {
success = false;
break;