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), |