|
1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\common\alloc.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "common.h" |
|
19 #include <e32atomics.h> |
|
20 |
|
21 |
|
22 |
|
23 #ifndef __KERNEL_MODE__ |
|
24 /** |
|
25 Opens this heap for shared access. |
|
26 |
|
27 Opening the heap increases the heap's access count by one. |
|
28 |
|
29 @return KErrNone if successful; |
|
30 KErrGeneral, if the original valeu of the access count |
|
31 was not positive. |
|
32 */ |
|
33 EXPORT_C TInt RAllocator::Open() |
|
34 { |
|
35 TInt c = __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0); |
|
36 return (c>0) ? KErrNone : KErrGeneral; |
|
37 } |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 /** |
|
43 Closes this shared heap. |
|
44 |
|
45 Closing the heap decreases the heap's access count by one. |
|
46 |
|
47 @panic USER 57 if the access count has already reached zero. |
|
48 */ |
|
49 EXPORT_C void RAllocator::Close() |
|
50 { |
|
51 TInt count = __e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0); |
|
52 __ASSERT_ALWAYS(count>0, Panic(EAllocatorClosedTooManyTimes)); |
|
53 if (count==1) |
|
54 DoClose(); |
|
55 } |
|
56 |
|
57 |
|
58 |
|
59 /** |
|
60 @internalComponent |
|
61 */ |
|
62 EXPORT_C void RAllocator::DoClose() |
|
63 { |
|
64 __ASSERT_ALWAYS(TUint32(iHandleCount)<=TUint32(EMaxHandles), Panic(EAllocatorBadHandleCount)); |
|
65 TInt handle[EMaxHandles]; |
|
66 TInt c = iHandleCount; |
|
67 wordmove(handle, iHandles, c*sizeof(TInt)); |
|
68 memclr(iHandles, c*sizeof(TInt)); |
|
69 TInt* pH = handle; |
|
70 TInt* pE = pH + c; |
|
71 while (pH<pE) |
|
72 { |
|
73 RHandleBase h; |
|
74 h.SetHandle(*pH++); |
|
75 h.Close(); |
|
76 } |
|
77 } |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 /** |
|
83 Allocates a cell of specified size from the heap, and clears |
|
84 it to binary zeroes. |
|
85 |
|
86 If there is insufficient memory available on the heap from which to |
|
87 allocate a cell of the required size, the function returns NULL. |
|
88 |
|
89 The resulting size of the allocated cell may be rounded up to a value greater |
|
90 than aSize, but is guaranteed to be not less than aSize. |
|
91 |
|
92 @param aSize The size of the cell to be allocated from the current thread's |
|
93 heap. |
|
94 |
|
95 @return A pointer to the allocated cell. NULL, if there is insufficient memory |
|
96 available. |
|
97 |
|
98 @panic USER 47 if the maximum unsigned value of aSize is greater |
|
99 than or equal to KMaxTInt/2. For example, |
|
100 calling Alloc(-1) raises this panic. |
|
101 */ |
|
102 EXPORT_C TAny* RAllocator::AllocZ(TInt aSize) |
|
103 { |
|
104 TAny* p = Alloc(aSize); |
|
105 if (p) |
|
106 Mem::FillZ(p, aSize); |
|
107 return p; |
|
108 } |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 /** |
|
114 Allocates a cell of specified size from the heap, clears it to |
|
115 binary zeroes, and leaves if there is insufficient memory in the heap. |
|
116 |
|
117 The resulting size of the allocated cell may be rounded up to a value greater |
|
118 than aSize, but is guaranteed to be not less than aSize. |
|
119 |
|
120 @param aSize The size of the cell to be allocated from the heap. |
|
121 |
|
122 @return A pointer to the allocated cell. |
|
123 |
|
124 @panic USER 47 if the maximum unsigned value of aSize is greater |
|
125 than or equal to KMaxTInt/2. For example, |
|
126 calling Alloc(-1) raises this panic. |
|
127 */ |
|
128 EXPORT_C TAny* RAllocator::AllocZL(TInt aSize) |
|
129 { |
|
130 TAny* p = AllocL(aSize); |
|
131 Mem::FillZ(p, aSize); |
|
132 return p; |
|
133 } |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 /** |
|
139 Allocates a cell of specified size from the heap, and leaves |
|
140 if there is insufficient memory in the heap. |
|
141 |
|
142 The resulting size of the allocated cell may be rounded up to a value greater |
|
143 than aSize, but is guaranteed to be not less than aSize. |
|
144 |
|
145 @param aSize The size of the cell to be allocated from the heap. |
|
146 |
|
147 @return A pointer to the allocated cell. |
|
148 |
|
149 @panic USER 47 if the maximum unsigned value of aSize is greater |
|
150 than or equal to KMaxTInt/2. For example, |
|
151 calling Alloc(-1) raises this panic. |
|
152 */ |
|
153 EXPORT_C TAny* RAllocator::AllocL(TInt aSize) |
|
154 { |
|
155 TAny* p = Alloc(aSize); |
|
156 if (!p) |
|
157 User::LeaveNoMemory(); |
|
158 return p; |
|
159 } |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 /** |
|
165 Allocates a cell of specified size from the heap, and, |
|
166 if successful, places a pointer to the cell onto the cleanup stack. |
|
167 |
|
168 The function leaves if there is insufficient memory in the heap. |
|
169 |
|
170 The resulting size of the allocated cell may be rounded up to a value greater |
|
171 than aSize, but is guaranteed to be not less than aSize. |
|
172 |
|
173 @param aSize The size of the cell to be allocated from the heap. |
|
174 |
|
175 @return A pointer to the allocated cell. |
|
176 |
|
177 @panic USER 47 if the maximum unsigned value of aSize is greater |
|
178 than or equal to KMaxTInt/2. For example, |
|
179 calling Alloc(-1) raises this panic. |
|
180 */ |
|
181 EXPORT_C TAny* RAllocator::AllocLC(TInt aSize) |
|
182 { |
|
183 TAny* p = AllocL(aSize); |
|
184 CleanupStack::PushL(p); |
|
185 return p; |
|
186 } |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 /** |
|
192 Frees the specified cell, returns it to the heap, and resets |
|
193 the pointer to NULL. |
|
194 |
|
195 @param aCell A reference to a pointer to a valid cell to be freed. If NULL |
|
196 this function call will be ignored. |
|
197 |
|
198 @panic USER 42 if aCell is not NULL and does not point to a valid cell. |
|
199 */ |
|
200 EXPORT_C void RAllocator::FreeZ(TAny*& aCell) |
|
201 { |
|
202 Free(aCell); |
|
203 aCell = NULL; |
|
204 } |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 /** |
|
210 Increases or decreases the size of an existing cell, and leaves |
|
211 if there is insufficient memory in the heap. |
|
212 |
|
213 If the cell is being decreased in size, then it is guaranteed not to move, |
|
214 and the function returns the pointer originally passed in aCell. Note that the |
|
215 length of the cell will be the same if the difference between the old size |
|
216 and the new size is smaller than the minimum cell size. |
|
217 |
|
218 If the cell is being increased in size, i.e. aSize is bigger than its |
|
219 current size, then the function tries to grow the cell in place. |
|
220 If successful, then the function returns the pointer originally |
|
221 passed in aCell. If unsuccessful, then: |
|
222 |
|
223 1. if the cell cannot be moved, i.e. aMode has the ENeverMove bit set, then |
|
224 the function leaves. |
|
225 2. if the cell can be moved, i.e. aMode does not have the ENeverMove bit set, |
|
226 then the function tries to allocate a new replacement cell, and, if |
|
227 successful, returns a pointer to the new cell; if unsuccessful, it |
|
228 leaves. |
|
229 |
|
230 Note that in debug mode, the function leaves if the cell cannot be grown |
|
231 in place, regardless of whether the ENeverMove bit is set. |
|
232 |
|
233 If the reallocated cell is at a different location from the original cell, then |
|
234 the content of the original cell is copied to the reallocated cell. |
|
235 |
|
236 Note the following general points: |
|
237 |
|
238 1. If reallocation fails, the content of the original cell is preserved. |
|
239 |
|
240 2. The resulting size of the re-allocated cell may be rounded up to a value |
|
241 greater than aSize, but is guaranteed to be not less than aSize. |
|
242 |
|
243 @param aCell A pointer to the cell to be reallocated. This may be NULL. |
|
244 |
|
245 @param aSize The new size of the cell. This may be bigger or smaller than the |
|
246 size of the original cell. |
|
247 |
|
248 @param aMode Flags controlling the reallocation. The only bit which has any |
|
249 effect on this function is that defined by the enumeration |
|
250 ENeverMove of the enum RAllocator::TReAllocMode. |
|
251 If this is set, then any successful reallocation guarantees not |
|
252 to have changed the start address of the cell. |
|
253 By default, this parameter is zero. |
|
254 |
|
255 @return A pointer to the reallocated cell. This may be the same as the original |
|
256 pointer supplied through aCell. |
|
257 |
|
258 @panic USER 42, if aCell is not NULL, and does not point to a valid cell. |
|
259 @panic USER 47, if the maximum unsigned value of aSize is greater |
|
260 than or equal to KMaxTInt/2. For example, |
|
261 calling ReAlloc(someptr,-1) raises this panic. |
|
262 |
|
263 @see RAllocator::TReAllocMode |
|
264 */ |
|
265 EXPORT_C TAny* RAllocator::ReAllocL(TAny* aCell, TInt aSize, TInt aMode) |
|
266 { |
|
267 TAny* p = ReAlloc(aCell, aSize, aMode); |
|
268 if (!p) |
|
269 User::LeaveNoMemory(); |
|
270 return p; |
|
271 } |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 /** |
|
277 Gets the total number of cells allocated on the heap. |
|
278 |
|
279 @return The number of cells allocated on the heap. |
|
280 */ |
|
281 EXPORT_C TInt RAllocator::Count() const |
|
282 { |
|
283 return iCellCount; |
|
284 } |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 /** |
|
290 Gets the the total number of cells allocated, and the number of free cells, |
|
291 on the heap. |
|
292 |
|
293 @param aFreeCount On return, contains the number of free cells |
|
294 on the heap. |
|
295 |
|
296 @return The number of cells allocated on the heap. |
|
297 */ |
|
298 EXPORT_C TInt RAllocator::Count(TInt& aFreeCount) const |
|
299 { |
|
300 return ((RAllocator*)this)->DebugFunction(ECount, &aFreeCount); |
|
301 } |
|
302 #endif |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 /** |
|
308 Checks the validity of the heap. |
|
309 |
|
310 The function walks through the list of allocated cells and the list of |
|
311 free cells checking that this heap is consistent and complete. |
|
312 |
|
313 @panic USER 47 if any corruption is found, specifically a bad allocated |
|
314 heap cell size. |
|
315 @panic USER 48 if any corruption is found, specifically a bad allocated |
|
316 heap cell address. |
|
317 @panic USER 49 if any corruption is found, specifically a bad free heap |
|
318 cell address. |
|
319 */ |
|
320 UEXPORT_C void RAllocator::Check() const |
|
321 { |
|
322 ((RAllocator*)this)->DebugFunction(ECheck); |
|
323 } |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 /** |
|
329 Marks the start of heap cell checking for this heap. |
|
330 |
|
331 If earlier calls to __DbgMarkStart() have been made, then this call |
|
332 to __DbgMarkStart() marks the start of a new nested level of |
|
333 heap cell checking. |
|
334 |
|
335 Every call to __DbgMarkStart() should be matched by a later call |
|
336 to __DbgMarkEnd() to verify that the number of heap cells allocated, |
|
337 at the current nested level, is as expected. This expected number of heap cells |
|
338 is passed to __DbgMarkEnd() as a parameter; however, the most common expected |
|
339 number is zero, reflecting the fact that most developers check that all memory |
|
340 allocated since a previous call to __DbgMarkStart() has been freed. |
|
341 |
|
342 @see RAllocator::__DbgMarkEnd() |
|
343 */ |
|
344 UEXPORT_C void RAllocator::__DbgMarkStart() |
|
345 { |
|
346 DebugFunction(EMarkStart); |
|
347 } |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 /** |
|
353 Marks the end of heap cell checking at the current nested level for this heap. |
|
354 |
|
355 A call to this function should match an earlier call to __DbgMarkStart(). |
|
356 If there are more calls to this function than calls to __DbgMarkStart(), |
|
357 then this function raises a USER 51 panic. |
|
358 |
|
359 The function checks that the number of heap cells allocated, at the current |
|
360 nested level, is aCount. The most common value for aCount is zero, reflecting |
|
361 the fact that most developers check that all memory allocated since a previous |
|
362 call to __DbgMarkStart() has been freed. |
|
363 |
|
364 If the check fails, the function returns a pointer to the first orphaned |
|
365 heap cell. |
|
366 |
|
367 @param aCount The number of allocated heap cells expected. |
|
368 |
|
369 @return A pointer to the first orphaned heap cell, if verification fails; |
|
370 zero otherwise. |
|
371 |
|
372 @see RAllocator::__DbgMarkStart() |
|
373 */ |
|
374 UEXPORT_C TUint32 RAllocator::__DbgMarkEnd(TInt aCount) |
|
375 { |
|
376 return DebugFunction(EMarkEnd, (TAny*)aCount); |
|
377 } |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 /** |
|
383 Checks the current number of allocated heap cells for this heap. |
|
384 |
|
385 If aCountAll is true, the function checks that the total number of allocated |
|
386 cells on this heap is the same as aCount. If aCountAll is false, then |
|
387 the function checks that the number of allocated cells at the current nested |
|
388 level is the same as aCount. |
|
389 |
|
390 If checking fails, the function raises a panic; |
|
391 information about the failure is put into the panic category; |
|
392 this takes the form: |
|
393 |
|
394 ALLOC COUNT\\rExpected aaa\\rAllocated bbb\\rLn: ccc ddddd |
|
395 |
|
396 where |
|
397 |
|
398 1. aaaa is the value aCount |
|
399 |
|
400 2. bbbb is the number of allocated heap cells |
|
401 |
|
402 3. ccc is a line number, copied from aLineNum |
|
403 |
|
404 4. ddddd is a file name, copied from the descriptor aFileName |
|
405 |
|
406 Note that the panic number is 1. |
|
407 |
|
408 @param aCountAll If true, the function checks that the total number of |
|
409 allocated cells on this heap is the same as aCount. |
|
410 If false, the function checks that the number of allocated |
|
411 cells at the current nested level is the same as aCount. |
|
412 @param aCount The expected number of allocated cells. |
|
413 @param aFileName A filename; this is displayed as part of the panic |
|
414 category if the check fails. |
|
415 @param aLineNum A line number; this is displayed as part of the panic category |
|
416 if the check fails. |
|
417 |
|
418 @return KErrNone, if successful; otherwise one of the other system wide error codes. |
|
419 */ |
|
420 UEXPORT_C TInt RAllocator::__DbgMarkCheck(TBool aCountAll, TInt aCount, const TDesC8& aFileName, TInt aLineNum) |
|
421 { |
|
422 SCheckInfo info; |
|
423 info.iAll = aCountAll; |
|
424 info.iCount = aCount; |
|
425 info.iFileName = &aFileName; |
|
426 info.iLineNum = aLineNum; |
|
427 return DebugFunction(ECheck, &info); |
|
428 } |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 /** |
|
434 Simulates a heap allocation failure for this heap. |
|
435 |
|
436 The failure occurs on subsequent calls to new or any of the functions which |
|
437 allocate memory from this heap. |
|
438 |
|
439 The timing of the allocation failure depends on the type of |
|
440 allocation failure requested, i.e. on the value of aType. |
|
441 |
|
442 The simulation of heap allocation failure is cancelled |
|
443 if aType is given the value RAllocator::ENone. |
|
444 |
|
445 Notes: |
|
446 |
|
447 1. If the failure type is RAllocator::EFailNext, the next attempt to allocate from |
|
448 this heap fails; however, no further failures will occur. |
|
449 |
|
450 2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1. |
|
451 |
|
452 @param aType An enumeration which indicates how to simulate heap |
|
453 allocation failure. |
|
454 @param aRate The rate of failure; when aType is RAllocator::EDeterministic, |
|
455 heap allocation fails every aRate attempts |
|
456 */ |
|
457 UEXPORT_C void RAllocator::__DbgSetAllocFail(TAllocFail aType, TInt aRate) |
|
458 { |
|
459 DebugFunction(ESetFail, (TAny*)aType, (TAny*)aRate); |
|
460 } |
|
461 |
|
462 |
|
463 /** |
|
464 Simulates a burst of heap allocation failures for this heap. |
|
465 |
|
466 The failure occurs for aBurst allocations attempt via subsequent calls |
|
467 to new or any of the functions which allocate memory from this heap. |
|
468 |
|
469 The timing of the allocation failure depends on the type of |
|
470 allocation failure requested, i.e. on the value of aType. |
|
471 |
|
472 The simulation of heap allocation failure is cancelled |
|
473 if aType is given the value RAllocator::ENone. |
|
474 |
|
475 Notes: |
|
476 |
|
477 1. If the failure type is RAllocator::EFailNext or RAllocator::EBurstFailNext, |
|
478 the next one or aBurst attempts to allocate from this heap will fail; |
|
479 however, no further failures will occur. |
|
480 |
|
481 2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1. |
|
482 |
|
483 @param aType An enumeration which indicates how to simulate heap |
|
484 allocation failure. |
|
485 @param aRate The rate of failure; when aType is RAllocator::EDeterministic, |
|
486 heap allocation fails every aRate attempts. |
|
487 @param aBurst The number of consecutive heap allocations that will fail each |
|
488 time the allocations should fail. |
|
489 |
|
490 @see RAllocator::TAllocFail |
|
491 */ |
|
492 UEXPORT_C void RAllocator::__DbgSetBurstAllocFail(TAllocFail aType, TUint aRate, TUint aBurst) |
|
493 { |
|
494 SRAllocatorBurstFail burstFail; |
|
495 burstFail.iRate = aRate; |
|
496 burstFail.iBurst = aBurst; |
|
497 DebugFunction(ESetBurstFail, (TAny*)aType, (TAny*)&burstFail); |
|
498 } |
|
499 |
|
500 /** |
|
501 Returns the number of heap allocation failures the current debug allocator fail |
|
502 function has caused so far. |
|
503 |
|
504 This is intended to only be used with fail types RAllocator::EFailNext, |
|
505 RAllocator::EBurstFailNext, RAllocator::EDeterministic and |
|
506 RAllocator::EBurstDeterministic. The return value is unreliable for |
|
507 all other fail types. |
|
508 |
|
509 @return The number of heap allocation failures the current debug fail |
|
510 function has caused. |
|
511 |
|
512 @see RAllocator::TAllocFail |
|
513 */ |
|
514 UEXPORT_C TUint RAllocator::__DbgCheckFailure() |
|
515 { |
|
516 return DebugFunction(ECheckFailure); |
|
517 } |
|
518 |
|
519 |
|
520 UEXPORT_C TInt RAllocator::Extension_(TUint, TAny*& a0, TAny*) |
|
521 { |
|
522 a0 = NULL; |
|
523 return KErrExtensionNotSupported; |
|
524 } |