|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 // INCLUDES |
|
21 |
|
22 #include <e32base.h> |
|
23 #include <e32std.h> |
|
24 #include <e32hal.h> |
|
25 #include "MemoryPool.h" |
|
26 #include "StopScheduler.h" |
|
27 #include "fast_malloc.h" |
|
28 #include <OOMMonitorSession.h> |
|
29 |
|
30 // CONSTANTS |
|
31 |
|
32 // CLASS DECLARATIONS |
|
33 |
|
34 //----------------------------------------------------------------------------- |
|
35 // CMemoryPool::AddCollector |
|
36 //----------------------------------------------------------------------------- |
|
37 void CMemoryPool::AddCollector( MMemoryCollector* aCollector ) |
|
38 { |
|
39 // sort the collectors according to their priorities |
|
40 TInt i; |
|
41 for( i=0; i<iCollectors.Count(); ++i ) |
|
42 { |
|
43 if( aCollector->Priority() <= iCollectors[i]->Priority() ) break; |
|
44 } |
|
45 |
|
46 iCollectors.Insert( aCollector, i ); |
|
47 } |
|
48 |
|
49 //----------------------------------------------------------------------------- |
|
50 // CMemoryPool::RemoveCollector |
|
51 //----------------------------------------------------------------------------- |
|
52 void CMemoryPool::RemoveCollector( MMemoryCollector* aCollector ) |
|
53 { |
|
54 TInt idx = iCollectors.Find( aCollector ); |
|
55 if( idx != KErrNotFound ) |
|
56 iCollectors.Remove( idx ); |
|
57 } |
|
58 |
|
59 //----------------------------------------------------------------------------- |
|
60 // CMemoryPool::AddStopper |
|
61 //----------------------------------------------------------------------------- |
|
62 void CMemoryPool::AddStopper( MOOMStopper* aStopper ) |
|
63 { |
|
64 if( !iStopScheduler ) |
|
65 iStopScheduler = new CStopScheduler(*this); |
|
66 iStoppers.Append( aStopper ); |
|
67 } |
|
68 |
|
69 //----------------------------------------------------------------------------- |
|
70 // CMemoryPool::RemoveStopper |
|
71 //----------------------------------------------------------------------------- |
|
72 void CMemoryPool::RemoveStopper( MOOMStopper* aStopper ) |
|
73 { |
|
74 if( !iStopScheduler ) return; |
|
75 TInt idx = iStoppers.Find( aStopper ); |
|
76 if( idx != KErrNotFound ) |
|
77 iStoppers.Remove( idx ); |
|
78 } |
|
79 |
|
80 //----------------------------------------------------------------------------- |
|
81 // CMemoryPool::SetNotifier |
|
82 //----------------------------------------------------------------------------- |
|
83 void CMemoryPool::SetNotifier( MOOMNotifier* aNotifier ) |
|
84 { |
|
85 iNotifier = aNotifier; |
|
86 } |
|
87 |
|
88 //----------------------------------------------------------------------------- |
|
89 // CMemoryPool::Create() |
|
90 //----------------------------------------------------------------------------- |
|
91 TBool CMemoryPool::Create() |
|
92 { |
|
93 iNestedChecks = 0; |
|
94 |
|
95 iCollectors.Reset(); |
|
96 iIsStopping = EFalse; |
|
97 iIsCollecting = EFalse; |
|
98 iMemStatus = ENoOOM; |
|
99 |
|
100 // stop scheduler |
|
101 iStopScheduler = 0; |
|
102 iNotifier = 0; |
|
103 |
|
104 return ETrue; |
|
105 } |
|
106 |
|
107 |
|
108 //----------------------------------------------------------------------------- |
|
109 // CMemoryPool::SetStopping |
|
110 //----------------------------------------------------------------------------- |
|
111 void CMemoryPool::SetStopping( TBool aStopping ) |
|
112 { |
|
113 iIsStopping = aStopping; |
|
114 // all operations are stopped, must have some memory available |
|
115 if( !iIsStopping ) iMemStatus = ENoOOM; |
|
116 |
|
117 // notify the client when stopping is done |
|
118 if( !aStopping && iNotifier ) |
|
119 { |
|
120 iNotifier->Notify(); |
|
121 } |
|
122 } |
|
123 |
|
124 //----------------------------------------------------------------------------- |
|
125 // CMemoryPool::CollectMemory |
|
126 //----------------------------------------------------------------------------- |
|
127 void CMemoryPool::CollectMemory(TUint aSize) |
|
128 { |
|
129 if( iIsCollecting ) return; |
|
130 |
|
131 iIsCollecting = ETrue; |
|
132 for( TInt i=0; i<iCollectors.Count(); ++i ) |
|
133 { |
|
134 iCollectors[i]->Collect(aSize); |
|
135 } |
|
136 |
|
137 User::CompressAllHeaps(); |
|
138 iIsCollecting = EFalse; |
|
139 |
|
140 if (iStopScheduler) |
|
141 iStopScheduler->Start( CStopScheduler::ECheckMemory, aSize ); |
|
142 } |
|
143 |
|
144 //----------------------------------------------------------------------------- |
|
145 // CMemoryPool::RestoreCollectors |
|
146 //----------------------------------------------------------------------------- |
|
147 void CMemoryPool::RestoreCollectors( TOOMPriority aPriority ) |
|
148 { |
|
149 if( iIsCollecting ) return; |
|
150 |
|
151 for( TInt i=0; i<iCollectors.Count(); ++i ) |
|
152 { |
|
153 if( iCollectors[i]->Priority() >= aPriority ) |
|
154 iCollectors[i]->Restore(); |
|
155 } |
|
156 } |
|
157 |
|
158 //----------------------------------------------------------------------------- |
|
159 // CMemoryPool::~CMemoryPool |
|
160 //----------------------------------------------------------------------------- |
|
161 CMemoryPool::~CMemoryPool() |
|
162 { |
|
163 iCollectors.Reset(); |
|
164 iStoppers.Reset(); |
|
165 delete iStopScheduler; |
|
166 |
|
167 // NOTE: remove this when UI spec has OOM notifier defined |
|
168 delete iNotifier; |
|
169 } |
|
170 |
|
171 //----------------------------------------------------------------------------- |
|
172 // CMemoryPool::AllocFromPool |
|
173 //----------------------------------------------------------------------------- |
|
174 TAny* CMemoryPool::AllocFromPool( TUint aSize ) |
|
175 { |
|
176 // reset the status for next allocation |
|
177 iMemStatus &= ~ERescueOOM; |
|
178 |
|
179 TAny *p = DoAlloc( aSize ); |
|
180 |
|
181 // check memory manager status |
|
182 if( !p || iMemStatus & ERescueOOM ) |
|
183 { |
|
184 if( !iIsCollecting ) |
|
185 { |
|
186 CollectMemory(); |
|
187 } |
|
188 |
|
189 if( !p ) |
|
190 p = DoAlloc( aSize ); |
|
191 |
|
192 NotifyAndStop(); |
|
193 } |
|
194 |
|
195 return p; |
|
196 } |
|
197 |
|
198 //----------------------------------------------------------------------------- |
|
199 // CMemoryPool::SetStatus |
|
200 //----------------------------------------------------------------------------- |
|
201 void CMemoryPool::SetStatus( TOOMCheckResult aType ) |
|
202 { |
|
203 iMemStatus |= aType; |
|
204 } |
|
205 |
|
206 //----------------------------------------------------------------------------- |
|
207 // CMemoryPool::NotifyAndStop() |
|
208 //----------------------------------------------------------------------------- |
|
209 void CMemoryPool::NotifyAndStop() |
|
210 { |
|
211 if( !iIsStopping ) |
|
212 { |
|
213 iIsStopping = ETrue; |
|
214 if (iStopScheduler) |
|
215 iStopScheduler->Start( CStopScheduler::EStopLoading, 0 ); |
|
216 } |
|
217 } |
|
218 |
|
219 //----------------------------------------------------------------------------- |
|
220 // CPlainAllocator::DoAlloc |
|
221 //----------------------------------------------------------------------------- |
|
222 TUint CFastMemoryPool::FreeMemory(TFreeMem& aFree ) |
|
223 { |
|
224 return free_memory( aFree.iPool, aFree.iHeap, aFree.iHal ); |
|
225 } |
|
226 |
|
227 //----------------------------------------------------------------------------- |
|
228 // CFastMemoryPool::DoAlloc |
|
229 //----------------------------------------------------------------------------- |
|
230 TAny* CFastMemoryPool::DoAlloc( TUint aSize ) |
|
231 { |
|
232 return fast_malloc( aSize ); |
|
233 } |
|
234 |
|
235 //----------------------------------------------------------------------------- |
|
236 // CFastMemoryPool::ReAllocate |
|
237 //----------------------------------------------------------------------------- |
|
238 TAny* CFastMemoryPool::ReAllocate( TAny* aPtr, TUint aSize ) |
|
239 { |
|
240 // reset the status for next allocation |
|
241 iMemStatus &= ~ERescueOOM; |
|
242 |
|
243 TAny* p = fast_realloc( aPtr, aSize ); |
|
244 |
|
245 // check memory manager status |
|
246 if( !p || iMemStatus & ERescueOOM ) |
|
247 { |
|
248 if( !iIsCollecting ) |
|
249 { |
|
250 CollectMemory(); |
|
251 } |
|
252 |
|
253 if( !p ) |
|
254 p = fast_realloc( aPtr, aSize ); |
|
255 |
|
256 NotifyAndStop(); |
|
257 } |
|
258 |
|
259 return p; |
|
260 } |
|
261 |
|
262 //----------------------------------------------------------------------------- |
|
263 // CFastMemoryPool::PreCheck |
|
264 //----------------------------------------------------------------------------- |
|
265 TBool CFastMemoryPool::PreCheck( TUint aTotalSize, TUint aMaxBufSize, const TDesC8& /*aCheckerName*/ ) |
|
266 { |
|
267 // avoid small checkings |
|
268 if( aTotalSize < 1024 ) return ETrue; |
|
269 |
|
270 if( !fast_pre_check( aTotalSize, aMaxBufSize ) ) |
|
271 { |
|
272 CollectMemory(aTotalSize); |
|
273 ROomMonitorSession oomMs; |
|
274 if ( oomMs.Connect() == KErrNone ) { |
|
275 oomMs.RequestFreeMemory( aTotalSize ); |
|
276 oomMs.Close(); |
|
277 } |
|
278 if( !fast_pre_check( aTotalSize, aMaxBufSize ) ) |
|
279 { |
|
280 iMemStatus |= ECheckOOM; |
|
281 NotifyAndStop(); |
|
282 return EFalse; |
|
283 } |
|
284 } |
|
285 |
|
286 return ETrue; |
|
287 } |
|
288 |
|
289 //----------------------------------------------------------------------------- |
|
290 // CMemoryPool::PostCheck |
|
291 //----------------------------------------------------------------------------- |
|
292 TUint CFastMemoryPool::PostCheck() |
|
293 { |
|
294 fast_post_check(); |
|
295 return iMemStatus; |
|
296 } |
|
297 |
|
298 //----------------------------------------------------------------------------- |
|
299 // CPlainAllocator::Free |
|
300 //----------------------------------------------------------------------------- |
|
301 void CFastMemoryPool::Free( TAny* aPtr ) |
|
302 { |
|
303 return fast_free( aPtr ); |
|
304 } |
|
305 |
|
306 //----------------------------------------------------------------------------- |
|
307 // CPlainAllocator::MemorySize |
|
308 //----------------------------------------------------------------------------- |
|
309 TUint CFastMemoryPool::MemorySize( TAny* aPtr ) |
|
310 { |
|
311 return fast_malloc_size( aPtr ); |
|
312 } |
|
313 |
|
314 //----------------------------------------------------------------------------- |
|
315 // CPlainAllocator::SetRescueBufferSize |
|
316 //----------------------------------------------------------------------------- |
|
317 void CFastMemoryPool::SetRescueBufferSize( TInt aSize ) |
|
318 { |
|
319 fast_set_rescue_buffer_size( aSize ); |
|
320 } |
|
321 |
|
322 void CFastMemoryPool::RestoreRescueBuffer() |
|
323 { |
|
324 alloc_rescue_buffer(); |
|
325 } |
|
326 |
|
327 //----------------------------------------------------------------------------- |
|
328 // CDefaultMemoryPool::~CDefaultMemoryPool |
|
329 //----------------------------------------------------------------------------- |
|
330 CDefaultMemoryPool::~CDefaultMemoryPool() |
|
331 { |
|
332 } |
|
333 |
|
334 //----------------------------------------------------------------------------- |
|
335 // CDefaultMemoryPool::DoAlloc |
|
336 //----------------------------------------------------------------------------- |
|
337 TAny* CDefaultMemoryPool::DoAlloc(TUint aSize) |
|
338 { |
|
339 return User::Alloc( aSize ); |
|
340 } |
|
341 |
|
342 //----------------------------------------------------------------------------- |
|
343 // CDefaultMemoryPool::ReAllocate |
|
344 //----------------------------------------------------------------------------- |
|
345 TAny* CDefaultMemoryPool::ReAllocate( TAny* aPtr, TUint aSize ) |
|
346 { |
|
347 return User::ReAlloc( aPtr, aSize ); |
|
348 } |
|
349 |
|
350 //----------------------------------------------------------------------------- |
|
351 // CDefaultMemoryPool::FreeMemory |
|
352 //----------------------------------------------------------------------------- |
|
353 TUint CDefaultMemoryPool::FreeMemory(TFreeMem& /*aFree*/) |
|
354 { |
|
355 // free memory in Hal |
|
356 TMemoryInfoV1Buf info; |
|
357 UserHal::MemoryInfo( info ); |
|
358 return info().iFreeRamInBytes; |
|
359 } |
|
360 |
|
361 //----------------------------------------------------------------------------- |
|
362 // CDefaultMemoryPool::Free |
|
363 //----------------------------------------------------------------------------- |
|
364 void CDefaultMemoryPool::Free(TAny* aPtr) |
|
365 { |
|
366 User::Free( aPtr ); |
|
367 } |
|
368 |
|
369 //----------------------------------------------------------------------------- |
|
370 // CDefaultMemoryPool::MemorySize |
|
371 //----------------------------------------------------------------------------- |
|
372 TUint CDefaultMemoryPool::MemorySize(TAny* aPtr) |
|
373 { |
|
374 return User::AllocLen( aPtr ); |
|
375 } |
|
376 |
|
377 //----------------------------------------------------------------------------- |
|
378 // CDefaultMemoryPool::SetRescueBufferSize |
|
379 //----------------------------------------------------------------------------- |
|
380 void CDefaultMemoryPool::SetRescueBufferSize( TInt aSize ) |
|
381 { |
|
382 iRescueBufferSize = aSize; |
|
383 } |
|
384 |
|
385 //----------------------------------------------------------------------------- |
|
386 // CDefaultMemoryPool::PreCheck |
|
387 //----------------------------------------------------------------------------- |
|
388 TBool CDefaultMemoryPool::PreCheck( TUint aTotalSize, TUint /*aMaxBufSize*/, const TDesC8& /*aCheckerName*/ ) |
|
389 { |
|
390 // avoid small checkings |
|
391 if( aTotalSize < 1024 ) return ETrue; |
|
392 |
|
393 // free memory in Hal |
|
394 TMemoryInfoV1Buf info; |
|
395 UserHal::MemoryInfo( info ); |
|
396 TInt sizeNeeded = aTotalSize + iRescueBufferSize; |
|
397 if( sizeNeeded > info().iFreeRamInBytes ) |
|
398 { |
|
399 CollectMemory(sizeNeeded); |
|
400 |
|
401 // check memory again |
|
402 UserHal::MemoryInfo( info ); |
|
403 |
|
404 if(sizeNeeded > info().iFreeRamInBytes ) |
|
405 { |
|
406 NotifyAndStop(); |
|
407 iMemStatus |= ECheckOOM; |
|
408 return EFalse; |
|
409 } |
|
410 } |
|
411 |
|
412 return ETrue; |
|
413 } |
|
414 |
|
415 //----------------------------------------------------------------------------- |
|
416 // CDefaultMemoryPool::PostCheck |
|
417 //----------------------------------------------------------------------------- |
|
418 TUint CDefaultMemoryPool::PostCheck() |
|
419 { |
|
420 return iMemStatus; |
|
421 } |
|
422 |
|
423 void CDefaultMemoryPool::RestoreRescueBuffer() |
|
424 { |
|
425 // do nothing here. |
|
426 } |
|
427 |
|
428 // END OF FILE |