kernel/eka/memmodel/epoc/flexible/mmu/mpager.h
changeset 176 af6ec97d9189
parent 132 e4a7b1cbe40c
child 245 647ab20fee2e
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h	Wed Jun 23 11:59:44 2010 +0100
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h	Wed Jun 23 12:52:28 2010 +0100
@@ -26,8 +26,11 @@
 
 /**
 Maximum number of pages to attempt to clean in one go.
+
+If a paging device sets a preferred write size greater than this then it will fail to install with
+KErrArgument.
 */
-const TInt KMaxPagesToClean = 4;
+const TUint KMaxPagesToClean = 16;
 
 struct SVMCacheInfo;
 class DMemModelThread;
@@ -348,15 +351,17 @@
 	
 	@param aOldPageInfo	The page info of the page to discard.
 	@param aBlockZoneId	The ID of the RAM zone not to allocate any required new page into.
-	@param aBlockRest	Set to ETrue when we don't want the allocator to search for new pages if the RAM 
-						zone with ID==aBlockZoneId is encountered, i.e. a general RAM defrag operation.
+	@param aMoveDisFlags 	Flags that control the discarding of the page, should be a mask of 
+							values from M::TMoveDiscardFlags
 	*/
-	TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TBool aBlockRest);
+	TInt DiscardPage(SPageInfo* aOldPageInfo, TUint aBlockZoneId, TUint aMoveDisFlags);
 
 	/**
 	Attempt to discard the specified page and then allocate a page of type aPageType
 	in its place.
 	
+	Note - This will always attempt to move dirty pages rather than write them to swap.
+	
 	@param aPageInfo	The page info of the page to discard.
 	@param aPageType 	The new page type to allocate into aPageInfo's physical address.
 	*/
@@ -385,6 +390,34 @@
 	*/
 	void FreePinReplacementPages(TUint aNumPages);
 
+	//
+	// following public members for use by DDataPagedMemoryManager...
+	//
+	
+	/**
+	Called by the data paged memory manager to set the number of pages the pager should attempt to
+	clean at once.
+
+	This also adjusts the maximum size of the oldest list if it is too small to contain the
+	specified number of pages.
+
+	@param aPagesToClean     Number of pages the pager should attempt to clean in one go
+	*/
+	void SetPagesToClean(TUint aPagesToClean);
+
+	/**
+	Get the number of pages the pager attempts to clean at once.
+	*/
+	TUint PagesToClean();
+
+	/**
+	Called by the data paged memory manager to set whether pages cleaned must have sequential page
+	colour.
+
+	@param aCleanInSequence  Whether pages must have sequential page colour
+	*/
+	void SetCleanInSequence(TBool aCleanInSequence);
+
 private:
 	/**
 	Add a page to the head of the live page list. I.e. make it the 'youngest' page.
@@ -413,9 +446,20 @@
 	void RemovePage(SPageInfo* aPageInfo);
 
 	/**
-	Try to remove the oldest page from the live page list and perform #StealPage.
+	Get a page, either by stealing one from the live list or allocating one from the system.
+
+	
+	
+	If the oldest page is an oldest dirty page, this may attempt to clean multiple pages by calling
+	#CleanSomePages.
 
-	@param aPageInfoOut Set to the SPageInfo pointer for the stolen page if any.
+	If the oldest page is on any other list (i.e. is an old or young page) this will steal it,
+	aquiring the page cleaning mutex first if it is dirty.
+
+	Called from #PageInAllocPage, #TryReturnOldestPageToSystem, #AllowAddFreePage and 
+	#AllowAddFreePages.
+	
+	@param aAllowAlloc Indicates whether the method should try to allocate a page from the system
 	
 	@return KErrNone on success, KErrInUse if stealing failed or 1 to indicate the the oldest page
 	was dirty and the PageCleaning mutex was not held.
@@ -423,15 +467,7 @@
 	@pre MmuLock held
 	@post MmuLock left unchanged.
 	*/
-	TInt TryStealOldestPage(SPageInfo*& aPageInfoOut);
-
-	/**
-	Remove the oldest page from the live page list and perform #StealPage.
-
-	@pre MmuLock held
-	@post MmuLock held (but may have been released by this function)
-	*/
-	SPageInfo* StealOldestPage();
+	SPageInfo* StealOrAllocPage(TBool aAllowAlloc, Mmu::TRamAllocFlags aAllocFlags);
 
 	/**
 	Steal a page from the memory object (if any) which is using the page.
@@ -479,9 +515,32 @@
 
 	@pre RamAllocLock held.
 	*/
-	void ReturnPageToSystem();
+	TBool TryReturnOldestPageToSystem();
+
+	/**
+	Ensure adding a page to the paging cache will be within the maximum size.
+	
+	@param aPageInfo	On return this is set to the SPageInfo of a page that must be returned
+						to the system before a page can be added to the paging cache, or
+						NULL if no page must be returned to the system.
+	*/
+	void AllowAddFreePage(SPageInfo*& aPageInfo);
 
 	/**
+	Ensure adding aNumPages pages to the paging cache will be within the maximum size.
+	
+	@param aPageInfo	On return this is set to the SPageInfo of a page that must be returned
+						to the system before any more pages can be added to the paging cache, or
+						NULL if no page must be returned to the system.
+	@param aNumPages	The number of pages the caller wishes to add to the paging cache.
+	
+	@return If aPageInfo == NULL on return, this is the number of pages it is possible to
+			add to the paging cache or 1 if aPageInfo != NULL, i.e. a page will need 
+			to be returned to the system.
+	*/
+	TUint AllowAddFreePages(SPageInfo*& aPageInfo, TUint aNumPages);
+	
+	/**
 	Put a specific page back on the system's free pool.
 
 	@pre RamAllocLock held.
@@ -498,11 +557,11 @@
 	SPageInfo* PageInAllocPage(Mmu::TRamAllocFlags aAllocFlags);
 
 	/**
-	Called by CleanSomePages() to determine which pages should be cleaned.
+	Called by CleanSomePages() to select the pages be cleaned.
 
-	This deals with the complexity of page colouring, which means that pages can only be mapped at
-	certain locations.  When cleaning multiple pages at once we need to find a set of pages that we
-	can map in memory sequentially.
+	This function finds a set of pages that can be mapped sequentially in memory when page colouring
+	restrictions are in effect.  It is only called on systems with page colouring restrictions where
+	the paging media driver does not support writing by phyiscal address.
 
 	@pre MmuLock held
 	
@@ -511,7 +570,22 @@
 	
 	@return The numnber of pages to clean.
 	*/
-	TInt SelectPagesToClean(SPageInfo** aPageInfosOut);
+	TInt SelectSequentialPagesToClean(SPageInfo** aPageInfosOut);
+
+	/**
+	Called by CleanSomePages() to select the pages be cleaned.
+
+	This funciton selects the oldest dirty pages.  It is called on systems without page colouring
+	restrictions or where the paging media driver supports writing by phyiscal address.
+
+	@pre MmuLock held
+	
+	@param aPageInfosOut Pointer to an array of SPageInfo pointers, which must be at least
+	KMaxPagesToClean long.  This will be filled in to indicate the pages to clean.
+	
+	@return The numnber of pages to clean.
+	*/
+	TInt SelectOldestPagesToClean(SPageInfo** aPageInfosOut);
 
 	/**
 	If the number of young pages exceeds that specified by iYoungOldRatio then a
@@ -587,6 +661,7 @@
 	*/
 	TInt PteAndInfoFromLinAddr(	TInt aOsAsid, TLinAddr aAddress, DMemoryMappingBase* aMapping, 
 								TUint aMapInstanceCount, TPte*& aPte, SPageInfo*& aPageInfo);
+	
 #ifdef _DEBUG
 	/**
 	Check consistency of live list.
@@ -612,6 +687,7 @@
 	SDblQue iOldestDirtyList;	/**< Head of 'oldestDirty' page list. */
 	TUint iOldestDirtyCount;	/**< Number of 'oldestDirty' pages */
 	TUint16 iOldOldestRatio;	/**< Ratio of old pages to oldest to clean and dirty in the live page list*/
+	TUint iMaxOldestPages;      /**< Maximum number of oldest pages. */
 	TUint iNumberOfFreePages;
 	TUint iNumberOfDirtyPages;	/**< The total number of dirty pages in the paging cache. Protected by MmuLock */
 	TUint iInitMinimumPageCount;/**< Initial value for iMinimumPageCount */
@@ -619,6 +695,9 @@
 	TUint iReservePageCount;	/**< Number of pages reserved for locking */
 	TUint iMinimumPageLimit;	/**< Minimum size for iMinimumPageCount, not including locked pages.
 								     iMinimumPageCount >= iMinimumPageLimit + iReservePageCount */
+	TUint iPagesToClean;        /**< Preferred number of pages to attempt to clean in one go. */
+	TBool iCleanInSequence;     /**< Pages to be cleaned must have sequential page colour. */
+
 	SVMEventInfo iEventInfo;
 
 #ifdef __DEMAND_PAGING_BENCHMARKS__
@@ -786,7 +865,6 @@
 const TInt KPagingRequestsPerDevice = 2;
 
 
-class DPoolPagingRequest;
 class DPageReadRequest;
 class DPageWriteRequest;
 
@@ -806,110 +884,98 @@
 		{
 	public:
 		TGroup(TUint aNumRequests);
-		DPoolPagingRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
-		DPoolPagingRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
-		void Signal(DPoolPagingRequest* aRequest);
+		DPageReadRequest* FindCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+		DPageReadRequest* GetRequest(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
 	public:
 		TUint iNumRequests;
-		DPoolPagingRequest** iRequests;
+		DPageReadRequest** iRequests;
 		SDblQue iFreeList;
 		};
 	TGroup iPageReadRequests;
 	DPageWriteRequest* iPageWriteRequest;
 
-	friend class DPoolPagingRequest;
 	friend class DPageReadRequest;
-	friend class DPageWriteRequest;
 	};
 
 
 /**
-Resources needed to service a paging request.
+Common resources needed to service a paging request.
 */
-class DPagingRequest : public SDblQueLink
+class DPagingRequestBase : public DBase
 	{
 public:
+	TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages);
+	void UnmapPages(TBool aIMBRequired);
+public:  // for DPagingRequestPool
+	DMutex*			iMutex;		/**< A mutex for synchronisation and priority inheritance. */
+protected:
+	Mmu::TTempMapping	iTempMapping;
+	};
+
+
+/**
+Resources needed to service a page in request.
+*/
+class DPageReadRequest : public DPagingRequestBase
+	{
+public:
+	static TUint ReservedPagesRequired();
+private:
+	static TInt iAllocNext;
+
+public:
 	enum
 		{
 		EMaxPages = 4
 		};
-	DPagingRequest();
-	TLinAddr MapPages(TUint aColour, TUint aCount, TPhysAddr* aPages);
-	void UnmapPages(TBool aIMBRequired);
-	void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
-	void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount);
-	void ResetUse();
-	TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
-	TBool CheckUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount);
-	TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
-public:
-	DMutex*			iMutex;		/**< A mutex for synchronisation and priority inheritance. */
-protected:
-	Mmu::TTempMapping	iTempMapping;
-private:
-	// used to identify memory request is used for...
-	TUint			iUseRegionCount;
-	DMemoryObject*	iUseRegionMemory[EMaxPages];
-	TUint			iUseRegionIndex[EMaxPages];
-	};
-
-
-__ASSERT_COMPILE(DPagingRequest::EMaxPages >= KMaxPagesToClean);
-
-
-/**
-A paging request that is part of a pool of similar request objects.
-*/
-class DPoolPagingRequest : public DPagingRequest
-	{
-public:
-	DPoolPagingRequest(DPagingRequestPool::TGroup& aPoolGroup);
+	DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup);
+	TInt Construct();
  	void Release();
 	void Wait();
 	void Signal();
-public:
-	TInt			iUsageCount;	/**< How many threads are using or waiting for this object. */	
+	void SetUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+	void ResetUse();
+	TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+	TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+	TLinAddr Buffer() { return iBuffer; }
+	TUint ThreadsWaiting() { return iUsageCount; }
 private:
+	~DPageReadRequest() { }  // can't delete
+public:  // for DPagingRequestPool
+	SDblQueLink iLink;  /**< Link into list of free requests. */
+private:
+	TInt iUsageCount;	/**< How many threads are using or waiting for this object. */	
+	TLinAddr iBuffer;	/**< A buffer of size EMaxPages+1 pages to read compressed data into. */
 	DPagingRequestPool::TGroup& iPoolGroup;
+	DMemoryObject* iMemory;
+	TUint iIndex;
+	TUint iCount;
 	};
 
-	
-/**
-Resources needed to service a page in request.
-*/
-class DPageReadRequest : public DPoolPagingRequest
-	{
-public:
-	DPageReadRequest(DPagingRequestPool::TGroup& aPoolGroup);
-	TInt Construct();
-	static TUint ReservedPagesRequired();
-private:
-	~DPageReadRequest(); // can't delete
-public:
-	TLinAddr		iBuffer;	/**< A buffer to read compressed data into. Size is EMaxPages+1 pages.*/
-private:
-	DMemoryObject*	iMemory;
-private:
-	static TInt iAllocNext;
-	};
-
-
-FORCE_INLINE TUint DPageReadRequest::ReservedPagesRequired()
-	{
-	return iAllocNext*EMaxPages;
-	}
-
 
 /**
 Resources needed to service a page out request.
 */
-class DPageWriteRequest : public DPagingRequest
+class DPageWriteRequest : public DPagingRequestBase
 	{
 public:
+	enum
+		{
+		EMaxPages = KMaxPagesToClean
+		};
 	DPageWriteRequest();
  	void Release();
+	void SetUseDiscontiguous(DMemoryObject** aMemory, TUint* aIndex, TUint aCount);
+	void ResetUse();
+	TBool CheckUseContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+	TBool IsCollisionContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
 private:
-	~DPageWriteRequest(); // can't delete
+	~DPageWriteRequest() { }  // can't delete	
+private:
+	// used to identify the memory the request is used for...
+	TUint			iUseRegionCount;
+	DMemoryObject*	iUseRegionMemory[EMaxPages];
+	TUint			iUseRegionIndex[EMaxPages];
 	};