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