55 |
84 |
56 TInt ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
85 TInt ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
57 TInt UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
86 TInt UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
58 TBool IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
87 TBool IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount); |
59 |
88 |
60 TInt ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, DPageReadRequest* aRequest, TPhysAddr* aPhysAddrs); |
89 TInt ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs); |
61 TInt WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TBool aBackground); |
90 TInt WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground); |
62 |
91 |
63 void GetSwapInfo(SVMSwapInfo& aInfoOut); |
92 void GetSwapInfo(SVMSwapInfo& aInfoOut); |
64 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds); |
93 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds); |
|
94 void SetSwapAlign(TUint aSwapAlign); |
65 |
95 |
66 private: |
96 private: |
67 inline TSwapState SwapState(TUint aSwapData); |
97 inline TSwapState SwapState(TUint aSwapData); |
68 inline TInt SwapIndex(TUint aSwapData); |
98 inline TInt SwapIndex(TUint aSwapData); |
69 inline TUint SwapData(TSwapState aSwapState, TInt aSwapIndex); |
99 inline TUint SwapData(TSwapState aSwapState, TInt aSwapIndex); |
70 |
100 |
71 TInt AllocSwapIndex(TInt aCount); |
101 TInt AllocSwapIndex(TUint aCount); |
72 void FreeSwapIndex(TInt aSwapIndex); |
102 void FreeSwapIndex(TInt aSwapIndex); |
73 void CheckSwapThresholdsAndUnlock(TUint aInitial); |
103 void CheckSwapThresholdsAndUnlock(TUint aInitial); |
74 |
104 |
75 void DoDeleteNotify(TUint aSwapIndex); |
105 void DoDeleteNotify(TUint aSwapIndex); |
76 TInt DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aSwapIndex, TBool aBackground); |
106 TInt DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aPageIndex, TPhysAddr* aPhysAddrs, TInt aSwapIndex, TBool aBackground); |
77 |
107 |
78 private: |
108 private: |
79 DPagingDevice* iDevice; ///< Paging device used to read and write swap pages |
109 DPagingDevice* iDevice; ///< Paging device used to read and write swap pages |
80 |
110 |
81 NFastMutex iSwapLock; ///< Fast mutex protecting access to all members below |
111 NFastMutex iSwapLock; ///< Fast mutex protecting access to all members below |
82 TUint iFreePageCount; ///< Number of swap pages that have not been reserved |
112 TUint iFreePageCount; ///< Number of swap pages that have not been reserved |
83 TBitMapAllocator* iBitMap; ///< Bitmap of swap pages that have been allocated |
113 TBitMapAllocator* iBitMap; ///< Bitmap of swap pages that have been allocated |
|
114 TUint iSwapAlign; ///< Log2 number of pages to align swap writes to |
84 TUint iAllocOffset; ///< Next offset to try when allocating a swap page |
115 TUint iAllocOffset; ///< Next offset to try when allocating a swap page |
85 TUint iSwapThesholdLow; |
116 TUint iSwapThesholdLow; |
86 TUint iSwapThesholdGood; |
117 TUint iSwapThesholdGood; |
87 }; |
118 }; |
88 |
119 |
89 |
120 |
90 /** |
121 /** |
91 Manager for demand paged memory objects which contain writeable data. |
122 Manager for demand paged memory objects which contain writeable data. |
92 The contents of the memory are written to a backing store whenever its |
123 The contents of the memory are written to a backing store whenever its |
93 pages are 'paged out'. |
124 pages are 'paged out'. |
94 |
125 |
95 @see DSwapManager |
126 @see DSwapManager |
96 */ |
127 */ |
97 class DDataPagedMemoryManager : public DPagedMemoryManager |
128 class DDataPagedMemoryManager : public DPagedMemoryManager |
98 { |
129 { |
99 private: |
130 private: |
100 // from DMemoryManager... |
131 // from DMemoryManager... |
112 virtual TBool IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
143 virtual TBool IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
113 |
144 |
114 public: |
145 public: |
115 void GetSwapInfo(SVMSwapInfo& aInfoOut); |
146 void GetSwapInfo(SVMSwapInfo& aInfoOut); |
116 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds); |
147 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds); |
|
148 TBool PhysicalAccessSupported(); |
|
149 TBool UsePhysicalAccess(); |
|
150 void SetUsePhysicalAccess(TBool aUsePhysicalAccess); |
|
151 TUint PreferredWriteSize(); |
|
152 TUint PreferredSwapAlignment(); |
|
153 TInt SetWriteSize(TUint aWriteShift); |
117 |
154 |
118 private: |
155 private: |
119 TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground); |
156 TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground); |
120 |
157 |
121 private: |
158 private: |
202 |
255 |
203 @param aCount The number of page's worth of space to allocate. |
256 @param aCount The number of page's worth of space to allocate. |
204 |
257 |
205 @return The swap index of the first location allocated. |
258 @return The swap index of the first location allocated. |
206 */ |
259 */ |
207 TInt DSwapManager::AllocSwapIndex(TInt aCount) |
260 TInt DSwapManager::AllocSwapIndex(TUint aCount) |
208 { |
261 { |
209 __NK_ASSERT_DEBUG(aCount > 0 && aCount <= KMaxPagesToClean); |
262 TRACE2(("DSwapManager::AllocSwapIndex %d", aCount)); |
|
263 |
|
264 __NK_ASSERT_DEBUG(aCount <= KMaxPagesToClean); |
210 NKern::FMWait(&iSwapLock); |
265 NKern::FMWait(&iSwapLock); |
211 |
266 |
212 // search for run of aCount from iAllocOffset to end |
267 TInt carry; |
213 TInt carry = 0; |
|
214 TInt l = KMaxTInt; |
268 TInt l = KMaxTInt; |
215 TInt swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset); |
269 TInt swapIndex = -1; |
216 |
270 |
217 // if search failed, retry from beginning |
271 // if size suitable for alignment, search for aligned run of aCount from iAllocOffset to end, |
|
272 // then from beginning |
|
273 // |
|
274 // note that this aligns writes that at least as large as the alignment size - an alternative |
|
275 // policy might be to align writes that are an exact multiple of the alignment size |
|
276 if (iSwapAlign && aCount >= (1u << iSwapAlign)) |
|
277 { |
|
278 carry = 0; |
|
279 swapIndex = iBitMap->AllocAligned(aCount, iSwapAlign, 0, EFalse, carry, l, iAllocOffset); |
|
280 if (swapIndex < 0) |
|
281 { |
|
282 carry = 0; |
|
283 swapIndex = iBitMap->AllocAligned(aCount, iSwapAlign, 0, EFalse, carry, l, 0); |
|
284 } |
|
285 } |
|
286 |
|
287 // if not doing aligned search, or aligned search failed, retry without alignment |
218 if (swapIndex < 0) |
288 if (swapIndex < 0) |
219 { |
289 { |
220 iAllocOffset = 0; |
|
221 carry = 0; |
290 carry = 0; |
222 swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset); |
291 swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset); |
|
292 if (swapIndex < 0) |
|
293 { |
|
294 carry = 0; |
|
295 swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, 0); |
|
296 } |
223 } |
297 } |
224 |
298 |
225 // if we found one then mark it as allocated and update iAllocOffset |
299 // if we found one then mark it as allocated and update iAllocOffset |
226 if (swapIndex >= 0) |
300 if (swapIndex >= 0) |
227 { |
301 { |
228 __NK_ASSERT_DEBUG(swapIndex <= (iBitMap->iSize - aCount)); |
302 __NK_ASSERT_DEBUG(swapIndex <= (TInt)(iBitMap->iSize - aCount)); |
229 iBitMap->Alloc(swapIndex, aCount); |
303 iBitMap->Alloc(swapIndex, aCount); |
230 iAllocOffset = (swapIndex + aCount) % iBitMap->iSize; |
304 iAllocOffset = (swapIndex + aCount) % iBitMap->iSize; |
231 } |
305 } |
232 |
306 |
233 NKern::FMSignal(&iSwapLock); |
307 NKern::FMSignal(&iSwapLock); |
234 __NK_ASSERT_DEBUG(swapIndex >= 0 || aCount > 1); // can't fail to allocate single page |
308 __NK_ASSERT_DEBUG(swapIndex >= 0 || aCount > 1); // can't fail to allocate single page |
|
309 |
|
310 TRACE2(("DSwapManager::AllocSwapIndex returns %d", swapIndex)); |
235 return swapIndex; |
311 return swapIndex; |
236 } |
312 } |
237 |
313 |
238 |
314 |
239 /** |
315 /** |
456 @param aBackground Whether this is being called in the background by the page cleaning thread |
532 @param aBackground Whether this is being called in the background by the page cleaning thread |
457 as opposed to on demand when a free page is required. |
533 as opposed to on demand when a free page is required. |
458 |
534 |
459 @pre Called with page cleaning lock held |
535 @pre Called with page cleaning lock held |
460 */ |
536 */ |
461 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TBool aBackground) |
537 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground) |
462 { |
538 { |
|
539 TRACE(("DSwapManager::WriteSwapPages %d pages", aCount)); |
|
540 |
463 __ASSERT_CRITICAL; // so we can pass the paging device a stack-allocated TThreadMessage |
541 __ASSERT_CRITICAL; // so we can pass the paging device a stack-allocated TThreadMessage |
464 __NK_ASSERT_DEBUG(PageCleaningLock::IsHeld()); |
542 __NK_ASSERT_DEBUG(PageCleaningLock::IsHeld()); |
465 |
543 |
466 START_PAGING_BENCHMARK; |
544 START_PAGING_BENCHMARK; |
467 |
545 |
501 else |
579 else |
502 { |
580 { |
503 if (startIndex != -1) |
581 if (startIndex != -1) |
504 { |
582 { |
505 // write pages from startIndex to i exclusive |
583 // write pages from startIndex to i exclusive |
506 TInt count = i - startIndex; |
584 TUint count = i - startIndex; |
507 __NK_ASSERT_DEBUG(count > 0 && count <= KMaxPagesToClean); |
585 __NK_ASSERT_DEBUG(count > 0 && count <= KMaxPagesToClean); |
508 |
586 |
509 // Get a new swap location for these pages, writing them all together if possible |
587 // Get a new swap location for these pages, writing them all together if possible |
510 TInt swapIndex = AllocSwapIndex(count); |
588 TInt swapIndex = AllocSwapIndex(count); |
511 if (swapIndex >= 0) |
589 if (swapIndex >= 0) |
512 r = DoWriteSwapPages(&aMemory[startIndex], &aIndex[startIndex], count, aLinAddr + (startIndex << KPageShift), swapIndex, aBackground); |
590 r = DoWriteSwapPages(&aMemory[startIndex], &aIndex[startIndex], count, aLinAddr, startIndex, aPhysAddrs, swapIndex, aBackground); |
513 else |
591 else |
514 { |
592 { |
515 // Otherwise, write them individually |
593 // Otherwise, write them individually |
516 for (TUint j = startIndex ; j < i ; ++j) |
594 for (TUint j = startIndex ; j < i ; ++j) |
517 { |
595 { |
518 swapIndex = AllocSwapIndex(1); |
596 swapIndex = AllocSwapIndex(1); |
519 __NK_ASSERT_DEBUG(swapIndex >= 0); |
597 __NK_ASSERT_DEBUG(swapIndex >= 0); |
520 r = DoWriteSwapPages(&aMemory[j], &aIndex[j], 1, aLinAddr + (j << KPageShift), swapIndex, aBackground); |
598 r = DoWriteSwapPages(&aMemory[j], &aIndex[j], 1, aLinAddr, j, &aPhysAddrs[j], swapIndex, aBackground); |
521 if (r != KErrNone) |
599 if (r != KErrNone) |
522 break; |
600 break; |
523 } |
601 } |
524 } |
602 } |
525 |
603 |
531 END_PAGING_BENCHMARK_N(EPagingBmWriteDataPage, aCount); |
609 END_PAGING_BENCHMARK_N(EPagingBmWriteDataPage, aCount); |
532 |
610 |
533 return r; |
611 return r; |
534 } |
612 } |
535 |
613 |
536 TInt DSwapManager::DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aSwapIndex, TBool aBackground) |
614 TInt DSwapManager::DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aPageIndex, TPhysAddr* aPhysAddrs, TInt aSwapIndex, TBool aBackground) |
537 { |
615 { |
|
616 TRACE2(("DSwapManager::DoWriteSwapPages %d pages to %d", aCount, aSwapIndex)); |
538 |
617 |
539 const TUint readUnitShift = iDevice->iReadUnitShift; |
618 const TUint readUnitShift = iDevice->iReadUnitShift; |
540 const TUint writeSize = aCount << (KPageShift - readUnitShift); |
619 const TUint writeSize = aCount << (KPageShift - readUnitShift); |
541 const TUint writeOffset = aSwapIndex << (KPageShift - readUnitShift); |
620 const TUint writeOffset = aSwapIndex << (KPageShift - readUnitShift); |
542 |
621 |
543 TThreadMessage msg; |
622 TThreadMessage msg; |
544 START_PAGING_BENCHMARK; |
623 START_PAGING_BENCHMARK; |
545 TInt r = iDevice->Write(&msg, aLinAddr, writeOffset, writeSize, aBackground); |
624 TInt r; |
|
625 if (aLinAddr == 0) |
|
626 r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground); |
|
627 else |
|
628 r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground); |
|
629 |
546 if (r != KErrNone) |
630 if (r != KErrNone) |
547 { |
631 { |
548 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r)); |
632 __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r)); |
549 } |
633 } |
550 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory |
634 __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory |
641 NKern::FMSignal(&iSwapLock); |
725 NKern::FMSignal(&iSwapLock); |
642 return KErrNone; |
726 return KErrNone; |
643 } |
727 } |
644 |
728 |
645 |
729 |
|
730 TBool DDataPagedMemoryManager::PhysicalAccessSupported() |
|
731 { |
|
732 return (iDevice->iFlags & DPagingDevice::ESupportsPhysicalAccess) != 0; |
|
733 } |
|
734 |
|
735 |
|
736 TBool DDataPagedMemoryManager::UsePhysicalAccess() |
|
737 { |
|
738 return iUsePhysicalAccess; |
|
739 } |
|
740 |
|
741 |
|
742 void DDataPagedMemoryManager::SetUsePhysicalAccess(TBool aUsePhysicalAccess) |
|
743 { |
|
744 TRACE(("WDP: Use physical access set to %d", aUsePhysicalAccess)); |
|
745 NKern::ThreadEnterCS(); |
|
746 PageCleaningLock::Lock(); |
|
747 iUsePhysicalAccess = aUsePhysicalAccess; |
|
748 ThePager.SetCleanInSequence(!iUsePhysicalAccess && KPageColouringRestriction); |
|
749 PageCleaningLock::Unlock(); |
|
750 NKern::ThreadLeaveCS(); |
|
751 } |
|
752 |
|
753 |
|
754 TUint DDataPagedMemoryManager::PreferredWriteSize() |
|
755 { |
|
756 return MaxU(iDevice->iPreferredWriteShift, KMinPreferredWriteShift + KPageShift) - KPageShift; |
|
757 } |
|
758 |
|
759 |
|
760 TUint DDataPagedMemoryManager::PreferredSwapAlignment() |
|
761 { |
|
762 return MaxU(iDevice->iPreferredWriteShift, KPageShift) - KPageShift; |
|
763 } |
|
764 |
|
765 |
|
766 TInt DDataPagedMemoryManager::SetWriteSize(TUint aWriteShift) |
|
767 { |
|
768 TRACE(("WDP: Set write size to %d (%d KB)", aWriteShift, 4 << aWriteShift)); |
|
769 // Check value is sensible |
|
770 if (aWriteShift > 31) |
|
771 return KErrArgument; |
|
772 if (aWriteShift > KMaxPreferredWriteShift) |
|
773 { |
|
774 aWriteShift = KMaxPreferredWriteShift; |
|
775 TRACE(("WDP: Reduced write size to %d (%d KB)", |
|
776 aWriteShift, 4 << aWriteShift)); |
|
777 |
|
778 } |
|
779 NKern::ThreadEnterCS(); |
|
780 PageCleaningLock::Lock(); |
|
781 ThePager.SetPagesToClean(1 << aWriteShift); |
|
782 PageCleaningLock::Unlock(); |
|
783 NKern::ThreadLeaveCS(); |
|
784 return KErrNone; |
|
785 } |
|
786 |
646 |
787 |
647 TInt DDataPagedMemoryManager::InstallPagingDevice(DPagingDevice* aDevice) |
788 TInt DDataPagedMemoryManager::InstallPagingDevice(DPagingDevice* aDevice) |
648 { |
789 { |
649 TRACEB(("DDataPagedMemoryManager::InstallPagingDevice(0x%08x)",aDevice)); |
790 TRACEB(("DDataPagedMemoryManager::InstallPagingDevice(0x%08x)",aDevice)); |
650 |
791 |
671 return KErrAlreadyExists; |
812 return KErrAlreadyExists; |
672 } |
813 } |
673 |
814 |
674 // Now we can determine the size of the swap, create the swap manager. |
815 // Now we can determine the size of the swap, create the swap manager. |
675 iSwapManager = new DSwapManager; |
816 iSwapManager = new DSwapManager; |
676 __NK_ASSERT_ALWAYS(iSwapManager); |
817 if (!iSwapManager) |
677 |
818 return KErrNoMemory; |
678 TInt r = iSwapManager->Create(iDevice); |
819 |
|
820 // Create swap manager object |
|
821 TInt r = iSwapManager->Create(aDevice); |
679 if (r != KErrNone) |
822 if (r != KErrNone) |
680 {// Couldn't create the swap manager. |
823 {// Couldn't create the swap manager. |
681 delete iSwapManager; |
824 delete iSwapManager; |
682 iSwapManager = NULL; |
825 iSwapManager = NULL; |
683 NKern::SafeSwap(NULL, (TAny*&)iDevice); |
826 NKern::SafeSwap(NULL, (TAny*&)iDevice); |
684 return r; |
827 return r; |
685 } |
828 } |
|
829 |
|
830 // Enable physical access where supported |
|
831 SetUsePhysicalAccess(PhysicalAccessSupported()); |
|
832 |
|
833 // Determine swap alignment and number of pages to clean at once from device's preferred write |
|
834 // size, if set |
|
835 TRACE(("WDP: Preferred write shift is %d", iDevice->iPreferredWriteShift)); |
|
836 r = SetWriteSize(PreferredWriteSize()); |
|
837 if (r != KErrNone) |
|
838 { |
|
839 delete iSwapManager; |
|
840 iSwapManager = NULL; |
|
841 NKern::SafeSwap(NULL, (TAny*&)iDevice); |
|
842 return r; |
|
843 } |
|
844 |
|
845 // Set swap alignment |
|
846 iSwapManager->SetSwapAlign(PreferredSwapAlignment()); |
|
847 |
686 NKern::LockedSetClear(K::MemModelAttributes, 0, EMemModelAttrDataPaging); |
848 NKern::LockedSetClear(K::MemModelAttributes, 0, EMemModelAttrDataPaging); |
687 |
849 |
688 return r; |
850 return r; |
689 } |
851 } |
690 |
852 |
753 |
915 |
754 TInt DDataPagedMemoryManager::ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest) |
916 TInt DDataPagedMemoryManager::ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest) |
755 { |
917 { |
756 __NK_ASSERT_DEBUG(aRequest->CheckUseContiguous(aMemory,aIndex,aCount)); |
918 __NK_ASSERT_DEBUG(aRequest->CheckUseContiguous(aMemory,aIndex,aCount)); |
757 |
919 |
|
920 // todo: Possible to read using physical addresses here, but not sure it's worth it because it's |
|
921 // not much saving and we may need to map the page anyway if it's blank to clear it |
|
922 // |
|
923 // todo: Could move clearing pages up to here maybe? |
|
924 |
758 // Map pages temporarily so that we can copy into them. |
925 // Map pages temporarily so that we can copy into them. |
759 const TLinAddr linAddr = aRequest->MapPages(aIndex, aCount, aPages); |
926 const TLinAddr linAddr = aRequest->MapPages(aIndex, aCount, aPages); |
760 |
927 |
761 TInt r = iSwapManager->ReadSwapPages(aMemory, aIndex, aCount, linAddr, aRequest, aPages); |
928 TInt r = iSwapManager->ReadSwapPages(aMemory, aIndex, aCount, linAddr, aPages); |
762 |
929 |
763 // The memory object allows executable mappings then need IMB. |
930 // The memory object allows executable mappings then need IMB. |
764 aRequest->UnmapPages(aMemory->IsExecutable()); |
931 aRequest->UnmapPages(aMemory->IsExecutable()); |
765 |
932 |
766 return r; |
933 return r; |
767 } |
934 } |
768 |
935 |
769 |
936 |
770 TInt DDataPagedMemoryManager::WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest* aRequest, TBool aAnyExecutable, TBool aBackground) |
937 TInt DDataPagedMemoryManager::WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest* aRequest, TBool aAnyExecutable, TBool aBackground) |
771 { |
938 { |
772 // Map pages temporarily so that we can copy into them. |
939 // Note: this method used to do an IMB for executable pages (like ReadPages) but it was thought |
773 const TLinAddr linAddr = aRequest->MapPages(aIndex[0], aCount, aPages); |
940 // that this was uncessessary and so was removed |
774 |
941 |
775 TInt r = iSwapManager->WriteSwapPages(aMemory, aIndex, aCount, linAddr, aBackground); |
942 TLinAddr linAddr = 0; |
776 |
943 |
777 // The memory object allows executable mappings then need IMB. |
944 if (iUsePhysicalAccess) |
778 aRequest->UnmapPages(aAnyExecutable); |
945 { |
|
946 // must maps pages to perform cache maintenance but can map each page individually |
|
947 for (TUint i = 0 ; i < aCount ; ++i) |
|
948 { |
|
949 TLinAddr addr = aRequest->MapPages(aIndex[i], 1, &aPages[i]); |
|
950 Cache::SyncMemoryBeforeDmaWrite(addr, KPageSize); |
|
951 aRequest->UnmapPages(EFalse); |
|
952 } |
|
953 } |
|
954 else |
|
955 linAddr = aRequest->MapPages(aIndex[0], aCount, aPages); |
|
956 |
|
957 TInt r = iSwapManager->WriteSwapPages(aMemory, aIndex, aCount, linAddr, aPages, aBackground); |
|
958 |
|
959 if (linAddr != 0) |
|
960 aRequest->UnmapPages(EFalse); |
779 |
961 |
780 return r; |
962 return r; |
781 } |
963 } |
782 |
964 |
783 |
965 |
784 void DDataPagedMemoryManager::CleanPages(TUint aPageCount, SPageInfo** aPageInfos, TBool aBackground) |
966 void DDataPagedMemoryManager::CleanPages(TUint aPageCount, SPageInfo** aPageInfos, TBool aBackground) |
785 { |
967 { |
|
968 TRACE(("DDataPagedMemoryManager::CleanPages %d", aPageCount)); |
|
969 |
786 __NK_ASSERT_DEBUG(PageCleaningLock::IsHeld()); |
970 __NK_ASSERT_DEBUG(PageCleaningLock::IsHeld()); |
787 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
971 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
788 __NK_ASSERT_DEBUG(aPageCount <= (TUint)KMaxPagesToClean); |
972 __NK_ASSERT_DEBUG(aPageCount <= (TUint)KMaxPagesToClean); |
789 |
973 |
790 TUint i; |
974 TUint i; |
791 DMemoryObject* memory[KMaxPagesToClean]; |
975 DMemoryObject* memory[KMaxPagesToClean]; |
792 TUint index[KMaxPagesToClean]; |
976 TUint index[KMaxPagesToClean]; |
793 TPhysAddr physAddr[KMaxPagesToClean]; |
977 TPhysAddr physAddr[KMaxPagesToClean]; |
794 TBool anyExecutable = EFalse; |
978 TBool anyExecutable = EFalse; |
795 |
979 |
796 for (i = 0 ; i < aPageCount ; ++i) |
980 for (i = 0 ; i < aPageCount ; ++i) |
797 { |
981 { |
798 SPageInfo* pi = aPageInfos[i]; |
982 SPageInfo* pi = aPageInfos[i]; |
799 |
983 |
800 __NK_ASSERT_DEBUG(!pi->IsWritable()); |
984 __NK_ASSERT_DEBUG(!pi->IsWritable()); |