--- 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;