kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp
branchRCL_3
changeset 19 4a8fed1c0ef6
parent 0 a41df078684a
child 22 2f92ad2dc5db
equal deleted inserted replaced
15:2d65c2f76d7b 19:4a8fed1c0ef6
    48 DPager ThePager;
    48 DPager ThePager;
    49 
    49 
    50 
    50 
    51 DPager::DPager()
    51 DPager::DPager()
    52 	: iMinimumPageCount(0), iMaximumPageCount(0), iYoungOldRatio(0),
    52 	: iMinimumPageCount(0), iMaximumPageCount(0), iYoungOldRatio(0),
    53 	  iYoungCount(0),iOldCount(0),iNumberOfFreePages(0)
    53 	  iYoungCount(0),iOldCount(0),
    54 	{
    54 #ifdef _USE_OLDEST_LISTS
    55 	}
    55 	  iOldestCleanCount(0),
    56 
    56 #endif
    57 
    57 	  iNumberOfFreePages(0), iReservePageCount(0), iMinimumPageLimit(0)
    58 void DPager::Init2()
    58 	{
    59 	{
    59 	}
    60 	TRACEB(("DPager::Init2()"));
    60 
       
    61 
       
    62 void DPager::InitCache()
       
    63 	{
       
    64 	//
       
    65 	// This routine doesn't acquire any mutexes because it should be called before the system
       
    66 	// is fully up and running. I.e. called before another thread can preempt this.
       
    67 	//
       
    68 	TRACEB(("DPager::InitCache()"));
       
    69 	// If any pages have been reserved then they will have already been allocated and 
       
    70 	// therefore should be counted as part of iMinimumPageCount.
       
    71 	__NK_ASSERT_DEBUG(iReservePageCount == iMinimumPageCount);
       
    72 	__NK_ASSERT_DEBUG(!CacheInitialised());
    61 
    73 
    62 #if defined(__CPU_ARM)
    74 #if defined(__CPU_ARM)
    63 
    75 
    64 /** Minimum number of young pages the demand paging live list may have.
    76 /** Minimum number of young pages the demand paging live list may have.
    65 	Need at least 4 mapped pages to guarantee to be able to execute all ARM instructions,
    77 	Need at least 4 mapped pages to guarantee to be able to execute all ARM instructions,
   102 	// A minimum young/old ratio of 1 means that we need at least twice iMinYoungPages pages...
   114 	// A minimum young/old ratio of 1 means that we need at least twice iMinYoungPages pages...
   103 	iAbsoluteMinPageCount = 2*iMinYoungPages;
   115 	iAbsoluteMinPageCount = 2*iMinYoungPages;
   104 
   116 
   105 	__NK_ASSERT_DEBUG(KMinOldPages<=iAbsoluteMinPageCount/2);
   117 	__NK_ASSERT_DEBUG(KMinOldPages<=iAbsoluteMinPageCount/2);
   106 
   118 
   107 	// initialise live list...
   119 	// Read any paging config data.
   108 	TUint minimumPageCount = 0;
       
   109 	TUint maximumPageCount = 0;
       
   110 
       
   111 	SDemandPagingConfig config = TheRomHeader().iDemandPagingConfig;
   120 	SDemandPagingConfig config = TheRomHeader().iDemandPagingConfig;
   112 
   121 
   113 	iMinimumPageCount = KDefaultMinPages;
   122 	// Set the list ratios...
   114 	if(minimumPageCount)
   123 	iYoungOldRatio = KDefaultYoungOldRatio;
   115 		iMinimumPageCount = minimumPageCount;
   124 	if(config.iYoungOldRatio)
       
   125 		iYoungOldRatio = config.iYoungOldRatio;
       
   126 #ifdef _USE_OLDEST_LISTS
       
   127 	iOldOldestRatio = KDefaultOldOldestRatio;
       
   128 	if(config.iSpare[2])
       
   129 		iOldOldestRatio = config.iSpare[2];
       
   130 #endif
       
   131 
       
   132 	// Set the minimum page counts...
       
   133 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
       
   134 									   + DPageReadRequest::ReservedPagesRequired();
       
   135 	
       
   136 	if(iMinimumPageLimit < iAbsoluteMinPageCount)
       
   137 		iMinimumPageLimit = iAbsoluteMinPageCount;
       
   138 
       
   139 	if (K::MemModelAttributes & (EMemModelAttrRomPaging | EMemModelAttrCodePaging | EMemModelAttrDataPaging))
       
   140 	    iMinimumPageCount = KDefaultMinPages; 
       
   141 	else
       
   142 		{// No paging is enabled so set the minimum cache size to the minimum
       
   143 		// allowable with the current young old ratio.
       
   144 	    iMinimumPageCount = iMinYoungPages * (iYoungOldRatio + 1);
       
   145 		}
       
   146 
   116 	if(config.iMinPages)
   147 	if(config.iMinPages)
   117 		iMinimumPageCount = config.iMinPages;
   148 		iMinimumPageCount = config.iMinPages;
   118 	if(iMinimumPageCount<iAbsoluteMinPageCount)
   149 	if(iMinimumPageCount < iAbsoluteMinPageCount)
   119 		iMinimumPageCount = iAbsoluteMinPageCount;
   150 		iMinimumPageCount = iAbsoluteMinPageCount;
       
   151 	if (iMinimumPageLimit + iReservePageCount > iMinimumPageCount)
       
   152 		iMinimumPageCount = iMinimumPageLimit + iReservePageCount;
       
   153 
   120 	iInitMinimumPageCount = iMinimumPageCount;
   154 	iInitMinimumPageCount = iMinimumPageCount;
   121 
   155 
       
   156 	// Set the maximum page counts...
   122 	iMaximumPageCount = KMaxTInt;
   157 	iMaximumPageCount = KMaxTInt;
   123 	if(maximumPageCount)
       
   124 		iMaximumPageCount = maximumPageCount;
       
   125 	if(config.iMaxPages)
   158 	if(config.iMaxPages)
   126 		iMaximumPageCount = config.iMaxPages;
   159 		iMaximumPageCount = config.iMaxPages;
   127 	if (iMaximumPageCount > KAbsoluteMaxPageCount)
   160 	if (iMaximumPageCount > KAbsoluteMaxPageCount)
   128 		iMaximumPageCount = KAbsoluteMaxPageCount;
   161 		iMaximumPageCount = KAbsoluteMaxPageCount;
   129 	iInitMaximumPageCount = iMaximumPageCount;
   162 	iInitMaximumPageCount = iMaximumPageCount;
   130 
   163 
   131 	iYoungOldRatio = KDefaultYoungOldRatio;
   164 
   132 	if(config.iYoungOldRatio)
   165 	TRACEB(("DPager::InitCache() live list min=%d max=%d ratio=%d",iMinimumPageCount,iMaximumPageCount,iYoungOldRatio));
   133 		iYoungOldRatio = config.iYoungOldRatio;
   166 
       
   167 	// Verify the page counts are valid.
       
   168 	__NK_ASSERT_ALWAYS(iMaximumPageCount >= iMinimumPageCount);
       
   169 	TUint minOldAndOldest = iMinimumPageCount / (1 + iYoungOldRatio);
       
   170 	__NK_ASSERT_ALWAYS(minOldAndOldest >= KMinOldPages);
       
   171 	__NK_ASSERT_ALWAYS(iMinimumPageCount >= minOldAndOldest);
       
   172 
       
   173 	// Need at least iMinYoungPages pages mapped to execute worst case CPU instruction
       
   174 	TUint minYoung = iMinimumPageCount - minOldAndOldest;
       
   175 	__NK_ASSERT_ALWAYS(minYoung >= iMinYoungPages);
       
   176 
       
   177 	// Verify that the young old ratio can be met even when there is only the 
       
   178 	// minimum number of old pages.
   134 	TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages;
   179 	TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages;
   135 	if(iYoungOldRatio>ratioLimit)
   180 	__NK_ASSERT_ALWAYS(iYoungOldRatio <= ratioLimit);
   136 		iYoungOldRatio = ratioLimit;
   181 
   137 
       
   138 #ifdef _USE_OLDEST_LISTS
       
   139 	iOldOldestRatio = KDefaultOldOldestRatio;
       
   140 	if(config.iSpare[2])
       
   141 		iOldOldestRatio = config.iSpare[2];
       
   142 #endif
       
   143 
       
   144 	iMinimumPageLimit = (iMinYoungPages * (1 + iYoungOldRatio)) / iYoungOldRatio;
       
   145 	if(iMinimumPageLimit<iAbsoluteMinPageCount)
       
   146 		iMinimumPageLimit = iAbsoluteMinPageCount;
       
   147 
       
   148 	TRACEB(("DPager::Init2() live list min=%d max=%d ratio=%d",iMinimumPageCount,iMaximumPageCount,iYoungOldRatio));
       
   149 
       
   150 	if(iMaximumPageCount<iMinimumPageCount)
       
   151 		__NK_ASSERT_ALWAYS(0);
       
   152 
       
   153 	//
       
   154 	// This routine doesn't acquire any mutexes because it should be called before the system
       
   155 	// is fully up and running. I.e. called before another thread can preempt this.
       
   156 	//
       
   157 
       
   158 	// Calculate page counts
       
   159 	TUint minOldAndOldest = iMinimumPageCount / (1 + iYoungOldRatio);
       
   160 	if(minOldAndOldest < KMinOldPages)
       
   161 		__NK_ASSERT_ALWAYS(0);
       
   162 	if (iMinimumPageCount < minOldAndOldest)
       
   163 		__NK_ASSERT_ALWAYS(0);
       
   164 	TUint minYoung = iMinimumPageCount - minOldAndOldest;
       
   165 	if(minYoung < iMinYoungPages)
       
   166 		__NK_ASSERT_ALWAYS(0); // Need at least iMinYoungPages pages mapped to execute worst case CPU instruction
       
   167 #ifdef _USE_OLDEST_LISTS
   182 #ifdef _USE_OLDEST_LISTS
   168 	// There should always be enough old pages to allow the oldest lists ratio.
   183 	// There should always be enough old pages to allow the oldest lists ratio.
   169 	TUint oldestCount = minOldAndOldest / (1 + iOldOldestRatio);
   184 	TUint oldestCount = minOldAndOldest / (1 + iOldOldestRatio);
   170 	if (!oldestCount)
   185 	__NK_ASSERT_ALWAYS(oldestCount);
   171 		__NK_ASSERT_ALWAYS(0);
   186 #endif
   172 #endif
   187 
   173 	iNumberOfFreePages = 0;
   188 	iNumberOfFreePages = 0;
   174 	iNumberOfDirtyPages = 0;
   189 	iNumberOfDirtyPages = 0;
   175 
   190 
   176 	// Allocate RAM pages and put them all on the old list
   191 	// Allocate RAM pages and put them all on the old list.
       
   192 	// Reserved pages have already been allocated and already placed on the
       
   193 	// old list so don't allocate them again.
   177 	RamAllocLock::Lock();
   194 	RamAllocLock::Lock();
   178 	iYoungCount = 0;
   195 	iYoungCount = 0;
       
   196 #ifdef _USE_OLDEST_LISTS
   179 	iOldCount = 0;
   197 	iOldCount = 0;
   180 #ifdef _USE_OLDEST_LISTS
       
   181 	iOldestCleanCount = 0;
       
   182 	iOldestDirtyCount = 0;
   198 	iOldestDirtyCount = 0;
       
   199 	__NK_ASSERT_DEBUG(iOldestCleanCount == iReservePageCount);
       
   200 #else
       
   201 	__NK_ASSERT_DEBUG(iOldCount == iReservePageCount);
   183 #endif
   202 #endif
   184 	Mmu& m = TheMmu;
   203 	Mmu& m = TheMmu;
   185 	for(TUint i=0; i<iMinimumPageCount; i++)
   204 	for(TUint i = iReservePageCount; i < iMinimumPageCount; i++)
   186 		{
   205 		{
   187 		// Allocate a single page
   206 		// Allocate a single page
   188 		TPhysAddr pagePhys;
   207 		TPhysAddr pagePhys;
   189 		TInt r = m.AllocRam(&pagePhys, 1, 
   208 		TInt r = m.AllocRam(&pagePhys, 1, 
   190 							(Mmu::TRamAllocFlags)(EMemAttNormalCached|Mmu::EAllocNoWipe|Mmu::EAllocNoPagerReclaim), 
   209 							(Mmu::TRamAllocFlags)(EMemAttNormalCached|Mmu::EAllocNoWipe|Mmu::EAllocNoPagerReclaim), 
   195 		AddAsFreePage(SPageInfo::FromPhysAddr(pagePhys));
   214 		AddAsFreePage(SPageInfo::FromPhysAddr(pagePhys));
   196 		MmuLock::Unlock();
   215 		MmuLock::Unlock();
   197 		}
   216 		}
   198 	RamAllocLock::Unlock();
   217 	RamAllocLock::Unlock();
   199 
   218 
       
   219 	__NK_ASSERT_DEBUG(CacheInitialised());
   200 #ifdef _USE_OLDEST_LISTS
   220 #ifdef _USE_OLDEST_LISTS
   201 	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));
   221 	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));
   202 #else
   222 #else
   203 	TRACEB(("DPager::Init2() end with young=%d old=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
   223 	TRACEB(("DPager::InitCache() end with young=%d old=%d min=%d free=%d max=%d",iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
   204 #endif
   224 #endif
   205 	}
   225 	}
   206 
   226 
   207 
   227 
   208 #ifdef _DEBUG
   228 #ifdef _DEBUG
  1686 
  1706 
  1687 
  1707 
  1688 TInt DPager::ResizeLiveList(TUint aMinimumPageCount, TUint aMaximumPageCount)
  1708 TInt DPager::ResizeLiveList(TUint aMinimumPageCount, TUint aMaximumPageCount)
  1689 	{
  1709 	{
  1690 	TRACE(("DPager::ResizeLiveList(%d,%d) current young=%d old=%d min=%d free=%d max=%d",aMinimumPageCount,aMaximumPageCount,iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
  1710 	TRACE(("DPager::ResizeLiveList(%d,%d) current young=%d old=%d min=%d free=%d max=%d",aMinimumPageCount,aMaximumPageCount,iYoungCount,iOldCount,iMinimumPageCount,iNumberOfFreePages,iMaximumPageCount));
       
  1711 	__NK_ASSERT_DEBUG(CacheInitialised());
       
  1712 
  1691 	if(!aMaximumPageCount)
  1713 	if(!aMaximumPageCount)
  1692 		{
  1714 		{
  1693 		aMinimumPageCount = iInitMinimumPageCount;
  1715 		aMinimumPageCount = iInitMinimumPageCount;
  1694 		aMaximumPageCount = iInitMaximumPageCount;
  1716 		aMaximumPageCount = iInitMaximumPageCount;
  1695 		}
  1717 		}
  1702 
  1724 
  1703 	NKern::ThreadEnterCS();
  1725 	NKern::ThreadEnterCS();
  1704 	RamAllocLock::Lock();
  1726 	RamAllocLock::Lock();
  1705 
  1727 
  1706 	MmuLock::Lock();
  1728 	MmuLock::Lock();
       
  1729 
       
  1730 	__NK_ASSERT_ALWAYS(iYoungOldRatio!=0);
  1707 
  1731 
  1708 	// Make sure aMinimumPageCount is not less than absolute minimum we can cope with...
  1732 	// Make sure aMinimumPageCount is not less than absolute minimum we can cope with...
  1709 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
  1733 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
  1710 						+ DPageReadRequest::ReservedPagesRequired();
  1734 						+ DPageReadRequest::ReservedPagesRequired();
  1711 	if(iMinimumPageLimit<iAbsoluteMinPageCount)
  1735 	if(iMinimumPageLimit<iAbsoluteMinPageCount)
  2188 	r = MM::MappingNew(bufferMapping,bufferMemory,ESupervisorReadWrite,KKernelOsAsid);
  2212 	r = MM::MappingNew(bufferMapping,bufferMemory,ESupervisorReadWrite,KKernelOsAsid);
  2189 	if(r!=KErrNone)
  2213 	if(r!=KErrNone)
  2190 		return r;
  2214 		return r;
  2191 	iBuffer = MM::MappingBase(bufferMapping);
  2215 	iBuffer = MM::MappingBase(bufferMapping);
  2192 
  2216 
  2193 	// ensure there are enough young pages to cope with new request object...
       
  2194 	r = ThePager.ResizeLiveList();
       
  2195 	if(r!=KErrNone)
       
  2196 		return r;
       
  2197 
       
  2198 	return r;
  2217 	return r;
  2199 	}
  2218 	}
  2200 
  2219 
  2201 
  2220 
  2202 //
  2221 //
  2404 */
  2423 */
  2405 EXPORT_C TInt Kern::InstallPagingDevice(DPagingDevice* aDevice)
  2424 EXPORT_C TInt Kern::InstallPagingDevice(DPagingDevice* aDevice)
  2406 	{
  2425 	{
  2407 	TRACEB(("Kern::InstallPagingDevice(0x%08x) name='%s' type=%d",aDevice,aDevice->iName,aDevice->iType));
  2426 	TRACEB(("Kern::InstallPagingDevice(0x%08x) name='%s' type=%d",aDevice,aDevice->iName,aDevice->iType));
  2408 
  2427 
       
  2428 	__NK_ASSERT_DEBUG(!ThePager.CacheInitialised());
  2409 	__NK_ASSERT_ALWAYS(aDevice->iReadUnitShift <= KPageShift);
  2429 	__NK_ASSERT_ALWAYS(aDevice->iReadUnitShift <= KPageShift);
  2410 
  2430 
  2411 	TInt r = KErrNotSupported;	// Will return this if unsupported device type is installed
  2431 	TInt r = KErrNotSupported;	// Will return this if unsupported device type is installed
  2412 
  2432 
  2413 	// create the pools of page out and page in requests...
  2433 	// create the pools of page out and page in requests...