kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp
branchRCL_3
changeset 19 4a8fed1c0ef6
parent 0 a41df078684a
child 22 2f92ad2dc5db
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp	Tue Feb 02 01:24:03 2010 +0200
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp	Sat Feb 20 00:10:51 2010 +0200
@@ -50,14 +50,26 @@
 
 DPager::DPager()
 	: iMinimumPageCount(0), iMaximumPageCount(0), iYoungOldRatio(0),
-	  iYoungCount(0),iOldCount(0),iNumberOfFreePages(0)
+	  iYoungCount(0),iOldCount(0),
+#ifdef _USE_OLDEST_LISTS
+	  iOldestCleanCount(0),
+#endif
+	  iNumberOfFreePages(0), iReservePageCount(0), iMinimumPageLimit(0)
 	{
 	}
 
 
-void DPager::Init2()
+void DPager::InitCache()
 	{
-	TRACEB(("DPager::Init2()"));
+	//
+	// This routine doesn't acquire any mutexes because it should be called before the system
+	// is fully up and running. I.e. called before another thread can preempt this.
+	//
+	TRACEB(("DPager::InitCache()"));
+	// If any pages have been reserved then they will have already been allocated and 
+	// therefore should be counted as part of iMinimumPageCount.
+	__NK_ASSERT_DEBUG(iReservePageCount == iMinimumPageCount);
+	__NK_ASSERT_DEBUG(!CacheInitialised());
 
 #if defined(__CPU_ARM)
 
@@ -104,85 +116,92 @@
 
 	__NK_ASSERT_DEBUG(KMinOldPages<=iAbsoluteMinPageCount/2);
 
-	// initialise live list...
-	TUint minimumPageCount = 0;
-	TUint maximumPageCount = 0;
-
+	// Read any paging config data.
 	SDemandPagingConfig config = TheRomHeader().iDemandPagingConfig;
 
-	iMinimumPageCount = KDefaultMinPages;
-	if(minimumPageCount)
-		iMinimumPageCount = minimumPageCount;
-	if(config.iMinPages)
-		iMinimumPageCount = config.iMinPages;
-	if(iMinimumPageCount<iAbsoluteMinPageCount)
-		iMinimumPageCount = iAbsoluteMinPageCount;
-	iInitMinimumPageCount = iMinimumPageCount;
-
-	iMaximumPageCount = KMaxTInt;
-	if(maximumPageCount)
-		iMaximumPageCount = maximumPageCount;
-	if(config.iMaxPages)
-		iMaximumPageCount = config.iMaxPages;
-	if (iMaximumPageCount > KAbsoluteMaxPageCount)
-		iMaximumPageCount = KAbsoluteMaxPageCount;
-	iInitMaximumPageCount = iMaximumPageCount;
-
+	// Set the list ratios...
 	iYoungOldRatio = KDefaultYoungOldRatio;
 	if(config.iYoungOldRatio)
 		iYoungOldRatio = config.iYoungOldRatio;
-	TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages;
-	if(iYoungOldRatio>ratioLimit)
-		iYoungOldRatio = ratioLimit;
-
 #ifdef _USE_OLDEST_LISTS
 	iOldOldestRatio = KDefaultOldOldestRatio;
 	if(config.iSpare[2])
 		iOldOldestRatio = config.iSpare[2];
 #endif
 
-	iMinimumPageLimit = (iMinYoungPages * (1 + iYoungOldRatio)) / iYoungOldRatio;
-	if(iMinimumPageLimit<iAbsoluteMinPageCount)
+	// Set the minimum page counts...
+	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
+									   + DPageReadRequest::ReservedPagesRequired();
+	
+	if(iMinimumPageLimit < iAbsoluteMinPageCount)
 		iMinimumPageLimit = iAbsoluteMinPageCount;
 
-	TRACEB(("DPager::Init2() live list min=%d max=%d ratio=%d",iMinimumPageCount,iMaximumPageCount,iYoungOldRatio));
-
-	if(iMaximumPageCount<iMinimumPageCount)
-		__NK_ASSERT_ALWAYS(0);
-
-	//
-	// This routine doesn't acquire any mutexes because it should be called before the system
-	// is fully up and running. I.e. called before another thread can preempt this.
-	//
-
-	// Calculate page counts
+	if (K::MemModelAttributes & (EMemModelAttrRomPaging | EMemModelAttrCodePaging | EMemModelAttrDataPaging))
+	    iMinimumPageCount = KDefaultMinPages; 
+	else
+		{// No paging is enabled so set the minimum cache size to the minimum
+		// allowable with the current young old ratio.
+	    iMinimumPageCount = iMinYoungPages * (iYoungOldRatio + 1);
+		}
+
+	if(config.iMinPages)
+		iMinimumPageCount = config.iMinPages;
+	if(iMinimumPageCount < iAbsoluteMinPageCount)
+		iMinimumPageCount = iAbsoluteMinPageCount;
+	if (iMinimumPageLimit + iReservePageCount > iMinimumPageCount)
+		iMinimumPageCount = iMinimumPageLimit + iReservePageCount;
+
+	iInitMinimumPageCount = iMinimumPageCount;
+
+	// Set the maximum page counts...
+	iMaximumPageCount = KMaxTInt;
+	if(config.iMaxPages)
+		iMaximumPageCount = config.iMaxPages;
+	if (iMaximumPageCount > KAbsoluteMaxPageCount)
+		iMaximumPageCount = KAbsoluteMaxPageCount;
+	iInitMaximumPageCount = iMaximumPageCount;
+
+
+	TRACEB(("DPager::InitCache() live list min=%d max=%d ratio=%d",iMinimumPageCount,iMaximumPageCount,iYoungOldRatio));
+
+	// Verify the page counts are valid.
+	__NK_ASSERT_ALWAYS(iMaximumPageCount >= iMinimumPageCount);
 	TUint minOldAndOldest = iMinimumPageCount / (1 + iYoungOldRatio);
-	if(minOldAndOldest < KMinOldPages)
-		__NK_ASSERT_ALWAYS(0);
-	if (iMinimumPageCount < minOldAndOldest)
-		__NK_ASSERT_ALWAYS(0);
+	__NK_ASSERT_ALWAYS(minOldAndOldest >= KMinOldPages);
+	__NK_ASSERT_ALWAYS(iMinimumPageCount >= minOldAndOldest);
+
+	// Need at least iMinYoungPages pages mapped to execute worst case CPU instruction
 	TUint minYoung = iMinimumPageCount - minOldAndOldest;
-	if(minYoung < iMinYoungPages)
-		__NK_ASSERT_ALWAYS(0); // Need at least iMinYoungPages pages mapped to execute worst case CPU instruction
+	__NK_ASSERT_ALWAYS(minYoung >= iMinYoungPages);
+
+	// Verify that the young old ratio can be met even when there is only the 
+	// minimum number of old pages.
+	TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages;
+	__NK_ASSERT_ALWAYS(iYoungOldRatio <= ratioLimit);
+
 #ifdef _USE_OLDEST_LISTS
 	// There should always be enough old pages to allow the oldest lists ratio.
 	TUint oldestCount = minOldAndOldest / (1 + iOldOldestRatio);
-	if (!oldestCount)
-		__NK_ASSERT_ALWAYS(0);
+	__NK_ASSERT_ALWAYS(oldestCount);
 #endif
+
 	iNumberOfFreePages = 0;
 	iNumberOfDirtyPages = 0;
 
-	// Allocate RAM pages and put them all on the old list
+	// Allocate RAM pages and put them all on the old list.
+	// Reserved pages have already been allocated and already placed on the
+	// old list so don't allocate them again.
 	RamAllocLock::Lock();
 	iYoungCount = 0;
+#ifdef _USE_OLDEST_LISTS
 	iOldCount = 0;
-#ifdef _USE_OLDEST_LISTS
-	iOldestCleanCount = 0;
 	iOldestDirtyCount = 0;
+	__NK_ASSERT_DEBUG(iOldestCleanCount == iReservePageCount);
+#else
+	__NK_ASSERT_DEBUG(iOldCount == iReservePageCount);
 #endif
 	Mmu& m = TheMmu;
-	for(TUint i=0; i<iMinimumPageCount; i++)
+	for(TUint i = iReservePageCount; i < iMinimumPageCount; i++)
 		{
 		// Allocate a single page
 		TPhysAddr pagePhys;
@@ -197,10 +216,11 @@
 		}
 	RamAllocLock::Unlock();
 
+	__NK_ASSERT_DEBUG(CacheInitialised());
 #ifdef _USE_OLDEST_LISTS
-	TRACEB(("DPager::Init2() end with young=%d old=%d oldClean=%d oldDirty=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iOldestCleanCount,iOldestDirtyCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
+	TRACEB(("DPager::InitCache() end with young=%d old=%d oldClean=%d oldDirty=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iOldestCleanCount,iOldestDirtyCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
 #else
-	TRACEB(("DPager::Init2() end with young=%d old=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
+	TRACEB(("DPager::InitCache() end with young=%d old=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
 #endif
 	}
 
@@ -1688,6 +1708,8 @@
 TInt DPager::ResizeLiveList(TUint aMinimumPageCount, TUint aMaximumPageCount)
 	{
 	TRACE(("DPager::ResizeLiveList(%d,%d) current young=%d old=%d min=%d free=%d max=%d",aMinimumPageCount,aMaximumPageCount,iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
+	__NK_ASSERT_DEBUG(CacheInitialised());
+
 	if(!aMaximumPageCount)
 		{
 		aMinimumPageCount = iInitMinimumPageCount;
@@ -1705,6 +1727,8 @@
 
 	MmuLock::Lock();
 
+	__NK_ASSERT_ALWAYS(iYoungOldRatio!=0);
+
 	// Make sure aMinimumPageCount is not less than absolute minimum we can cope with...
 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
 						+ DPageReadRequest::ReservedPagesRequired();
@@ -2190,11 +2214,6 @@
 		return r;
 	iBuffer = MM::MappingBase(bufferMapping);
 
-	// ensure there are enough young pages to cope with new request object...
-	r = ThePager.ResizeLiveList();
-	if(r!=KErrNone)
-		return r;
-
 	return r;
 	}
 
@@ -2406,6 +2425,7 @@
 	{
 	TRACEB(("Kern::InstallPagingDevice(0x%08x) name='%s' type=%d",aDevice,aDevice->iName,aDevice->iType));
 
+	__NK_ASSERT_DEBUG(!ThePager.CacheInitialised());
 	__NK_ASSERT_ALWAYS(aDevice->iReadUnitShift <= KPageShift);
 
 	TInt r = KErrNotSupported;	// Will return this if unsupported device type is installed