mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-03 21:10:30 +00:00
Kernel: When physical page allocation fails, try to purge something
Instead of panicking right away when we run out of physical pages, we now try to find a PurgeableVMObject with some volatile pages in it. If we find one, we purge that entire object and steal one of its pages. This makes it possible for the kernel to keep going instead of dying. Very cool. :^)
This commit is contained in:
parent
dafd715743
commit
c1f8291ce4
Notes:
sideshowbarker
2024-07-19 10:39:22 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c1f8291ce49
3 changed files with 36 additions and 3 deletions
|
@ -9,6 +9,7 @@
|
|||
#include <Kernel/VM/AnonymousVMObject.h>
|
||||
#include <Kernel/VM/InodeVMObject.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#include <Kernel/VM/PurgeableVMObject.h>
|
||||
|
||||
//#define MM_DEBUG
|
||||
//#define PAGE_FAULT_DEBUG
|
||||
|
@ -424,9 +425,25 @@ RefPtr<PhysicalPage> MemoryManager::allocate_user_physical_page(ShouldZeroFill s
|
|||
kprintf("MM: no user physical regions available (?)\n");
|
||||
}
|
||||
|
||||
kprintf("MM: no user physical pages available\n");
|
||||
ASSERT_NOT_REACHED();
|
||||
return {};
|
||||
for_each_vmobject([&](auto& vmobject) {
|
||||
if (vmobject.is_purgeable()) {
|
||||
auto& purgeable_vmobject = static_cast<PurgeableVMObject&>(vmobject);
|
||||
int purged_page_count = purgeable_vmobject.purge_with_interrupts_disabled({});
|
||||
if (purged_page_count) {
|
||||
kprintf("MM: Purge saved the day! Purged %d pages from PurgeableVMObject{%p}\n", purged_page_count, &purgeable_vmobject);
|
||||
page = find_free_user_physical_page();
|
||||
ASSERT(page);
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
if (!page) {
|
||||
kprintf("MM: no user physical pages available\n");
|
||||
ASSERT_NOT_REACHED();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MM_DEBUG
|
||||
|
|
|
@ -29,6 +29,19 @@ NonnullRefPtr<VMObject> PurgeableVMObject::clone()
|
|||
int PurgeableVMObject::purge()
|
||||
{
|
||||
LOCKER(m_paging_lock);
|
||||
return purge_impl();
|
||||
}
|
||||
|
||||
int PurgeableVMObject::purge_with_interrupts_disabled(Badge<MemoryManager>)
|
||||
{
|
||||
ASSERT_INTERRUPTS_DISABLED();
|
||||
if (m_paging_lock.is_locked())
|
||||
return 0;
|
||||
return purge_impl();
|
||||
}
|
||||
|
||||
int PurgeableVMObject::purge_impl()
|
||||
{
|
||||
if (!m_volatile)
|
||||
return 0;
|
||||
int purged_page_count = 0;
|
||||
|
|
|
@ -10,6 +10,7 @@ public:
|
|||
virtual NonnullRefPtr<VMObject> clone() override;
|
||||
|
||||
int purge();
|
||||
int purge_with_interrupts_disabled(Badge<MemoryManager>);
|
||||
|
||||
bool was_purged() const { return m_was_purged; }
|
||||
void set_was_purged(bool b) { m_was_purged = b; }
|
||||
|
@ -21,6 +22,8 @@ private:
|
|||
explicit PurgeableVMObject(size_t);
|
||||
explicit PurgeableVMObject(const PurgeableVMObject&);
|
||||
|
||||
int purge_impl();
|
||||
|
||||
PurgeableVMObject& operator=(const PurgeableVMObject&) = delete;
|
||||
PurgeableVMObject& operator=(PurgeableVMObject&&) = delete;
|
||||
PurgeableVMObject(PurgeableVMObject&&) = delete;
|
||||
|
|
Loading…
Reference in a new issue