Changed COW to reuse current page if it is the last reference.
authorJohn Hodge <[email protected]>
Tue, 22 Sep 2009 12:17:46 +0000 (20:17 +0800)
committerJohn Hodge <[email protected]>
Tue, 22 Sep 2009 12:17:46 +0000 (20:17 +0800)
Kernel/arch/x86/include/mm_phys.h
Kernel/arch/x86/mm_phys.c
Kernel/arch/x86/mm_virt.c

index 65ab091..8d46109 100644 (file)
@@ -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
index 80e92fe..e81c99e 100644 (file)
@@ -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 ];
+}
index 25da743..8fe1b4a 100644 (file)
@@ -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;

UCC git Repository :: git.ucc.asn.au