kernel/eka/memmodel/epoc/flexible/mmu/mpager.h
branchRCL_3
changeset 28 5b5d147c7838
parent 26 c734af59ce98
child 36 bbf8bed59bcb
equal deleted inserted replaced
26:c734af59ce98 28:5b5d147c7838
    24 #include "mmu.h"
    24 #include "mmu.h"
    25 #include <kern_priv.h>
    25 #include <kern_priv.h>
    26 
    26 
    27 /**
    27 /**
    28 Maximum number of pages to attempt to clean in one go.
    28 Maximum number of pages to attempt to clean in one go.
       
    29 
       
    30 If a paging device sets a preferred write size greater than this then it will fail to install with
       
    31 KErrArgument.
    29 */
    32 */
    30 const TInt KMaxPagesToClean = 4;
    33 const TUint KMaxPagesToClean = 16;
    31 
    34 
    32 struct SVMCacheInfo;
    35 struct SVMCacheInfo;
    33 class DMemModelThread;
    36 class DMemModelThread;
    34 class DMemoryMappingBase;
    37 class DMemoryMappingBase;
    35 
    38 
   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);
   369 
   374 
   370 	/**
   375 	/**
   371 	*/
   376 	*/
   372 	void FreePinReplacementPages(TUint aNumPages);
   377 	void FreePinReplacementPages(TUint aNumPages);
   373 
   378 
       
   379 	//
       
   380 	// following public members for use by DDataPagedMemoryManager...
       
   381 	//
       
   382 	
       
   383 	/**
       
   384 	Called by the data paged memory manager to set the number of pages the pager should attempt to
       
   385 	clean at once.
       
   386 
       
   387 	This also adjusts the maximum size of the oldest list if it is too small to contain the
       
   388 	specified number of pages.
       
   389 
       
   390 	@param aPagesToClean     Number of pages the pager should attempt to clean in one go
       
   391 	*/
       
   392 	void SetPagesToClean(TUint aPagesToClean);
       
   393 
       
   394 	/**
       
   395 	Get the number of pages the pager attempts to clean at once.
       
   396 	*/
       
   397 	TUint PagesToClean();
       
   398 
       
   399 	/**
       
   400 	Called by the data paged memory manager to set whether pages cleaned must have sequential page
       
   401 	colour.
       
   402 
       
   403 	@param aCleanInSequence  Whether pages must have sequential page colour
       
   404 	*/
       
   405 	void SetCleanInSequence(TBool aCleanInSequence);
       
   406 
   374 private:
   407 private:
   375 	/**
   408 	/**
   376 	Add a page to the head of the live page list. I.e. make it the 'youngest' page.
   409 	Add a page to the head of the live page list. I.e. make it the 'youngest' page.
   377 
   410 
   378 	@pre MmuLock held
   411 	@pre MmuLock held
   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
   463 	/**
   498 	/**
   464 	Put a page back on the system's free pool.
   499 	Put a page back on the system's free pool.
   465 
   500 
   466 	@pre RamAllocLock held.
   501 	@pre RamAllocLock held.
   467 	*/
   502 	*/
   468 	void ReturnPageToSystem();
   503 	TBool TryReturnOldestPageToSystem();
   469 
   504 
   470 	/**
   505 	/**
   471 	Put a specific page back on the system's free pool.
   506 	Put a specific page back on the system's free pool.
   472 
   507 
   473 	@pre RamAllocLock held.
   508 	@pre RamAllocLock held.
   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 
   571 	@return KErrNone on success, KErrAbort when the mapping is now invalid, KErrNotFound when
   621 	@return KErrNone on success, KErrAbort when the mapping is now invalid, KErrNotFound when
   572 	the page table or page info can't be found.
   622 	the page table or page info can't be found.
   573 	*/
   623 	*/
   574 	TInt PteAndInfoFromLinAddr(	TInt aOsAsid, TLinAddr aAddress, DMemoryMappingBase* aMapping, 
   624 	TInt PteAndInfoFromLinAddr(	TInt aOsAsid, TLinAddr aAddress, DMemoryMappingBase* aMapping, 
   575 								TUint aMapInstanceCount, TPte*& aPte, SPageInfo*& aPageInfo);
   625 								TUint aMapInstanceCount, TPte*& aPte, SPageInfo*& aPageInfo);
       
   626 	
   576 #ifdef _DEBUG
   627 #ifdef _DEBUG
   577 	/**
   628 	/**
   578 	Check consistency of live list.
   629 	Check consistency of live list.
   579 	*/
   630 	*/
   580 	TBool CheckLists();
   631 	TBool CheckLists();
   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);
   770 Multiplier for number of request objects in pool per drive that supports paging.
   825 Multiplier for number of request objects in pool per drive that supports paging.
   771 */
   826 */
   772 const TInt KPagingRequestsPerDevice = 2;
   827 const TInt KPagingRequestsPerDevice = 2;
   773 
   828 
   774 
   829 
   775 class DPoolPagingRequest;
       
   776 class DPageReadRequest;
   830 class DPageReadRequest;
   777 class DPageWriteRequest;
   831 class DPageWriteRequest;
   778 
   832 
   779 /**
   833 /**
   780 A pool of paging requests for use by a single paging device.
   834 A pool of paging requests for use by a single paging device.
   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;