kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp
branchRCL_3
changeset 39 2bb754abd467
parent 36 bbf8bed59bcb
child 41 0ffb4e86fcc9
equal deleted inserted replaced
36:bbf8bed59bcb 39:2bb754abd467
   456 		{
   456 		{
   457 		case SPageInfo::EPagedYoung:
   457 		case SPageInfo::EPagedYoung:
   458 		case SPageInfo::EPagedOld:
   458 		case SPageInfo::EPagedOld:
   459 		case SPageInfo::EPagedOldestClean:
   459 		case SPageInfo::EPagedOldestClean:
   460 		case SPageInfo::EPagedOldestDirty:
   460 		case SPageInfo::EPagedOldestDirty:
   461 			{// Update the list links point to the new page.
   461 			{// Update the list links to point to the new page.
   462 			__NK_ASSERT_DEBUG(iYoungCount);
       
   463 			SDblQueLink* prevLink = aOldPageInfo.iLink.iPrev;
   462 			SDblQueLink* prevLink = aOldPageInfo.iLink.iPrev;
   464 #ifdef _DEBUG
   463 #ifdef _DEBUG
   465 			SDblQueLink* nextLink = aOldPageInfo.iLink.iNext;
   464 			SDblQueLink* nextLink = aOldPageInfo.iLink.iNext;
   466 			__NK_ASSERT_DEBUG(prevLink == aOldPageInfo.iLink.iPrev);
   465 			__NK_ASSERT_DEBUG(prevLink == aOldPageInfo.iLink.iPrev);
   467 			__NK_ASSERT_DEBUG(prevLink->iNext == &aOldPageInfo.iLink);
   466 			__NK_ASSERT_DEBUG(prevLink->iNext == &aOldPageInfo.iLink);
   633 
   632 
   634 
   633 
   635 template <class T, TUint maxObjects> class TSequentialColourSelector
   634 template <class T, TUint maxObjects> class TSequentialColourSelector
   636 	{
   635 	{
   637 public:
   636 public:
   638 	static const TUint KMaxSearchLength = _ALIGN_UP(maxObjects, KPageColourCount);
   637 	enum
       
   638 		{
       
   639 		KMaxSearchLength = _ALIGN_UP(maxObjects, KPageColourCount)
       
   640 		};
   639 	
   641 	
   640 	FORCE_INLINE TSequentialColourSelector(TUint aTargetLength)
   642 	FORCE_INLINE TSequentialColourSelector(TUint aTargetLength)
   641 		{
   643 		{
   642 		memclr(this, sizeof(*this));
   644 		memclr(this, sizeof(*this));
   643 		__NK_ASSERT_DEBUG(aTargetLength <= maxObjects);
   645 		__NK_ASSERT_DEBUG(aTargetLength <= maxObjects);
  1107 		return EFalse;
  1109 		return EFalse;
  1108 		}
  1110 		}
  1109 	}
  1111 	}
  1110 
  1112 
  1111 
  1113 
       
  1114 TUint DPager::AllowAddFreePages(SPageInfo*& aPageInfo, TUint aNumPages)
       
  1115 	{
       
  1116 	if (iMinimumPageCount + iNumberOfFreePages == iMaximumPageCount)
       
  1117 		{// The paging cache is already at the maximum size so steal a page
       
  1118 		// so it can be returned to the system if required.
       
  1119 		aPageInfo = StealOrAllocPage(EFalse, (Mmu::TRamAllocFlags)0);
       
  1120 		__NK_ASSERT_DEBUG(aPageInfo->PagedState() == SPageInfo::EUnpaged);
       
  1121 		return 1;
       
  1122 		}
       
  1123 	// The paging cache is not at its maximum so determine how many can be added to
       
  1124 	// the paging cache without it growing past its maximum.
       
  1125 	aPageInfo = NULL;
       
  1126 	__NK_ASSERT_DEBUG(iMinimumPageCount + iNumberOfFreePages < iMaximumPageCount);
       
  1127 	if (iMinimumPageCount + iNumberOfFreePages + aNumPages > iMaximumPageCount)
       
  1128 		{
       
  1129 		return iMaximumPageCount - (iMinimumPageCount + iNumberOfFreePages);
       
  1130 		}
       
  1131 	else
       
  1132 		return aNumPages;
       
  1133 	}
       
  1134 
       
  1135 
       
  1136 void DPager::AllowAddFreePage(SPageInfo*& aPageInfo)
       
  1137 	{
       
  1138 	if (iMinimumPageCount + iNumberOfFreePages == iMaximumPageCount)
       
  1139 		{// The paging cache is already at the maximum size so steal a page
       
  1140 		// so it can be returned to the system if required.
       
  1141 		aPageInfo = StealOrAllocPage(EFalse, (Mmu::TRamAllocFlags)0);
       
  1142 		__NK_ASSERT_DEBUG(aPageInfo->PagedState() == SPageInfo::EUnpaged);
       
  1143 		return;
       
  1144 		}
       
  1145 	aPageInfo = NULL;
       
  1146 	}
       
  1147 
       
  1148 
  1112 void DPager::ReturnPageToSystem(SPageInfo& aPageInfo)
  1149 void DPager::ReturnPageToSystem(SPageInfo& aPageInfo)
  1113 	{
  1150 	{
  1114 	__NK_ASSERT_DEBUG(RamAllocLock::IsHeld());
  1151 	__NK_ASSERT_DEBUG(RamAllocLock::IsHeld());
  1115 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
  1152 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
  1116 
  1153 
  1184 	MmuLock::Lock();
  1221 	MmuLock::Lock();
  1185 
  1222 
  1186 	TPhysAddr* end = aPages+aCount;
  1223 	TPhysAddr* end = aPages+aCount;
  1187 	while(aPages<end)
  1224 	while(aPages<end)
  1188 		{
  1225 		{
       
  1226 		// Steal a page from the paging cache in case we need to return one to the system.
       
  1227 		// This may release the ram alloc lock.
       
  1228 		SPageInfo* pageInfo;
       
  1229 		AllowAddFreePage(pageInfo);
       
  1230 
  1189 		TPhysAddr pagePhys = *aPages++;
  1231 		TPhysAddr pagePhys = *aPages++;
  1190 		if(RPageArray::State(pagePhys)!=RPageArray::ECommitted)
  1232 		if(RPageArray::State(pagePhys)!=RPageArray::ECommitted)
       
  1233 			{
       
  1234 			if (pageInfo)
       
  1235 				AddAsFreePage(pageInfo);
  1191 			continue; // page is not present
  1236 			continue; // page is not present
       
  1237 			}
  1192 
  1238 
  1193 #ifdef _DEBUG
  1239 #ifdef _DEBUG
  1194 		SPageInfo* pi = SPageInfo::SafeFromPhysAddr(pagePhys&~KPageMask);
  1240 		SPageInfo* pi = SPageInfo::SafeFromPhysAddr(pagePhys&~KPageMask);
  1195 		__NK_ASSERT_DEBUG(pi);
  1241 		__NK_ASSERT_DEBUG(pi);
  1196 #else
  1242 #else
  1209 
  1255 
  1210 		case SPageInfo::EPagedYoung:
  1256 		case SPageInfo::EPagedYoung:
  1211 		case SPageInfo::EPagedOld:
  1257 		case SPageInfo::EPagedOld:
  1212 		case SPageInfo::EPagedOldestDirty:
  1258 		case SPageInfo::EPagedOldestDirty:
  1213 		case SPageInfo::EPagedOldestClean:
  1259 		case SPageInfo::EPagedOldestClean:
       
  1260 			if (pageInfo)
       
  1261 				AddAsFreePage(pageInfo);
  1214 			continue; // discard already been allowed
  1262 			continue; // discard already been allowed
  1215 
  1263 
  1216 		case SPageInfo::EPagedPinned:
  1264 		case SPageInfo::EPagedPinned:
  1217 			__NK_ASSERT_DEBUG(0);
  1265 			__NK_ASSERT_DEBUG(0);
  1218 		default:
  1266 		default:
  1219 			__NK_ASSERT_DEBUG(0);
  1267 			__NK_ASSERT_DEBUG(0);
       
  1268 			if (pageInfo)
       
  1269 				AddAsFreePage(pageInfo);
  1220 			continue;
  1270 			continue;
  1221 			}
  1271 			}
  1222 
  1272 
  1223 		// put page on live list...
  1273 		// put page on live list and free the stolen page...
  1224 		AddAsYoungestPage(pi);
  1274 		AddAsYoungestPage(pi);
  1225 		++iNumberOfFreePages;
  1275 		++iNumberOfFreePages;
  1226 
  1276 		if (pageInfo)
       
  1277 			ReturnPageToSystem(*pageInfo);
  1227 		Event(EEventPageDonate,pi);
  1278 		Event(EEventPageDonate,pi);
  1228 
  1279 
  1229 		// re-balance live list...
  1280 		// re-balance live list...
  1230 		RemoveExcessPages();
       
  1231 		BalanceAges();
  1281 		BalanceAges();
  1232 		}
  1282 		}
  1233 
  1283 
       
  1284 	__NK_ASSERT_DEBUG((iMinimumPageCount + iNumberOfFreePages) <= iMaximumPageCount);
  1234 	MmuLock::Unlock();
  1285 	MmuLock::Unlock();
  1235 	RamAllocLock::Unlock();
  1286 	RamAllocLock::Unlock();
  1236 	}
  1287 	}
  1237 
  1288 
  1238 
  1289 
  1280 			__NK_ASSERT_DEBUG(0);
  1331 			__NK_ASSERT_DEBUG(0);
  1281 			break;
  1332 			break;
  1282 			}
  1333 			}
  1283 
  1334 
  1284 		// check paging list has enough pages before we remove one...
  1335 		// check paging list has enough pages before we remove one...
  1285 		if(iNumberOfFreePages<1)
  1336 		if(!iNumberOfFreePages)
  1286 			{
  1337 			{
  1287 			// need more pages so get a page from the system...
  1338 			// need more pages so get a page from the system...
  1288 			if(!TryGrowLiveList())
  1339 			if(!TryGrowLiveList())
  1289 				{
  1340 				{
  1290 				// out of memory...
  1341 				// out of memory...
  1316 		BalanceAges();
  1367 		BalanceAges();
  1317 		}
  1368 		}
  1318 
  1369 
  1319 	// we may have added a spare free page to the live list without removing one,
  1370 	// we may have added a spare free page to the live list without removing one,
  1320 	// this could cause us to have too many pages, so deal with this...
  1371 	// this could cause us to have too many pages, so deal with this...
       
  1372 
       
  1373 	// If there are too many pages they should all be unused free pages otherwise 
       
  1374 	// the ram alloc lock may be released by RemoveExcessPages().
       
  1375 	__NK_ASSERT_DEBUG(	!HaveTooManyPages() ||
       
  1376 						(iMinimumPageCount + iNumberOfFreePages - iMaximumPageCount
       
  1377 						<= iOldestCleanCount));
  1321 	RemoveExcessPages();
  1378 	RemoveExcessPages();
  1322 
  1379 
       
  1380 	__NK_ASSERT_DEBUG((iMinimumPageCount + iNumberOfFreePages) <= iMaximumPageCount);
  1323 	MmuLock::Unlock();
  1381 	MmuLock::Unlock();
  1324 	RamAllocLock::Unlock();
  1382 	RamAllocLock::Unlock();
  1325 	return r;
  1383 	return r;
  1326 	}
  1384 	}
  1327 
  1385 
  1881 			break;
  1939 			break;
  1882 			}
  1940 			}
  1883 		}
  1941 		}
  1884 	while(TryGrowLiveList());
  1942 	while(TryGrowLiveList());
  1885 
  1943 
       
  1944 	if (!ok)
       
  1945 		{// Failed to allocate enough pages so free any excess..
       
  1946 
       
  1947 		// If there are too many pages they should all be unused free pages otherwise 
       
  1948 		// the ram alloc lock may be released by RemoveExcessPages().
       
  1949 		__NK_ASSERT_DEBUG(	!HaveTooManyPages() ||
       
  1950 							(iMinimumPageCount + iNumberOfFreePages - iMaximumPageCount
       
  1951 							<= iOldestCleanCount));
       
  1952 		RemoveExcessPages();
       
  1953 		}
       
  1954 	__NK_ASSERT_DEBUG((iMinimumPageCount + iNumberOfFreePages) <= iMaximumPageCount);
  1886 	MmuLock::Unlock();
  1955 	MmuLock::Unlock();
  1887 	RamAllocLock::Unlock();
  1956 	RamAllocLock::Unlock();
  1888 	return ok;
  1957 	return ok;
  1889 	}
  1958 	}
  1890 
  1959 
  1895 	__ASSERT_CRITICAL;
  1964 	__ASSERT_CRITICAL;
  1896 
  1965 
  1897 	RamAllocLock::Lock();
  1966 	RamAllocLock::Lock();
  1898 	MmuLock::Lock();
  1967 	MmuLock::Lock();
  1899 
  1968 
  1900 	iNumberOfFreePages += aNumPages;
  1969 	while (aNumPages)
  1901 	RemoveExcessPages();
  1970 		{
  1902 
  1971 		SPageInfo* pageInfo;
       
  1972 		// This may release the ram alloc lock but it will flash the mmulock
       
  1973 		// if not all pages could be added in one go, i.e. freePages != aNumPages.
       
  1974 		TUint freePages = AllowAddFreePages(pageInfo, aNumPages);
       
  1975 		iNumberOfFreePages += freePages;
       
  1976 		aNumPages -= freePages;
       
  1977 		if (pageInfo)
       
  1978 			ReturnPageToSystem(*pageInfo);
       
  1979 		}
       
  1980 
       
  1981 	__NK_ASSERT_DEBUG((iMinimumPageCount + iNumberOfFreePages) <= iMaximumPageCount);
  1903 	MmuLock::Unlock();
  1982 	MmuLock::Unlock();
  1904 	RamAllocLock::Unlock();
  1983 	RamAllocLock::Unlock();
  1905 	}
  1984 	}
  1906 
  1985 
  1907 
  1986 
  2052 		}
  2131 		}
  2053 	if (aMaximumPageCount > KAbsoluteMaxPageCount)
  2132 	if (aMaximumPageCount > KAbsoluteMaxPageCount)
  2054 		aMaximumPageCount = KAbsoluteMaxPageCount;
  2133 		aMaximumPageCount = KAbsoluteMaxPageCount;
  2055 
  2134 
  2056 	// Min must not be greater than max...
  2135 	// Min must not be greater than max...
  2057 	if(aMinimumPageCount>aMaximumPageCount)
  2136 	if(aMinimumPageCount > aMaximumPageCount)
  2058 		return KErrArgument;
  2137 		return KErrArgument;
  2059 	
  2138 	
  2060 	NKern::ThreadEnterCS();
  2139 	NKern::ThreadEnterCS();
  2061 	RamAllocLock::Lock();
  2140 	RamAllocLock::Lock();
  2062 
  2141 
  2070 	__NK_ASSERT_ALWAYS(iYoungOldRatio);
  2149 	__NK_ASSERT_ALWAYS(iYoungOldRatio);
  2071 
  2150 
  2072 	// Make sure aMinimumPageCount is not less than absolute minimum we can cope with...
  2151 	// Make sure aMinimumPageCount is not less than absolute minimum we can cope with...
  2073 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
  2152 	iMinimumPageLimit = iMinYoungPages * (1 + iYoungOldRatio) / iYoungOldRatio
  2074 						+ DPageReadRequest::ReservedPagesRequired();
  2153 						+ DPageReadRequest::ReservedPagesRequired();
  2075 	if(iMinimumPageLimit<iAbsoluteMinPageCount)
  2154 	if(iMinimumPageLimit < iAbsoluteMinPageCount)
  2076 		iMinimumPageLimit = iAbsoluteMinPageCount;
  2155 		iMinimumPageLimit = iAbsoluteMinPageCount;
  2077 	if(aMinimumPageCount<iMinimumPageLimit+iReservePageCount)
  2156 	if(aMinimumPageCount < iMinimumPageLimit + iReservePageCount)
  2078 		aMinimumPageCount = iMinimumPageLimit+iReservePageCount;
  2157 		aMinimumPageCount = iMinimumPageLimit + iReservePageCount;
  2079 	if(aMaximumPageCount<aMinimumPageCount)
  2158 	if(aMaximumPageCount < aMinimumPageCount)
  2080 		aMaximumPageCount=aMinimumPageCount;
  2159 		aMaximumPageCount = aMinimumPageCount;
  2081 
  2160 
  2082 	// Increase iMaximumPageCount?
  2161 	// Increase iMaximumPageCount?
  2083 	if(aMaximumPageCount > iMaximumPageCount)
  2162 	if(aMaximumPageCount > iMaximumPageCount)
  2084 		iMaximumPageCount = aMaximumPageCount;
  2163 		iMaximumPageCount = aMaximumPageCount;
  2085 
  2164 
  2089 		iNumberOfFreePages += iMinimumPageCount - aMinimumPageCount;
  2168 		iNumberOfFreePages += iMinimumPageCount - aMinimumPageCount;
  2090 		iMinimumPageCount = aMinimumPageCount;
  2169 		iMinimumPageCount = aMinimumPageCount;
  2091 		}
  2170 		}
  2092 
  2171 
  2093 	// Increase iMinimumPageCount?
  2172 	// Increase iMinimumPageCount?
  2094 	TInt r=KErrNone;
  2173 	TInt r = KErrNone;
  2095 	while(aMinimumPageCount > iMinimumPageCount)
  2174 	while(aMinimumPageCount > iMinimumPageCount)
  2096 		{
  2175 		{
  2097 		TUint newMin = MinU(aMinimumPageCount, iMinimumPageCount + iNumberOfFreePages);
  2176 		TUint newMin = MinU(aMinimumPageCount, iMinimumPageCount + iNumberOfFreePages);
  2098 		
  2177 		
  2099 		if (newMin == iMinimumPageCount)
  2178 		if (newMin == iMinimumPageCount)
  2100 			{
  2179 			{
  2101 			// have to add pages before we can increase minimum page count
  2180 			// have to add pages before we can increase minimum page count
  2102 			if(!TryGrowLiveList())
  2181 			if(!TryGrowLiveList())
  2103 				{
  2182 				{
  2104 				r=KErrNoMemory;
  2183 				r = KErrNoMemory;
  2105 				break;
  2184 				break;
  2106 				}
  2185 				}
  2107 			}
  2186 			}
  2108 		else
  2187 		else
  2109 			{
  2188 			{