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) |
747 |
748 |
748 TInt DMovableMemoryManager::MovePage( DMemoryObject* aMemory, SPageInfo* aOldPageInfo, |
749 TInt DMovableMemoryManager::MovePage( DMemoryObject* aMemory, SPageInfo* aOldPageInfo, |
749 TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest) |
750 TPhysAddr& aNewPage, TUint aBlockZoneId, TBool aBlockRest) |
750 { |
751 { |
751 __NK_ASSERT_DEBUG(RamAllocLock::IsHeld()); |
752 __NK_ASSERT_DEBUG(RamAllocLock::IsHeld()); |
752 |
753 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
753 // Allocate the new page to move to, ensuring that we use the page type of the |
754 TInt r = KErrInUse; |
754 // manager assigned to this page. |
|
755 TPhysAddr newPage; |
|
756 Mmu& m = TheMmu; |
|
757 TInt r = m.AllocRam(&newPage, 1, aMemory->RamAllocFlags(), aMemory->iManager->PageType(), |
|
758 aBlockZoneId, aBlockRest); |
|
759 if (r != KErrNone) |
|
760 {// Failed to allocate a new page to move the page to so can't continue. |
|
761 return r; |
|
762 } |
|
763 |
|
764 r = KErrInUse; |
|
765 MmuLock::Lock(); |
|
766 |
755 |
767 TUint index = aOldPageInfo->Index(); |
756 TUint index = aOldPageInfo->Index(); |
768 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", |
769 aMemory,aOldPageInfo,aBlockZoneId,aBlockRest,index)); |
758 aMemory,aOldPageInfo,aBlockZoneId,aBlockRest,index)); |
770 __NK_ASSERT_DEBUG(aMemory==aOldPageInfo->Owner()); |
759 __NK_ASSERT_DEBUG(aMemory==aOldPageInfo->Owner()); |
773 RPageArray::TIter pageIter; |
762 RPageArray::TIter pageIter; |
774 TPhysAddr* const movingPageArrayPtr = aMemory->iPages.MovePageStart(index, pageIter); |
763 TPhysAddr* const movingPageArrayPtr = aMemory->iPages.MovePageStart(index, pageIter); |
775 if (!movingPageArrayPtr) |
764 if (!movingPageArrayPtr) |
776 {// 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. |
777 MmuLock::Unlock(); |
766 MmuLock::Unlock(); |
778 TheMmu.FreeRam(&newPage, 1, aMemory->iManager->PageType()); |
|
779 return r; |
767 return r; |
780 } |
768 } |
781 __NK_ASSERT_DEBUG(RPageArray::IsPresent(*movingPageArrayPtr)); |
769 __NK_ASSERT_DEBUG(RPageArray::IsPresent(*movingPageArrayPtr)); |
782 TPhysAddr oldPageEntry = *movingPageArrayPtr; |
770 TPhysAddr oldPageEntry = *movingPageArrayPtr; |
783 TPhysAddr oldPage = oldPageEntry & ~KPageMask; |
771 TPhysAddr oldPage = oldPageEntry & ~KPageMask; |
786 {// 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 |
787 // when the page is being shadowed. |
775 // when the page is being shadowed. |
788 __NK_ASSERT_DEBUG(SPageInfo::FromPhysAddr(oldPage)->Type() == SPageInfo::EShadow); |
776 __NK_ASSERT_DEBUG(SPageInfo::FromPhysAddr(oldPage)->Type() == SPageInfo::EShadow); |
789 } |
777 } |
790 #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 |
791 __NK_ASSERT_DEBUG((newPage & KPageMask) == 0); |
798 __NK_ASSERT_DEBUG((newPage & KPageMask) == 0); |
792 __NK_ASSERT_DEBUG(newPage != oldPage); |
799 __NK_ASSERT_DEBUG(newPage != oldPage); |
793 |
800 |
794 // Set the modifier so we can detect if the page state is updated. |
801 MmuLock::Lock(); |
795 aOldPageInfo->SetModifier(&pageIter); |
802 if (aOldPageInfo->CheckModified(&pageIter) || |
796 |
803 oldPageEntry != *movingPageArrayPtr) |
797 // 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. |
798 // 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 |
799 // to discover any physically pinned mappings. |
815 // to discover any physically pinned mappings. |
800 TBool pageRestrictedNA = !aMemory->IsReadOnly(); |
816 TBool pageRestrictedNA = !aMemory->IsReadOnly(); |
801 TRestrictPagesType restrictType = pageRestrictedNA ? |
817 TRestrictPagesType restrictType = pageRestrictedNA ? |
802 ERestrictPagesNoAccessForMoving : |
818 ERestrictPagesNoAccessForMoving : |
803 ERestrictPagesForMovingFlag; |
819 ERestrictPagesForMovingFlag; |
804 |
820 |
805 // This page's contents may be changed so restrict the page to no access |
|
806 // so we can detect any access to it while we are moving it. |
|
807 MmuLock::Unlock(); |
|
808 // 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. |
809 aMemory->RestrictPages(pageIter, restrictType); |
822 aMemory->RestrictPages(pageIter, restrictType); |
810 |
823 |
811 const TUint KOldMappingSlot = 0; |
824 const TUint KOldMappingSlot = 0; |
812 const TUint KNewMappingSlot = 1; |
825 const TUint KNewMappingSlot = 1; |