From 9e62eb48566f0c5e77460ed5923ff9d228fcd195 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 5 Nov 2018 14:10:18 +0100 Subject: [PATCH] Only COW on fault if the physical page has retain_count > 1. This makes COW pages lazily-but-transparently revert back to read/write. --- Kernel/MemoryManager.cpp | 10 ++++++++++ Kernel/MemoryManager.h | 2 ++ Kernel/ProcFileSystem.cpp | 5 +++-- Kernel/i386.cpp | 2 ++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 93989f8d0d..1b0d801ec9 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -223,6 +223,16 @@ Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr) bool MemoryManager::copy_on_write(Process& process, Region& region, unsigned page_index_in_region) { + ASSERT_INTERRUPTS_DISABLED(); + if (region.physical_pages[page_index_in_region]->retain_count() == 1) { +#ifdef PAGE_FAULT_DEBUG + dbgprintf(" >> It's a COW page but nobody is sharing it anymore. Remap r/w\n"); +#endif + region.cow_map.set(page_index_in_region, false); + remap_region_page(process.m_page_directory, region, page_index_in_region, true); + return true; + } + #ifdef PAGE_FAULT_DEBUG dbgprintf(" >> It's a COW page and it's time to COW!\n"); #endif diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 415fa83a28..9477e420d2 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -37,6 +37,8 @@ public: return_to_freelist(); } + unsigned retain_count() const { return m_retain_count; } + private: PhysicalPage(PhysicalAddress paddr) : m_paddr(paddr) diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 0516089dbd..23e05d3604 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -61,9 +61,10 @@ ByteBuffer procfs$pid_vm(Process& process) region->name.characters()); for (size_t i = 0; i < region->physical_pages.size(); ++i) { auto& physical_page = region->physical_pages[i]; - ptr += ksprintf(ptr, "P%x%s ", + ptr += ksprintf(ptr, "P%x%s(%u) ", physical_page ? physical_page->paddr().get() : 0, - region->cow_map.get(i) ? "!" : "" + region->cow_map.get(i) ? "!" : "", + physical_page->retain_count() ); } ptr += ksprintf(ptr, "\n"); diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index dfc903a48c..244a5b4c71 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -8,6 +8,8 @@ #include "IRQHandler.h" #include "PIC.h" +//#define PAGE_FAULT_DEBUG + struct DescriptorTablePointer { WORD size; void* address;