mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
Kernel/Memory: Fix redundant page faults on anonymous mmaps after fork
After a fork(), page faults on anonymous mmaps can cause a redundant page fault to occur. This happens because VMObjects for anonymous mmaps are initially filled with references to the lazy_committed_page or shared_zero_page. If there is a fork, VMObject::try_clone() is called and all pages of the VMObject are marked as cow (via the m_cow_map). Page faults on a zero/lazy page are handled by handle_zero_fault(). handle_zero_fault() does not update m_cow_map, so if the page was marked cow before the fault, it will still be marked cow after the fault. This causes a second (redundant) page fault when the CPU retries the write. This commit removes the redundant page fault by not marking zero/lazy pages as cow in m_cow_map.
This commit is contained in:
parent
2278b17c42
commit
8812410617
2 changed files with 14 additions and 2 deletions
|
@ -267,10 +267,21 @@ NonnullRefPtr<PhysicalRAMPage> AnonymousVMObject::allocate_committed_page(Badge<
|
|||
return m_unused_committed_pages->take_one();
|
||||
}
|
||||
|
||||
void AnonymousVMObject::reset_cow_map()
|
||||
{
|
||||
for (size_t i = 0; i < page_count(); ++i) {
|
||||
auto& page = physical_pages()[i];
|
||||
bool should_cow = !page->is_shared_zero_page() && !page->is_lazy_committed_page();
|
||||
m_cow_map.set(i, should_cow);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<void> AnonymousVMObject::ensure_cow_map()
|
||||
{
|
||||
if (m_cow_map.is_null())
|
||||
if (m_cow_map.is_null()) {
|
||||
m_cow_map = TRY(Bitmap::create(page_count(), true));
|
||||
reset_cow_map();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -279,7 +290,7 @@ ErrorOr<void> AnonymousVMObject::ensure_or_reset_cow_map()
|
|||
if (m_cow_map.is_null())
|
||||
TRY(ensure_cow_map());
|
||||
else
|
||||
m_cow_map.fill(true);
|
||||
reset_cow_map();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ private:
|
|||
|
||||
ErrorOr<void> ensure_cow_map();
|
||||
ErrorOr<void> ensure_or_reset_cow_map();
|
||||
void reset_cow_map();
|
||||
|
||||
Optional<CommittedPhysicalPageSet> m_unused_committed_pages;
|
||||
Bitmap m_cow_map;
|
||||
|
|
Loading…
Reference in a new issue