mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-03 04:50:29 +00:00
Kernel: Don't try to return a committed page that we don't have
When we get a COW fault and discover that whoever we were COW'ing together with has either COW'ed that page on their end (or they have unmapped/exited) we simplify life for ourselves by clearing the COW bit and keeping the page we already have. (No need to COW if the page is not shared!) The act of doing this does not return a committed page to the pool. In fact, that committed page we had reserved for this purpose was used up (allocated) by our COW buddy when they COW'ed the page. This fixes a kernel panic when running TestLibCMkTemp. :^)
This commit is contained in:
parent
101486279f
commit
50472fd69f
Notes:
sideshowbarker
2024-07-18 08:20:39 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/50472fd69f7
2 changed files with 12 additions and 20 deletions
|
@ -319,20 +319,21 @@ PageFaultResponse AnonymousVMObject::handle_cow_fault(size_t page_index, Virtual
|
|||
}
|
||||
|
||||
auto& page_slot = physical_pages()[page_index];
|
||||
bool have_committed = m_shared_committed_cow_pages;
|
||||
|
||||
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");
|
||||
set_should_cow(page_index, false);
|
||||
if (have_committed) {
|
||||
if (m_shared_committed_cow_pages->return_one())
|
||||
m_shared_committed_cow_pages = nullptr;
|
||||
}
|
||||
|
||||
// If we were sharing committed COW pages with another process, and the other process
|
||||
// has exhausted the supply, we can stop counting the shared pages.
|
||||
if (m_shared_committed_cow_pages && m_shared_committed_cow_pages->is_empty())
|
||||
m_shared_committed_cow_pages = nullptr;
|
||||
|
||||
return PageFaultResponse::Continue;
|
||||
}
|
||||
|
||||
RefPtr<PhysicalPage> page;
|
||||
if (have_committed) {
|
||||
if (m_shared_committed_cow_pages) {
|
||||
dbgln_if(PAGE_FAULT_DEBUG, " >> It's a committed COW page and it's time to COW!");
|
||||
page = m_shared_committed_cow_pages->allocate_one();
|
||||
} else {
|
||||
|
@ -386,13 +387,4 @@ NonnullRefPtr<PhysicalPage> CommittedCowPages::allocate_one()
|
|||
return MM.allocate_committed_user_physical_page(MemoryManager::ShouldZeroFill::Yes);
|
||||
}
|
||||
|
||||
bool CommittedCowPages::return_one()
|
||||
{
|
||||
VERIFY(m_committed_pages > 0);
|
||||
m_committed_pages--;
|
||||
|
||||
MM.uncommit_user_physical_pages(1);
|
||||
return m_committed_pages == 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ class CommittedCowPages : public RefCounted<CommittedCowPages> {
|
|||
public:
|
||||
CommittedCowPages() = delete;
|
||||
|
||||
CommittedCowPages(size_t);
|
||||
explicit CommittedCowPages(size_t);
|
||||
~CommittedCowPages();
|
||||
|
||||
NonnullRefPtr<PhysicalPage> allocate_one();
|
||||
bool return_one();
|
||||
[[nodiscard]] NonnullRefPtr<PhysicalPage> allocate_one();
|
||||
[[nodiscard]] size_t is_empty() const { return m_committed_pages == 0; }
|
||||
|
||||
private:
|
||||
size_t m_committed_pages;
|
||||
public:
|
||||
size_t m_committed_pages { 0 };
|
||||
};
|
||||
|
||||
class AnonymousVMObject final : public VMObject {
|
||||
|
|
Loading…
Reference in a new issue