1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 19:35:09 +00:00

Kernel: Uncommit a shared COW page when discovering it was unshared

When we hit a COW fault and discover than no other process is sharing
the physical page, we simply remap it r/w and save ourselves the
trouble. When this happens, we can also give back (uncommit) one of our
shared committed COW pages, since we won't be needing it.

We had this optimization before, but I mistakenly removed it in
50472fd69f since I had misunderstood
it to be the reason for a panic.
This commit is contained in:
Andreas Kling 2021-08-05 17:14:13 +02:00
parent 843d0d0d15
commit dd58d0f650
4 changed files with 23 additions and 1 deletions

View file

@ -315,6 +315,12 @@ PageFaultResponse AnonymousVMObject::handle_cow_fault(size_t page_index, Virtual
if (page_slot->ref_count() == 1) { if (page_slot->ref_count() == 1) {
dbgln_if(PAGE_FAULT_DEBUG, " >> It's a COW page but nobody is sharing it anymore. Remap r/w"); dbgln_if(PAGE_FAULT_DEBUG, " >> It's a COW page but nobody is sharing it anymore. Remap r/w");
set_should_cow(page_index, false); set_should_cow(page_index, false);
if (m_shared_committed_cow_pages) {
m_shared_committed_cow_pages->uncommit_one();
if (!m_shared_committed_cow_pages->is_empty())
m_shared_committed_cow_pages = nullptr;
}
return PageFaultResponse::Continue; return PageFaultResponse::Continue;
} }
@ -368,4 +374,10 @@ NonnullRefPtr<PhysicalPage> AnonymousVMObject::SharedCommittedCowPages::take_one
return m_committed_pages.take_one(); return m_committed_pages.take_one();
} }
void AnonymousVMObject::SharedCommittedCowPages::uncommit_one()
{
ScopedSpinLock locker(m_lock);
m_committed_pages.uncommit_one();
}
} }

View file

@ -70,9 +70,11 @@ private:
explicit SharedCommittedCowPages(CommittedPhysicalPageSet&&); explicit SharedCommittedCowPages(CommittedPhysicalPageSet&&);
~SharedCommittedCowPages(); ~SharedCommittedCowPages();
[[nodiscard]] NonnullRefPtr<PhysicalPage> take_one();
[[nodiscard]] bool is_empty() const { return m_committed_pages.is_empty(); } [[nodiscard]] bool is_empty() const { return m_committed_pages.is_empty(); }
[[nodiscard]] NonnullRefPtr<PhysicalPage> take_one();
void uncommit_one();
public: public:
SpinLock<u8> m_lock; SpinLock<u8> m_lock;
CommittedPhysicalPageSet m_committed_pages; CommittedPhysicalPageSet m_committed_pages;

View file

@ -1137,4 +1137,11 @@ NonnullRefPtr<PhysicalPage> CommittedPhysicalPageSet::take_one()
return MM.allocate_committed_user_physical_page(MemoryManager::ShouldZeroFill::Yes); return MM.allocate_committed_user_physical_page(MemoryManager::ShouldZeroFill::Yes);
} }
void CommittedPhysicalPageSet::uncommit_one()
{
VERIFY(m_page_count > 0);
--m_page_count;
MM.uncommit_user_physical_pages({}, 1);
}
} }

View file

@ -126,6 +126,7 @@ public:
size_t page_count() const { return m_page_count; } size_t page_count() const { return m_page_count; }
[[nodiscard]] NonnullRefPtr<PhysicalPage> take_one(); [[nodiscard]] NonnullRefPtr<PhysicalPage> take_one();
void uncommit_one();
void operator=(CommittedPhysicalPageSet&&) = delete; void operator=(CommittedPhysicalPageSet&&) = delete;