kernel/eka/memmodel/epoc/flexible/mmu/mmanager.cpp
branchRCL_3
changeset 41 0ffb4e86fcc9
parent 28 5b5d147c7838
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mmanager.cpp	Mon Jun 21 17:12:14 2010 +0300
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mmanager.cpp	Thu Jul 15 20:11:42 2010 +0300
@@ -131,6 +131,7 @@
 TInt DMemoryManager::MovePage(	DMemoryObject* aMemory, SPageInfo* aOldPageInfo, 
 								TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
 	{
+	MmuLock::Unlock();
 	return KErrNotSupported;
 	}
 
@@ -749,20 +750,8 @@
 										TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
 	{
 	__NK_ASSERT_DEBUG(RamAllocLock::IsHeld());
-
-	// Allocate the new page to move to, ensuring that we use the page type of the
-	// manager assigned to this page.
-	TPhysAddr newPage;
-	Mmu& m = TheMmu;
-	TInt r = m.AllocRam(&newPage, 1, aMemory->RamAllocFlags(), aMemory->iManager->PageType(), 
-						aBlockZoneId, aBlockRest);
-	if (r != KErrNone)
-		{// Failed to allocate a new page to move the page to so can't continue.
-		return r;
-		}
-	
-	r = KErrInUse;
-	MmuLock::Lock();
+	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
+	TInt r = KErrInUse;
 
 	TUint index = aOldPageInfo->Index();
 	TRACE(	("DMovableMemoryManager::MovePage(0x%08x,0x%08x,?,0x%08x,%d) index=0x%x",
@@ -775,7 +764,6 @@
 	if (!movingPageArrayPtr)
 		{// Can't move the page another operation is being performed on it.
 		MmuLock::Unlock();
-		TheMmu.FreeRam(&newPage, 1, aMemory->iManager->PageType());
 		return r;
 		}
 	__NK_ASSERT_DEBUG(RPageArray::IsPresent(*movingPageArrayPtr));
@@ -788,13 +776,41 @@
 		__NK_ASSERT_DEBUG(SPageInfo::FromPhysAddr(oldPage)->Type() == SPageInfo::EShadow);
 		}
 #endif
+	// Set the modifier so we can detect if the page state is updated.
+	aOldPageInfo->SetModifier(&pageIter);
+
+	MmuLock::Unlock();
+
+	// Allocate the new page to move to, ensuring that we use the page type of the
+	// manager assigned to this page.
+	TPhysAddr newPage;
+	Mmu& m = TheMmu;
+	TInt allocRet = m.AllocRam(&newPage, 1, aMemory->RamAllocFlags(), aMemory->iManager->PageType(), 
+						aBlockZoneId, aBlockRest);
+	if (allocRet != KErrNone)
+		{
+		MmuLock::Lock();
+		aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
+		MmuLock::Unlock();
+		return allocRet;
+		}
+
 	__NK_ASSERT_DEBUG((newPage & KPageMask) == 0);
 	__NK_ASSERT_DEBUG(newPage != oldPage);
 
-	// Set the modifier so we can detect if the page state is updated.
-	aOldPageInfo->SetModifier(&pageIter);
+	MmuLock::Lock();
+	if (aOldPageInfo->CheckModified(&pageIter) ||
+		oldPageEntry != *movingPageArrayPtr)
+		{// The page was modified or freed.
+		aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
+		MmuLock::Unlock();
+		m.FreeRam(&newPage, 1, aMemory->iManager->PageType());
+		return r;
+		}
+	MmuLock::Unlock();
 
-	// Restrict the page ready for moving.
+	// This page's contents may be changed so restrict the page to no access 
+	// so we can detect any access to it while we are moving it.
 	// Read only memory objects don't need to be restricted but we still need
 	// to discover any physically pinned mappings.
 	TBool pageRestrictedNA = !aMemory->IsReadOnly();
@@ -802,9 +818,6 @@
 										ERestrictPagesNoAccessForMoving :
 										ERestrictPagesForMovingFlag;
 
-	// This page's contents may be changed so restrict the page to no access 
-	// so we can detect any access to it while we are moving it.
-	MmuLock::Unlock();
 	// This will clear the memory objects mapping added flag so we can detect any new mappings.
 	aMemory->RestrictPages(pageIter, restrictType);
 
@@ -891,7 +904,7 @@
 #endif
 	// indicate we've stopped moving memory now...
 	MmuLock::Lock();
-	RPageArray::MovePageEnd(*movingPageArrayPtr);
+	aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
 	MmuLock::Unlock();
 
 	return r;