kernel/eka/memmodel/epoc/flexible/mmu/mmanager.cpp
changeset 201 43365a9b78a3
parent 152 657f875b013e
equal deleted inserted replaced
200:73ea206103e6 201:43365a9b78a3
   129 
   129 
   130 
   130 
   131 TInt DMemoryManager::MovePage(	DMemoryObject* aMemory, SPageInfo* aOldPageInfo, 
   131 TInt DMemoryManager::MovePage(	DMemoryObject* aMemory, SPageInfo* aOldPageInfo, 
   132 								TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
   132 								TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
   133 	{
   133 	{
       
   134 	MmuLock::Unlock();
   134 	return KErrNotSupported;
   135 	return KErrNotSupported;
   135 	}
   136 	}
   136 
   137 
   137 
   138 
   138 TInt DMemoryManager::MoveAndAllocPage(DMemoryObject*, SPageInfo*, TZonePageType)
   139 TInt DMemoryManager::MoveAndAllocPage(DMemoryObject*, SPageInfo*, TZonePageType)
   139 	{
   140 	{
       
   141 	__NK_ASSERT_DEBUG(0);	// This should only be invoked on managers that can move or discard pages.
   140 	return KErrNotSupported;
   142 	return KErrNotSupported;
   141 	}
   143 	}
   142 
   144 
   143 
   145 
   144 TZonePageType DMemoryManager::PageType()
   146 TZonePageType DMemoryManager::PageType()
   746 
   748 
   747 TInt DMovableMemoryManager::MovePage(	DMemoryObject* aMemory, SPageInfo* aOldPageInfo, 
   749 TInt DMovableMemoryManager::MovePage(	DMemoryObject* aMemory, SPageInfo* aOldPageInfo, 
   748 										TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
   750 										TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest)
   749 	{
   751 	{
   750 	__NK_ASSERT_DEBUG(RamAllocLock::IsHeld());
   752 	__NK_ASSERT_DEBUG(RamAllocLock::IsHeld());
   751 
   753 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
   752 	// Allocate the new page to move to, ensuring that we use the page type of the
   754 	TInt r = KErrInUse;
   753 	// manager assigned to this page.
       
   754 	TPhysAddr newPage;
       
   755 	Mmu& m = TheMmu;
       
   756 	TInt r = m.AllocRam(&newPage, 1, aMemory->RamAllocFlags(), aMemory->iManager->PageType(), 
       
   757 						aBlockZoneId, aBlockRest);
       
   758 	if (r != KErrNone)
       
   759 		{// Failed to allocate a new page to move the page to so can't continue.
       
   760 		return r;
       
   761 		}
       
   762 	
       
   763 	r = KErrInUse;
       
   764 	MmuLock::Lock();
       
   765 
   755 
   766 	TUint index = aOldPageInfo->Index();
   756 	TUint index = aOldPageInfo->Index();
   767 	TRACE(	("DMovableMemoryManager::MovePage(0x%08x,0x%08x,?,0x%08x,%d) index=0x%x",
   757 	TRACE(	("DMovableMemoryManager::MovePage(0x%08x,0x%08x,?,0x%08x,%d) index=0x%x",
   768 			aMemory,aOldPageInfo,aBlockZoneId,aBlockRest,index));
   758 			aMemory,aOldPageInfo,aBlockZoneId,aBlockRest,index));
   769 	__NK_ASSERT_DEBUG(aMemory==aOldPageInfo->Owner());
   759 	__NK_ASSERT_DEBUG(aMemory==aOldPageInfo->Owner());
   772 	RPageArray::TIter pageIter;
   762 	RPageArray::TIter pageIter;
   773 	TPhysAddr* const movingPageArrayPtr = aMemory->iPages.MovePageStart(index, pageIter);
   763 	TPhysAddr* const movingPageArrayPtr = aMemory->iPages.MovePageStart(index, pageIter);
   774 	if (!movingPageArrayPtr)
   764 	if (!movingPageArrayPtr)
   775 		{// Can't move the page another operation is being performed on it.
   765 		{// Can't move the page another operation is being performed on it.
   776 		MmuLock::Unlock();
   766 		MmuLock::Unlock();
   777 		TheMmu.FreeRam(&newPage, 1, aMemory->iManager->PageType());
       
   778 		return r;
   767 		return r;
   779 		}
   768 		}
   780 	__NK_ASSERT_DEBUG(RPageArray::IsPresent(*movingPageArrayPtr));
   769 	__NK_ASSERT_DEBUG(RPageArray::IsPresent(*movingPageArrayPtr));
   781 	TPhysAddr oldPageEntry = *movingPageArrayPtr;
   770 	TPhysAddr oldPageEntry = *movingPageArrayPtr;
   782 	TPhysAddr oldPage = oldPageEntry & ~KPageMask;
   771 	TPhysAddr oldPage = oldPageEntry & ~KPageMask;
   785 		{// The address of page array entry and the page info should match except
   774 		{// The address of page array entry and the page info should match except
   786 		// when the page is being shadowed.
   775 		// when the page is being shadowed.
   787 		__NK_ASSERT_DEBUG(SPageInfo::FromPhysAddr(oldPage)->Type() == SPageInfo::EShadow);
   776 		__NK_ASSERT_DEBUG(SPageInfo::FromPhysAddr(oldPage)->Type() == SPageInfo::EShadow);
   788 		}
   777 		}
   789 #endif
   778 #endif
       
   779 	// Set the modifier so we can detect if the page state is updated.
       
   780 	aOldPageInfo->SetModifier(&pageIter);
       
   781 
       
   782 	MmuLock::Unlock();
       
   783 
       
   784 	// Allocate the new page to move to, ensuring that we use the page type of the
       
   785 	// manager assigned to this page.
       
   786 	TPhysAddr newPage;
       
   787 	Mmu& m = TheMmu;
       
   788 	TInt allocRet = m.AllocRam(&newPage, 1, aMemory->RamAllocFlags(), aMemory->iManager->PageType(), 
       
   789 						aBlockZoneId, aBlockRest);
       
   790 	if (allocRet != KErrNone)
       
   791 		{
       
   792 		MmuLock::Lock();
       
   793 		aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
       
   794 		MmuLock::Unlock();
       
   795 		return allocRet;
       
   796 		}
       
   797 
   790 	__NK_ASSERT_DEBUG((newPage & KPageMask) == 0);
   798 	__NK_ASSERT_DEBUG((newPage & KPageMask) == 0);
   791 	__NK_ASSERT_DEBUG(newPage != oldPage);
   799 	__NK_ASSERT_DEBUG(newPage != oldPage);
   792 
   800 
   793 	// Set the modifier so we can detect if the page state is updated.
   801 	MmuLock::Lock();
   794 	aOldPageInfo->SetModifier(&pageIter);
   802 	if (aOldPageInfo->CheckModified(&pageIter) ||
   795 
   803 		oldPageEntry != *movingPageArrayPtr)
   796 	// Restrict the page ready for moving.
   804 		{// The page was modified or freed.
       
   805 		aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
       
   806 		MmuLock::Unlock();
       
   807 		m.FreeRam(&newPage, 1, aMemory->iManager->PageType());
       
   808 		return r;
       
   809 		}
       
   810 	MmuLock::Unlock();
       
   811 
       
   812 	// This page's contents may be changed so restrict the page to no access 
       
   813 	// so we can detect any access to it while we are moving it.
   797 	// Read only memory objects don't need to be restricted but we still need
   814 	// Read only memory objects don't need to be restricted but we still need
   798 	// to discover any physically pinned mappings.
   815 	// to discover any physically pinned mappings.
   799 	TBool pageRestrictedNA = !aMemory->IsReadOnly();
   816 	TBool pageRestrictedNA = !aMemory->IsReadOnly();
   800 	TRestrictPagesType restrictType = 	pageRestrictedNA ? 
   817 	TRestrictPagesType restrictType = 	pageRestrictedNA ? 
   801 										ERestrictPagesNoAccessForMoving :
   818 										ERestrictPagesNoAccessForMoving :
   802 										ERestrictPagesForMovingFlag;
   819 										ERestrictPagesForMovingFlag;
   803 
   820 
   804 	// This page's contents may be changed so restrict the page to no access 
       
   805 	// so we can detect any access to it while we are moving it.
       
   806 	MmuLock::Unlock();
       
   807 	// This will clear the memory objects mapping added flag so we can detect any new mappings.
   821 	// This will clear the memory objects mapping added flag so we can detect any new mappings.
   808 	aMemory->RestrictPages(pageIter, restrictType);
   822 	aMemory->RestrictPages(pageIter, restrictType);
   809 
   823 
   810 	const TUint KOldMappingSlot = 0;
   824 	const TUint KOldMappingSlot = 0;
   811 	const TUint KNewMappingSlot = 1;
   825 	const TUint KNewMappingSlot = 1;
   814 	// Verify that page restricting wasn't interrupted, if it was then the page 
   828 	// Verify that page restricting wasn't interrupted, if it was then the page 
   815 	// can't be moved so remap it.
   829 	// can't be moved so remap it.
   816 	// If the page array entry (*movingPageArrayPtr) has been modified then a pinning 
   830 	// If the page array entry (*movingPageArrayPtr) has been modified then a pinning 
   817 	// veto'd the preparation.
   831 	// veto'd the preparation.
   818 	MmuLock::Lock();
   832 	MmuLock::Lock();
   819 	if (aOldPageInfo->CheckModified(&pageIter) || oldPageEntry != *movingPageArrayPtr)
   833 	if (aOldPageInfo->CheckModified(&pageIter) ||
       
   834 		oldPageEntry != *movingPageArrayPtr)
   820 		{// Page is pinned or has been modified by another operation.
   835 		{// Page is pinned or has been modified by another operation.
   821 		MmuLock::Unlock();
   836 		MmuLock::Unlock();
   822 		TheMmu.FreeRam(&newPage, 1, aMemory->iManager->PageType());
   837 		TheMmu.FreeRam(&newPage, 1, aMemory->iManager->PageType());
   823 		goto remap;
   838 		goto remap;
   824 		}
   839 		}
   839 #ifndef _DEBUG
   854 #ifndef _DEBUG
   840 	TheMmu.UnmapTemp(KOldMappingSlot);
   855 	TheMmu.UnmapTemp(KOldMappingSlot);
   841 #endif
   856 #endif
   842 	
   857 	
   843 	MmuLock::Lock();
   858 	MmuLock::Lock();
   844 	if (!aOldPageInfo->CheckModified(&pageIter) && oldPageEntry == *movingPageArrayPtr &&
   859 	if (!aOldPageInfo->CheckModified(&pageIter) &&
       
   860 		oldPageEntry == *movingPageArrayPtr &&
   845 		!aMemory->MappingAddedFlag())
   861 		!aMemory->MappingAddedFlag())
   846 		{
   862 		{
   847 		// The page has been copied without anyone modifying it so set the page 
   863 		// The page has been copied without anyone modifying it so set the page 
   848 		// array entry to new physical address and map the page.
   864 		// array entry to new physical address and map the page.
   849 		RPageArray::PageMoveNewAddr(*movingPageArrayPtr, newPage);
   865 		RPageArray::PageMoveNewAddr(*movingPageArrayPtr, newPage);
   886 #else
   902 #else
   887 		}
   903 		}
   888 #endif
   904 #endif
   889 	// indicate we've stopped moving memory now...
   905 	// indicate we've stopped moving memory now...
   890 	MmuLock::Lock();
   906 	MmuLock::Lock();
   891 	RPageArray::MovePageEnd(*movingPageArrayPtr);
   907 	aMemory->iPages.MovePageEnd(*movingPageArrayPtr, index);
   892 	MmuLock::Unlock();
   908 	MmuLock::Unlock();
   893 
   909 
   894 	return r;
   910 	return r;
   895 	}
   911 	}
   896 
   912 
  1117 			// page successfully unmapped...
  1133 			// page successfully unmapped...
  1118 			aPageInfo->SetReadOnly(); // page not mapped, so must be read-only
  1134 			aPageInfo->SetReadOnly(); // page not mapped, so must be read-only
  1119 
  1135 
  1120 			// attempt to clean the page if it is dirty...
  1136 			// attempt to clean the page if it is dirty...
  1121 			if (aPageInfo->IsDirty())
  1137 			if (aPageInfo->IsDirty())
       
  1138 				{
       
  1139 				//Kern::Printf("WDP: Cleaning single page in StealPage");
  1122 				aMemory->iManager->CleanPages(1, &aPageInfo, EFalse);
  1140 				aMemory->iManager->CleanPages(1, &aPageInfo, EFalse);
       
  1141 				}
  1123 
  1142 
  1124 			if(aPageInfo)
  1143 			if(aPageInfo)
  1125 				{
  1144 				{
  1126 				// page successfully stolen...
  1145 				// page successfully stolen...
  1127 				__NK_ASSERT_DEBUG((*p^page)<(TUint)KPageSize); // sanity check, page should still be allocated to us
  1146 				__NK_ASSERT_DEBUG((*p^page)<(TUint)KPageSize); // sanity check, page should still be allocated to us
  1533 
  1552 
  1534 	MmuLock::Lock();
  1553 	MmuLock::Lock();
  1535 
  1554 
  1536 	page = *p;
  1555 	page = *p;
  1537 	if(aPageInfo->CheckModified(&pageList) || page!=originalPage/*page state changed*/)
  1556 	if(aPageInfo->CheckModified(&pageList) || page!=originalPage/*page state changed*/)
  1538 		{
       
  1539 		// page state was changed by someone else...
       
  1540 		r = KErrInUse;
  1557 		r = KErrInUse;
  1541 		}
       
  1542 	else
  1558 	else
  1543 		{
  1559 		{
  1544 		// nobody else has modified page state, so restrictions successfully applied...
  1560 		// nobody else has modified page state, so restrictions successfully applied...
  1545 		*p = (page&~RPageArray::EStateMask)|RPageArray::ECommitted; // restore state
  1561 		*p = (page&~RPageArray::EStateMask)|RPageArray::ECommitted; // restore state
  1546 		aPageInfo->SetReadOnly();
  1562 		aPageInfo->SetReadOnly();
  1675 TInt DPagedMemoryManager::DoPin(DMemoryObject* aMemory, TUint aIndex, TUint aCount, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs)
  1691 TInt DPagedMemoryManager::DoPin(DMemoryObject* aMemory, TUint aIndex, TUint aCount, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs)
  1676 	{
  1692 	{
  1677 	TRACE(("DPagedMemoryManager::DoPin(0x%08x,0x%08x,0x%08x,0x%08x)",aMemory, aIndex, aCount, aMapping));
  1693 	TRACE(("DPagedMemoryManager::DoPin(0x%08x,0x%08x,0x%08x,0x%08x)",aMemory, aIndex, aCount, aMapping));
  1678 	__ASSERT_CRITICAL;
  1694 	__ASSERT_CRITICAL;
  1679 	__NK_ASSERT_DEBUG(aPinArgs.HaveSufficientPages(aCount));
  1695 	__NK_ASSERT_DEBUG(aPinArgs.HaveSufficientPages(aCount));
       
  1696 	__NK_ASSERT_DEBUG(aMapping->IsPinned());
       
  1697 	__NK_ASSERT_DEBUG(!aMapping->PagesPinned());
  1680 
  1698 
  1681 	// check and allocate page array entries...
  1699 	// check and allocate page array entries...
  1682 	RPageArray::TIter pageList;
  1700 	RPageArray::TIter pageList;
  1683 	TInt r = aMemory->iPages.AddStart(aIndex,aCount,pageList,true);
  1701 	TInt r = aMemory->iPages.AddStart(aIndex,aCount,pageList,true);
  1684 	if(r!=KErrNone)
  1702 	if(r!=KErrNone)