From f7f1b08ec035ddef61218b51d8e9a9d4c1ee7b9a Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 22 Sep 2009 20:17:46 +0800 Subject: [PATCH] Changed COW to reuse current page if it is the last reference. --- Kernel/arch/x86/include/mm_phys.h | 3 ++- Kernel/arch/x86/mm_phys.c | 19 +++++++++++++++++-- Kernel/arch/x86/mm_virt.c | 16 ++++++++++++---- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Kernel/arch/x86/include/mm_phys.h b/Kernel/arch/x86/include/mm_phys.h index 65ab091b..8d461098 100644 --- a/Kernel/arch/x86/include/mm_phys.h +++ b/Kernel/arch/x86/include/mm_phys.h @@ -6,8 +6,9 @@ #define _MM_PHYS_H // === FUNCTIONS === -extern Uint32 MM_AllocPhys(); +extern tPAddr MM_AllocPhys(); extern void MM_RefPhys(Uint32 Addr); extern void MM_DerefPhys(Uint32 Addr); +extern int MM_GetRefCount(tPAddr Addr); #endif diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index 80e92fe6..e81c99e6 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -85,7 +85,7 @@ void MM_Install(tMBoot_Info *MBoot) } /** - * \fn Uint32 MM_AllocPhys() + * \fn tPAddr MM_AllocPhys() * \brief Allocates a physical page */ tPAddr MM_AllocPhys() @@ -154,7 +154,7 @@ void MM_RefPhys(tPAddr Addr) /** * \fn void MM_DerefPhys(Uint32 Addr) */ -void MM_DerefPhys(Uint32 Addr) +void MM_DerefPhys(tPAddr Addr) { // Get page number Addr >>= 12; @@ -185,3 +185,18 @@ void MM_DerefPhys(Uint32 Addr) // Release spinlock RELEASE( &giPhysAlloc ); } + +/** + * \fn int MM_GetRefCount(tPAddr Addr) + */ +int MM_GetRefCount(tPAddr Addr) +{ + // Get page number + Addr >>= 12; + + // We don't care about non-ram pages + if(Addr >= giPageCount) return -1; + + // Check if it is freed + return gaPageReferences[ Addr ]; +} diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 25da7433..8fe1b4aa 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -105,10 +105,18 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) && gaPageTable[Addr>>12] & PF_COW ) { tPAddr paddr; - paddr = MM_DuplicatePage( Addr ); - MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF ); - gaPageTable[Addr>>12] &= PF_USER; - gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE; + if(MM_GetRefCount( gaPageTable[Addr>>12] & ~0xFFF ) == 0) + { + gaPageTable[Addr>>12] &= ~PF_COW; + gaPageTable[Addr>>12] |= PF_PRESENT|PF_WRITE; + } + else + { + paddr = MM_DuplicatePage( Addr ); + MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF ); + gaPageTable[Addr>>12] &= PF_USER; + gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE; + } INVLPG( Addr & ~0xFFF ); //LEAVE('-') return; -- 2.20.1