diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index db2a55e0f7..8f44ddc25a 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include //#define MM_DEBUG //#define PAGE_FAULT_DEBUG @@ -424,9 +425,25 @@ RefPtr 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(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 diff --git a/Kernel/VM/PurgeableVMObject.cpp b/Kernel/VM/PurgeableVMObject.cpp index d06b27a901..f671f80817 100644 --- a/Kernel/VM/PurgeableVMObject.cpp +++ b/Kernel/VM/PurgeableVMObject.cpp @@ -29,6 +29,19 @@ NonnullRefPtr PurgeableVMObject::clone() int PurgeableVMObject::purge() { LOCKER(m_paging_lock); + return purge_impl(); +} + +int PurgeableVMObject::purge_with_interrupts_disabled(Badge) +{ + 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; diff --git a/Kernel/VM/PurgeableVMObject.h b/Kernel/VM/PurgeableVMObject.h index d352ff7c97..c357ebc47c 100644 --- a/Kernel/VM/PurgeableVMObject.h +++ b/Kernel/VM/PurgeableVMObject.h @@ -10,6 +10,7 @@ public: virtual NonnullRefPtr clone() override; int purge(); + int purge_with_interrupts_disabled(Badge); 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;