346 /** |
349 /** |
347 Attempt to discard the specified page. |
350 Attempt to discard the specified page. |
348 |
351 |
349 @param aOldPageInfo The page info of the page to discard. |
352 @param aOldPageInfo The page info of the page to discard. |
350 @param aBlockZoneId The ID of the RAM zone not to allocate any required new page into. |
353 @param aBlockZoneId The ID of the RAM zone not to allocate any required new page into. |
351 @param aBlockRest Set to ETrue when we don't want the allocator to search for new pages if the RAM |
354 @param aMoveDisFlags Flags that control the discarding of the page, should be a mask of |
352 zone with ID==aBlockZoneId is encountered, i.e. a general RAM defrag operation. |
355 values from M::TMoveDiscardFlags |
353 */ |
356 */ |
354 TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TBool aBlockRest); |
357 TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TUint aMoveDisFlags); |
355 |
358 |
356 /** |
359 /** |
357 Attempt to discard the specified page and then allocate a page of type aPageType |
360 Attempt to discard the specified page and then allocate a page of type aPageType |
358 in its place. |
361 in its place. |
|
362 |
|
363 Note - This will always attempt to move dirty pages rather than write them to swap. |
359 |
364 |
360 @param aPageInfo The page info of the page to discard. |
365 @param aPageInfo The page info of the page to discard. |
361 @param aPageType The new page type to allocate into aPageInfo's physical address. |
366 @param aPageType The new page type to allocate into aPageInfo's physical address. |
362 */ |
367 */ |
363 TInt DiscardAndAllocPage(SPageInfo* aPageInfo, TZonePageType aPageType); |
368 TInt DiscardAndAllocPage(SPageInfo* aPageInfo, TZonePageType aPageType); |
411 @post MmuLock left unchanged. |
444 @post MmuLock left unchanged. |
412 */ |
445 */ |
413 void RemovePage(SPageInfo* aPageInfo); |
446 void RemovePage(SPageInfo* aPageInfo); |
414 |
447 |
415 /** |
448 /** |
416 Try to remove the oldest page from the live page list and perform #StealPage. |
449 Get a page, either by stealing one from the live list or allocating one from the system. |
417 |
450 |
418 @param aPageInfoOut Set to the SPageInfo pointer for the stolen page if any. |
451 |
|
452 |
|
453 If the oldest page is an oldest dirty page, this may attempt to clean multiple pages by calling |
|
454 #CleanSomePages. |
|
455 |
|
456 If the oldest page is on any other list (i.e. is an old or young page) this will steal it, |
|
457 aquiring the page cleaning mutex first if it is dirty. |
|
458 |
|
459 Called from #PageInAllocPage, #TryReturnOldestPageToSystem, #AllowAddFreePage and |
|
460 #AllowAddFreePages. |
|
461 |
|
462 @param aAllowAlloc Indicates whether the method should try to allocate a page from the system |
419 |
463 |
420 @return KErrNone on success, KErrInUse if stealing failed or 1 to indicate the the oldest page |
464 @return KErrNone on success, KErrInUse if stealing failed or 1 to indicate the the oldest page |
421 was dirty and the PageCleaning mutex was not held. |
465 was dirty and the PageCleaning mutex was not held. |
422 |
466 |
423 @pre MmuLock held |
467 @pre MmuLock held |
424 @post MmuLock left unchanged. |
468 @post MmuLock left unchanged. |
425 */ |
469 */ |
426 TInt TryStealOldestPage(SPageInfo*& aPageInfoOut); |
470 SPageInfo* StealOrAllocPage(TBool aAllowAlloc, Mmu::TRamAllocFlags aAllocFlags); |
427 |
|
428 /** |
|
429 Remove the oldest page from the live page list and perform #StealPage. |
|
430 |
|
431 @pre MmuLock held |
|
432 @post MmuLock held (but may have been released by this function) |
|
433 */ |
|
434 SPageInfo* StealOldestPage(); |
|
435 |
471 |
436 /** |
472 /** |
437 Steal a page from the memory object (if any) which is using the page. |
473 Steal a page from the memory object (if any) which is using the page. |
438 If successful the returned page will be in the EUnknown state and the |
474 If successful the returned page will be in the EUnknown state and the |
439 cache state for the page is indeterminate. This is the same state as |
475 cache state for the page is indeterminate. This is the same state as |
477 /** |
513 /** |
478 Put a page back on the system's free pool. |
514 Put a page back on the system's free pool. |
479 |
515 |
480 @pre RamAllocLock held. |
516 @pre RamAllocLock held. |
481 */ |
517 */ |
482 void ReturnPageToSystem(); |
518 TBool TryReturnOldestPageToSystem(); |
483 |
519 |
|
520 /** |
|
521 Ensure adding a page to the paging cache will be within the maximum size. |
|
522 |
|
523 @param aPageInfo On return this is set to the SPageInfo of a page that must be returned |
|
524 to the system before a page can be added to the paging cache, or |
|
525 NULL if no page must be returned to the system. |
|
526 */ |
|
527 void AllowAddFreePage(SPageInfo*& aPageInfo); |
|
528 |
|
529 /** |
|
530 Ensure adding aNumPages pages to the paging cache will be within the maximum size. |
|
531 |
|
532 @param aPageInfo On return this is set to the SPageInfo of a page that must be returned |
|
533 to the system before any more pages can be added to the paging cache, or |
|
534 NULL if no page must be returned to the system. |
|
535 @param aNumPages The number of pages the caller wishes to add to the paging cache. |
|
536 |
|
537 @return If aPageInfo == NULL on return, this is the number of pages it is possible to |
|
538 add to the paging cache or 1 if aPageInfo != NULL, i.e. a page will need |
|
539 to be returned to the system. |
|
540 */ |
|
541 TUint AllowAddFreePages(SPageInfo*& aPageInfo, TUint aNumPages); |
|
542 |
484 /** |
543 /** |
485 Put a specific page back on the system's free pool. |
544 Put a specific page back on the system's free pool. |
486 |
545 |
487 @pre RamAllocLock held. |
546 @pre RamAllocLock held. |
488 */ |
547 */ |
496 3. The oldest page from the live page list. |
555 3. The oldest page from the live page list. |
497 */ |
556 */ |
498 SPageInfo* PageInAllocPage(Mmu::TRamAllocFlags aAllocFlags); |
557 SPageInfo* PageInAllocPage(Mmu::TRamAllocFlags aAllocFlags); |
499 |
558 |
500 /** |
559 /** |
501 Called by CleanSomePages() to determine which pages should be cleaned. |
560 Called by CleanSomePages() to select the pages be cleaned. |
502 |
561 |
503 This deals with the complexity of page colouring, which means that pages can only be mapped at |
562 This function finds a set of pages that can be mapped sequentially in memory when page colouring |
504 certain locations. When cleaning multiple pages at once we need to find a set of pages that we |
563 restrictions are in effect. It is only called on systems with page colouring restrictions where |
505 can map in memory sequentially. |
564 the paging media driver does not support writing by phyiscal address. |
506 |
565 |
507 @pre MmuLock held |
566 @pre MmuLock held |
508 |
567 |
509 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
568 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
510 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
569 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
511 |
570 |
512 @return The numnber of pages to clean. |
571 @return The numnber of pages to clean. |
513 */ |
572 */ |
514 TInt SelectPagesToClean(SPageInfo** aPageInfosOut); |
573 TInt SelectSequentialPagesToClean(SPageInfo** aPageInfosOut); |
|
574 |
|
575 /** |
|
576 Called by CleanSomePages() to select the pages be cleaned. |
|
577 |
|
578 This funciton selects the oldest dirty pages. It is called on systems without page colouring |
|
579 restrictions or where the paging media driver supports writing by phyiscal address. |
|
580 |
|
581 @pre MmuLock held |
|
582 |
|
583 @param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least |
|
584 KMaxPagesToClean long. This will be filled in to indicate the pages to clean. |
|
585 |
|
586 @return The numnber of pages to clean. |
|
587 */ |
|
588 TInt SelectOldestPagesToClean(SPageInfo** aPageInfosOut); |
515 |
589 |
516 /** |
590 /** |
517 If the number of young pages exceeds that specified by iYoungOldRatio then a |
591 If the number of young pages exceeds that specified by iYoungOldRatio then a |
518 single page is made 'old'. Call this after adding a new 'young' page. |
592 single page is made 'old'. Call this after adding a new 'young' page. |
519 |
593 |
610 SDblQue iOldestCleanList; /**< Head of 'oldestClean' page list. */ |
685 SDblQue iOldestCleanList; /**< Head of 'oldestClean' page list. */ |
611 TUint iOldestCleanCount; /**< Number of 'oldestClean' pages */ |
686 TUint iOldestCleanCount; /**< Number of 'oldestClean' pages */ |
612 SDblQue iOldestDirtyList; /**< Head of 'oldestDirty' page list. */ |
687 SDblQue iOldestDirtyList; /**< Head of 'oldestDirty' page list. */ |
613 TUint iOldestDirtyCount; /**< Number of 'oldestDirty' pages */ |
688 TUint iOldestDirtyCount; /**< Number of 'oldestDirty' pages */ |
614 TUint16 iOldOldestRatio; /**< Ratio of old pages to oldest to clean and dirty in the live page list*/ |
689 TUint16 iOldOldestRatio; /**< Ratio of old pages to oldest to clean and dirty in the live page list*/ |
|
690 TUint iMaxOldestPages; /**< Maximum number of oldest pages. */ |
615 TUint iNumberOfFreePages; |
691 TUint iNumberOfFreePages; |
616 TUint iNumberOfDirtyPages; /**< The total number of dirty pages in the paging cache. Protected by MmuLock */ |
692 TUint iNumberOfDirtyPages; /**< The total number of dirty pages in the paging cache. Protected by MmuLock */ |
617 TUint iInitMinimumPageCount;/**< Initial value for iMinimumPageCount */ |
693 TUint iInitMinimumPageCount;/**< Initial value for iMinimumPageCount */ |
618 TUint iInitMaximumPageCount;/**< Initial value for iMaximumPageCount */ |
694 TUint iInitMaximumPageCount;/**< Initial value for iMaximumPageCount */ |
619 TUint iReservePageCount; /**< Number of pages reserved for locking */ |
695 TUint iReservePageCount; /**< Number of pages reserved for locking */ |
620 TUint iMinimumPageLimit; /**< Minimum size for iMinimumPageCount, not including locked pages. |
696 TUint iMinimumPageLimit; /**< Minimum size for iMinimumPageCount, not including locked pages. |
621 iMinimumPageCount >= iMinimumPageLimit + iReservePageCount */ |
697 iMinimumPageCount >= iMinimumPageLimit + iReservePageCount */ |
|
698 TUint iPagesToClean; /**< Preferred number of pages to attempt to clean in one go. */ |
|
699 TBool iCleanInSequence; /**< Pages to be cleaned must have sequential page colour. */ |
|
700 |
622 SVMEventInfo iEventInfo; |
701 SVMEventInfo iEventInfo; |
623 |
702 |
624 #ifdef __DEMAND_PAGING_BENCHMARKS__ |
703 #ifdef __DEMAND_PAGING_BENCHMARKS__ |
625 public: |
704 public: |
626 void RecordBenchmarkData(TPagingBenchmark aBm, TUint32 aStartTime, TUint32 aEndTime, TUint aCount); |
705 void RecordBenchmarkData(TPagingBenchmark aBm, TUint32 aStartTime, TUint32 aEndTime, TUint aCount); |
804 private: |
882 private: |
805 class TGroup |
883 class TGroup |
806 { |
884 { |
807 public: |
885 public: |
808 TGroup(TUint aNumRequests); |
886 TGroup(TUint aNumRequests); |
809 DPoolPagingRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
887 DPageReadRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
810 DPoolPagingRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
888 DPageReadRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
811 void Signal(DPoolPagingRequest* aRequest); |
|
812 public: |
889 public: |
813 TUint iNumRequests; |
890 TUint iNumRequests; |
814 DPoolPagingRequest** iRequests; |
891 DPageReadRequest** iRequests; |
815 SDblQue iFreeList; |
892 SDblQue iFreeList; |
816 }; |
893 }; |
817 TGroup iPageReadRequests; |
894 TGroup iPageReadRequests; |
818 DPageWriteRequest* iPageWriteRequest; |
895 DPageWriteRequest* iPageWriteRequest; |
819 |
896 |
820 friend class DPoolPagingRequest; |
|
821 friend class DPageReadRequest; |
897 friend class DPageReadRequest; |
822 friend class DPageWriteRequest; |
|
823 }; |
898 }; |
824 |
899 |
825 |
900 |
826 /** |
901 /** |
827 Resources needed to service a paging request. |
902 Common resources needed to service a paging request. |
828 */ |
903 */ |
829 class DPagingRequest : public SDblQueLink |
904 class DPagingRequestBase : public DBase |
|
905 { |
|
906 public: |
|
907 TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages); |
|
908 void UnmapPages(TBool aIMBRequired); |
|
909 public: // for DPagingRequestPool |
|
910 DMutex* iMutex; /**< A mutex for synchronisation and priority inheritance. */ |
|
911 protected: |
|
912 Mmu::TTempMapping iTempMapping; |
|
913 }; |
|
914 |
|
915 |
|
916 /** |
|
917 Resources needed to service a page in request. |
|
918 */ |
|
919 class DPageReadRequest : public DPagingRequestBase |
|
920 { |
|
921 public: |
|
922 static TUint ReservedPagesRequired(); |
|
923 private: |
|
924 static TInt iAllocNext; |
|
925 |
|
926 public: |
|
927 enum |
|
928 { |
|
929 EMaxPages = 4 |
|
930 }; |
|
931 DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
932 TInt Construct(); |
|
933 void Release(); |
|
934 void Wait(); |
|
935 void Signal(); |
|
936 void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
937 void ResetUse(); |
|
938 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
939 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
940 TLinAddr Buffer() { return iBuffer; } |
|
941 TUint ThreadsWaiting() { return iUsageCount; } |
|
942 private: |
|
943 ~DPageReadRequest() { } // can't delete |
|
944 public: // for DPagingRequestPool |
|
945 SDblQueLink iLink; /**< Link into list of free requests. */ |
|
946 private: |
|
947 TInt iUsageCount; /**< How many threads are using or waiting for this object. */ |
|
948 TLinAddr iBuffer; /**< A buffer of size EMaxPages+1 pages to read compressed data into. */ |
|
949 DPagingRequestPool::TGroup& iPoolGroup; |
|
950 DMemoryObject* iMemory; |
|
951 TUint iIndex; |
|
952 TUint iCount; |
|
953 }; |
|
954 |
|
955 |
|
956 /** |
|
957 Resources needed to service a page out request. |
|
958 */ |
|
959 class DPageWriteRequest : public DPagingRequestBase |
830 { |
960 { |
831 public: |
961 public: |
832 enum |
962 enum |
833 { |
963 { |
834 EMaxPages = 4 |
964 EMaxPages = KMaxPagesToClean |
835 }; |
965 }; |
836 DPagingRequest(); |
966 DPageWriteRequest(); |
837 TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages); |
967 void Release(); |
838 void UnmapPages(TBool aIMBRequired); |
|
839 void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
|
840 void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
968 void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
841 void ResetUse(); |
969 void ResetUse(); |
842 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
970 TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
843 TBool CheckUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount); |
|
844 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
971 TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount); |
845 public: |
|
846 DMutex* iMutex; /**< A mutex for synchronisation and priority inheritance. */ |
|
847 protected: |
|
848 Mmu::TTempMapping iTempMapping; |
|
849 private: |
972 private: |
850 // used to identify memory request is used for... |
973 ~DPageWriteRequest() { } // can't delete |
|
974 private: |
|
975 // used to identify the memory the request is used for... |
851 TUint iUseRegionCount; |
976 TUint iUseRegionCount; |
852 DMemoryObject* iUseRegionMemory[EMaxPages]; |
977 DMemoryObject* iUseRegionMemory[EMaxPages]; |
853 TUint iUseRegionIndex[EMaxPages]; |
978 TUint iUseRegionIndex[EMaxPages]; |
854 }; |
|
855 |
|
856 |
|
857 __ASSERT_COMPILE(DPagingRequest::EMaxPages >= KMaxPagesToClean); |
|
858 |
|
859 |
|
860 /** |
|
861 A paging request that is part of a pool of similar request objects. |
|
862 */ |
|
863 class DPoolPagingRequest : public DPagingRequest |
|
864 { |
|
865 public: |
|
866 DPoolPagingRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
867 void Release(); |
|
868 void Wait(); |
|
869 void Signal(); |
|
870 public: |
|
871 TInt iUsageCount; /**< How many threads are using or waiting for this object. */ |
|
872 private: |
|
873 DPagingRequestPool::TGroup& iPoolGroup; |
|
874 }; |
|
875 |
|
876 |
|
877 /** |
|
878 Resources needed to service a page in request. |
|
879 */ |
|
880 class DPageReadRequest : public DPoolPagingRequest |
|
881 { |
|
882 public: |
|
883 DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup); |
|
884 TInt Construct(); |
|
885 static TUint ReservedPagesRequired(); |
|
886 private: |
|
887 ~DPageReadRequest(); // can't delete |
|
888 public: |
|
889 TLinAddr iBuffer; /**< A buffer to read compressed data into. Size is EMaxPages+1 pages.*/ |
|
890 private: |
|
891 DMemoryObject* iMemory; |
|
892 private: |
|
893 static TInt iAllocNext; |
|
894 }; |
|
895 |
|
896 |
|
897 FORCE_INLINE TUint DPageReadRequest::ReservedPagesRequired() |
|
898 { |
|
899 return iAllocNext*EMaxPages; |
|
900 } |
|
901 |
|
902 |
|
903 /** |
|
904 Resources needed to service a page out request. |
|
905 */ |
|
906 class DPageWriteRequest : public DPagingRequest |
|
907 { |
|
908 public: |
|
909 DPageWriteRequest(); |
|
910 void Release(); |
|
911 private: |
|
912 ~DPageWriteRequest(); // can't delete |
|
913 }; |
979 }; |
914 |
980 |
915 |
981 |
916 /** |
982 /** |
917 Class providing access to the mutex used to protect page cleaning operations; |
983 Class providing access to the mutex used to protect page cleaning operations; |