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 { |