332 /** |
335 /** |
333 Attempt to discard the specified page. |
336 Attempt to discard the specified page. |
334 |
337 |
335 @param aOldPageInfo The page info of the page to discard. |
338 @param aOldPageInfo The page info of the page to discard. |
336 @param aBlockZoneId The ID of the RAM zone not to allocate any required new page into. |
339 @param aBlockZoneId The ID of the RAM zone not to allocate any required new page into. |
337 @param aBlockRest Set to ETrue when we don't want the allocator to search for new pages if the RAM |
340 @param aMoveDisFlags Flags that control the discarding of the page, should be a mask of |
338 zone with ID==aBlockZoneId is encountered, i.e. a general RAM defrag operation. |
341 values from M::TMoveDiscardFlags |
339 */ |
342 */ |
340 TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TBool aBlockRest); |
343 TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TUint aMoveDisFlags); |
341 |
344 |
342 /** |
345 /** |
343 Attempt to discard the specified page and then allocate a page of type aPageType |
346 Attempt to discard the specified page and then allocate a page of type aPageType |
344 in its place. |
347 in its place. |
|
348 |
|
349 Note - This will always attempt to move dirty pages rather than write them to swap. |
345 |
350 |
346 @param aPageInfo The page info of the page to discard. |
351 @param aPageInfo The page info of the page to discard. |
347 @param aPageType The new page type to allocate into aPageInfo's physical address. |
352 @param aPageType The new page type to allocate into aPageInfo's physical address. |
348 */ |
353 */ |
349 TInt DiscardAndAllocPage(SPageInfo* aPageInfo, TZonePageType aPageType); |
354 TInt DiscardAndAllocPage(SPageInfo* aPageInfo, TZonePageType aPageType); |
397 @post MmuLock left unchanged. |
430 @post MmuLock left unchanged. |
398 */ |
431 */ |
399 void RemovePage(SPageInfo* aPageInfo); |
432 void RemovePage(SPageInfo* aPageInfo); |
400 |
433 |
401 /** |
434 /** |
402 Try to remove the oldest page from the live page list and perform #StealPage. |
435 Attempt to steal the oldest page on the live list. |
403 |
436 |
|
437 If the oldest page is an oldest dirty page, this attempts to clean multiple pages by calling |
|
438 #CleanSomePages and then returns without stealing any page. This allows the caller to restart |
|
439 their operation after the lengthy cleaning process, which may no longer need to call this |
|
440 function. |
|
441 |
|
442 If the oldest page is on any other list (i.e. is an old or young page) this will steal it, |
|
443 aquiring the page cleaning mutex first if it is dirty. |
|
444 |
|
445 Called from #PageInAllocPage. |
|
446 |
404 @param aPageInfoOut Set to the SPageInfo pointer for the stolen page if any. |
447 @param aPageInfoOut Set to the SPageInfo pointer for the stolen page if any. |
405 |
448 |
406 @return KErrNone on success, KErrInUse if stealing failed or 1 to indicate the the oldest page |
449 @return KErrNone on success, KErrInUse if stealing failed or 1 to indicate the the oldest page |
407 was dirty and the PageCleaning mutex was not held. |
450 was dirty and the PageCleaning mutex was not held. |
408 |
451 |
409 @pre MmuLock held |
452 @pre MmuLock held |
410 @post MmuLock left unchanged. |
453 @post MmuLock left unchanged. |
411 */ |
454 */ |
412 TInt TryStealOldestPage(SPageInfo*& aPageInfoOut); |
455 TInt TryStealOldestPage(SPageInfo*& aPageInfoOut); |
413 |
|
414 /** |
|
415 Remove the oldest page from the live page list and perform #StealPage. |
|
416 |
|
417 @pre MmuLock held |
|
418 @post MmuLock held (but may have been released by this function) |
|
419 */ |
|
420 SPageInfo* StealOldestPage(); |
|
421 |
456 |
422 /** |
457 /** |
423 Steal a page from the memory object (if any) which is using the page. |
458 Steal a page from the memory object (if any) which is using the page. |
424 If successful the returned page will be in the EUnknown state and the |
459 If successful the returned page will be in the EUnknown state and the |
425 cache state for the page is indeterminate. This is the same state as |
460 cache state for the page is indeterminate. This is the same state as |
482 3. The oldest page from the live page list. |
517 3. The oldest page from the live page list. |
483 */ |
518 */ |
484 SPageInfo* PageInAllocPage(Mmu::TRamAllocFlags aAllocFlags); |
519 SPageInfo* PageInAllocPage(Mmu::TRamAllocFlags aAllocFlags); |
485 |
520 |
486 /** |
521 /** |
487 Called by CleanSomePages() to determine which pages should be cleaned. |
522 Called by CleanSomePages() to select the pages be cleaned. |
488 |
523 |
489 This deals with the complexity of page colouring, which means that pages can only be mapped at |
524 This function finds a set of pages that can be mapped sequentially in memory when page colouring |
490 certain locations. When cleaning multiple pages at once we need to find a set of pages that we |
525 restrictions are in effect. It is only called on systems with page colouring restrictions where |
491 can map in memory sequentially. |
526 the paging media driver does not support writing by phyiscal address. |
492 |
527 |
493 @pre MmuLock held |
528 @pre MmuLock held |
494 |
529 |
495 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
530 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
496 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
531 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
497 |
532 |
498 @return The numnber of pages to clean. |
533 @return The numnber of pages to clean. |
499 */ |
534 */ |
500 TInt SelectPagesToClean(SPageInfo** aPageInfosOut); |
535 TInt SelectSequentialPagesToClean(SPageInfo** aPageInfosOut); |
|
536 |
|
537 /** |
|
538 Called by CleanSomePages() to select the pages be cleaned. |
|
539 |
|
540 This funciton selects the oldest dirty pages. It is called on systems without page colouring |
|
541 restrictions or where the paging media driver supports writing by phyiscal address. |
|
542 |
|
543 @pre MmuLock held |
|
544 |
|
545 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
|
546 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
|
547 |
|
548 @return The numnber of pages to clean. |
|
549 */ |
|
550 TInt SelectOldestPagesToClean(SPageInfo** aPageInfosOut); |
501 |
551 |
502 /** |
552 /** |
503 If the number of young pages exceeds that specified by iYoungOldRatio then a |
553 If the number of young pages exceeds that specified by iYoungOldRatio then a |
504 single page is made 'old'. Call this after adding a new 'young' page. |
554 single page is made 'old'. Call this after adding a new 'young' page. |
505 |
555 |
596 SDblQue iOldestCleanList; /**< Head of 'oldestClean' page list. */ |
647 SDblQue iOldestCleanList; /**< Head of 'oldestClean' page list. */ |
597 TUint iOldestCleanCount; /**< Number of 'oldestClean' pages */ |
648 TUint iOldestCleanCount; /**< Number of 'oldestClean' pages */ |
598 SDblQue iOldestDirtyList; /**< Head of 'oldestDirty' page list. */ |
649 SDblQue iOldestDirtyList; /**< Head of 'oldestDirty' page list. */ |
599 TUint iOldestDirtyCount; /**< Number of 'oldestDirty' pages */ |
650 TUint iOldestDirtyCount; /**< Number of 'oldestDirty' pages */ |
600 TUint16 iOldOldestRatio; /**< Ratio of old pages to oldest to clean and dirty in the live page list*/ |
651 TUint16 iOldOldestRatio; /**< Ratio of old pages to oldest to clean and dirty in the live page list*/ |
|
652 TUint iMaxOldestPages; /**< Maximum number of oldest pages. */ |
601 TUint iNumberOfFreePages; |
653 TUint iNumberOfFreePages; |
602 TUint iNumberOfDirtyPages; /**< The total number of dirty pages in the paging cache. Protected by MmuLock */ |
654 TUint iNumberOfDirtyPages; /**< The total number of dirty pages in the paging cache. Protected by MmuLock */ |
603 TUint iInitMinimumPageCount;/**< Initial value for iMinimumPageCount */ |
655 TUint iInitMinimumPageCount;/**< Initial value for iMinimumPageCount */ |
604 TUint iInitMaximumPageCount;/**< Initial value for iMaximumPageCount */ |
656 TUint iInitMaximumPageCount;/**< Initial value for iMaximumPageCount */ |
605 TUint iReservePageCount; /**< Number of pages reserved for locking */ |
657 TUint iReservePageCount; /**< Number of pages reserved for locking */ |
606 TUint iMinimumPageLimit; /**< Minimum size for iMinimumPageCount, not including locked pages. |
658 TUint iMinimumPageLimit; /**< Minimum size for iMinimumPageCount, not including locked pages. |
607 iMinimumPageCount >= iMinimumPageLimit + iReservePageCount */ |
659 iMinimumPageCount >= iMinimumPageLimit + iReservePageCount */ |
|
660 TUint iPagesToClean; /**< Preferred number of pages to attempt to clean in one go. */ |
|
661 TBool iCleanInSequence; /**< Pages to be cleaned must have sequential page colour. */ |
|
662 |
608 SVMEventInfo iEventInfo; |
663 SVMEventInfo iEventInfo; |
609 |
664 |
610 #ifdef __DEMAND_PAGING_BENCHMARKS__ |
665 #ifdef __DEMAND_PAGING_BENCHMARKS__ |
611 public: |
666 public: |
612 void RecordBenchmarkData(TPagingBenchmark aBm, TUint32 aStartTime, TUint32 aEndTime, TUint aCount); |
667 void RecordBenchmarkData(TPagingBenchmark aBm, TUint32 aStartTime, TUint32 aEndTime, TUint aCount); |
790 private: |
844 private: |
791 class TGroup |
845 class TGroup |
792 { |
846 { |
793 public: |
847 public: |
794 TGroup(TUint aNumRequests); |
848 TGroup(TUint aNumRequests); |
795 DPoolPagingRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
849 DPageReadRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
796 DPoolPagingRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
850 DPageReadRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
797 void Signal(DPoolPagingRequest* aRequest); |
|
798 public: |
851 public: |
799 TUint iNumRequests; |
852 TUint iNumRequests; |
800 DPoolPagingRequest** iRequests; |
853 DPageReadRequest** iRequests; |
801 SDblQue iFreeList; |
854 SDblQue iFreeList; |
802 }; |
855 }; |
803 TGroup iPageReadRequests; |
856 TGroup iPageReadRequests; |
804 DPageWriteRequest* iPageWriteRequest; |
857 DPageWriteRequest* iPageWriteRequest; |
805 |
858 |
806 friend class DPoolPagingRequest; |
|
807 friend class DPageReadRequest; |
859 friend class DPageReadRequest; |
808 friend class DPageWriteRequest; |
|
809 }; |
860 }; |
810 |
861 |
811 |
862 |
812 /** |
863 /** |
813 Resources needed to service a paging request. |
864 Common resources needed to service a paging request. |
814 */ |
865 */ |
815 class DPagingRequest : public SDblQueLink |
866 class DPagingRequestBase : public DBase |
|
867 { |
|
868 public: |
|
869 TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages); |
|
870 void UnmapPages(TBool aIMBRequired); |
|
871 public: // for DPagingRequestPool |
|
872 DMutex* iMutex; /**< A mutex for synchronisation and priority inheritance. */ |
|
873 protected: |
|
874 Mmu::TTempMapping iTempMapping; |
|
875 }; |
|
876 |
|
877 |
|
878 /** |
|
879 Resources needed to service a page in request. |
|
880 */ |
|
881 class DPageReadRequest : public DPagingRequestBase |
|
882 { |
|
883 public: |
|
884 static TUint ReservedPagesRequired(); |
|
885 private: |
|
886 static TInt iAllocNext; |
|
887 |
|
888 public: |
|
889 enum |
|
890 { |
|
891 EMaxPages = 4 |
|
892 }; |
|
893 DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
894 TInt Construct(); |
|
895 void Release(); |
|
896 void Wait(); |
|
897 void Signal(); |
|
898 void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
899 void ResetUse(); |
|
900 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
901 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
902 TLinAddr Buffer() { return iBuffer; } |
|
903 TUint ThreadsWaiting() { return iUsageCount; } |
|
904 private: |
|
905 ~DPageReadRequest() { } // can't delete |
|
906 public: // for DPagingRequestPool |
|
907 SDblQueLink iLink; /**< Link into list of free requests. */ |
|
908 private: |
|
909 TInt iUsageCount; /**< How many threads are using or waiting for this object. */ |
|
910 TLinAddr iBuffer; /**< A buffer of size EMaxPages+1 pages to read compressed data into. */ |
|
911 DPagingRequestPool::TGroup& iPoolGroup; |
|
912 DMemoryObject* iMemory; |
|
913 TUint iIndex; |
|
914 TUint iCount; |
|
915 }; |
|
916 |
|
917 |
|
918 /** |
|
919 Resources needed to service a page out request. |
|
920 */ |
|
921 class DPageWriteRequest : public DPagingRequestBase |
816 { |
922 { |
817 public: |
923 public: |
818 enum |
924 enum |
819 { |
925 { |
820 EMaxPages = 4 |
926 EMaxPages = KMaxPagesToClean |
821 }; |
927 }; |
822 DPagingRequest(); |
928 DPageWriteRequest(); |
823 TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages); |
929 void Release(); |
824 void UnmapPages(TBool aIMBRequired); |
|
825 void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
826 void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
930 void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
827 void ResetUse(); |
931 void ResetUse(); |
828 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
932 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
829 TBool CheckUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
|
830 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
933 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
831 public: |
|
832 DMutex* iMutex; /**< A mutex for synchronisation and priority inheritance. */ |
|
833 protected: |
|
834 Mmu::TTempMapping iTempMapping; |
|
835 private: |
934 private: |
836 // used to identify memory request is used for... |
935 ~DPageWriteRequest() { } // can't delete |
|
936 private: |
|
937 // used to identify the memory the request is used for... |
837 TUint iUseRegionCount; |
938 TUint iUseRegionCount; |
838 DMemoryObject* iUseRegionMemory[EMaxPages]; |
939 DMemoryObject* iUseRegionMemory[EMaxPages]; |
839 TUint iUseRegionIndex[EMaxPages]; |
940 TUint iUseRegionIndex[EMaxPages]; |
840 }; |
|
841 |
|
842 |
|
843 __ASSERT_COMPILE(DPagingRequest::EMaxPages >= KMaxPagesToClean); |
|
844 |
|
845 |
|
846 /** |
|
847 A paging request that is part of a pool of similar request objects. |
|
848 */ |
|
849 class DPoolPagingRequest : public DPagingRequest |
|
850 { |
|
851 public: |
|
852 DPoolPagingRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
853 void Release(); |
|
854 void Wait(); |
|
855 void Signal(); |
|
856 public: |
|
857 TInt iUsageCount; /**< How many threads are using or waiting for this object. */ |
|
858 private: |
|
859 DPagingRequestPool::TGroup& iPoolGroup; |
|
860 }; |
|
861 |
|
862 |
|
863 /** |
|
864 Resources needed to service a page in request. |
|
865 */ |
|
866 class DPageReadRequest : public DPoolPagingRequest |
|
867 { |
|
868 public: |
|
869 DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
870 TInt Construct(); |
|
871 static TUint ReservedPagesRequired(); |
|
872 private: |
|
873 ~DPageReadRequest(); // can't delete |
|
874 public: |
|
875 TLinAddr iBuffer; /**< A buffer to read compressed data into. Size is EMaxPages+1 pages.*/ |
|
876 private: |
|
877 DMemoryObject* iMemory; |
|
878 private: |
|
879 static TInt iAllocNext; |
|
880 }; |
|
881 |
|
882 |
|
883 FORCE_INLINE TUint DPageReadRequest::ReservedPagesRequired() |
|
884 { |
|
885 return iAllocNext*EMaxPages; |
|
886 } |
|
887 |
|
888 |
|
889 /** |
|
890 Resources needed to service a page out request. |
|
891 */ |
|
892 class DPageWriteRequest : public DPagingRequest |
|
893 { |
|
894 public: |
|
895 DPageWriteRequest(); |
|
896 void Release(); |
|
897 private: |
|
898 ~DPageWriteRequest(); // can't delete |
|
899 }; |
941 }; |
900 |
942 |
901 |
943 |
902 /** |
944 /** |
903 Class providing access to the mutex used to protect page cleaning operations; |
945 Class providing access to the mutex used to protect page cleaning operations; |