#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
}
/**
- * \fn Uint32 MM_AllocPhys()
+ * \fn tPAddr MM_AllocPhys()
* \brief Allocates a physical page
*/
tPAddr MM_AllocPhys()
/**
* \fn void MM_DerefPhys(Uint32 Addr)
*/
-void MM_DerefPhys(Uint32 Addr)
+void MM_DerefPhys(tPAddr Addr)
{
// Get page number
Addr >>= 12;
// 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 ];
+}
&& 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;