|
1 // Copyright (c) 1995-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 // e32test\heap\t_heapdl.cpp |
|
15 // Overview: |
|
16 // Tests RHybridHeap class. |
|
17 // API Information: |
|
18 // RHybridHeap |
|
19 // Details: |
|
20 // |
|
21 // |
|
22 |
|
23 #include <e32test.h> |
|
24 #include <e32math.h> |
|
25 #include <e32def_private.h> |
|
26 #include "dla.h" |
|
27 #include "slab.h" |
|
28 #include "page_alloc.h" |
|
29 #include "heap_hybrid.h" |
|
30 |
|
31 const TUint KTestIterations = 100; |
|
32 |
|
33 const TInt KHeadSize = (TInt)RHeap::EAllocCellSize; |
|
34 |
|
35 class TestHybridHeap |
|
36 { |
|
37 public: |
|
38 static void TopSize(TInt& aTopSize, const RHybridHeap * aHybridHeap); |
|
39 static void DvSize(TInt& aDvSize, const RHybridHeap * aHybridHeap); |
|
40 static void SmallMap(TUint& aSmallMap, const RHybridHeap * aHybridHeap); |
|
41 static void TreeMap(TUint& aTreeMap, const RHybridHeap * aHybridHeap); |
|
42 static void TrimCheck(TInt& aTrimCheck, const RHybridHeap * aHybridHeap); |
|
43 static void GrowBy(TInt& aGrowBy, const RHybridHeap * aHybridHeap); |
|
44 static void PageSize(TInt& aPageSize, const RHybridHeap * aHybridHeap); |
|
45 }; |
|
46 |
|
47 |
|
48 void TestHybridHeap::TopSize(TInt& aTopSize, const RHybridHeap * aHybridHeap) |
|
49 { |
|
50 aTopSize = aHybridHeap->iGlobalMallocState.iTopSize; |
|
51 } |
|
52 |
|
53 |
|
54 void TestHybridHeap::DvSize(TInt& aDvSize, const RHybridHeap * aHybridHeap) |
|
55 { |
|
56 aDvSize = aHybridHeap->iGlobalMallocState.iDvSize; |
|
57 } |
|
58 |
|
59 |
|
60 void TestHybridHeap::SmallMap(TUint& aSmallMap, const RHybridHeap * aHybridHeap) |
|
61 { |
|
62 aSmallMap = aHybridHeap->iGlobalMallocState.iSmallMap; |
|
63 } |
|
64 |
|
65 |
|
66 void TestHybridHeap::TreeMap(TUint& aTreeMap, const RHybridHeap * aHybridHeap) |
|
67 { |
|
68 aTreeMap = aHybridHeap->iGlobalMallocState.iTreeMap; |
|
69 } |
|
70 |
|
71 |
|
72 void TestHybridHeap::TrimCheck(TInt& aTrimCheck, const RHybridHeap * aHybridHeap) |
|
73 { |
|
74 aTrimCheck = aHybridHeap->iGlobalMallocState.iTrimCheck; |
|
75 } |
|
76 |
|
77 |
|
78 void TestHybridHeap::GrowBy(TInt& aGrowBy, const RHybridHeap * aHybridHeap) |
|
79 { |
|
80 aGrowBy = aHybridHeap->iGrowBy; |
|
81 } |
|
82 |
|
83 void TestHybridHeap::PageSize(TInt& aPageSize, const RHybridHeap * aHybridHeap) |
|
84 { |
|
85 aPageSize = aHybridHeap->iPageSize; |
|
86 } |
|
87 |
|
88 |
|
89 LOCAL_D RTest test(_L("T_HEAPDL")); |
|
90 |
|
91 |
|
92 class TestRHeap |
|
93 { |
|
94 public: |
|
95 void InitTests(); |
|
96 void Test1(void); |
|
97 void Test2(void); |
|
98 void Test3(void); |
|
99 void Test4(void); |
|
100 void CloseTests(); |
|
101 private: |
|
102 RHybridHeap* iHybridHeap; |
|
103 RHeap *iHeap; |
|
104 }; |
|
105 |
|
106 |
|
107 void TestRHeap::InitTests() |
|
108 { |
|
109 // Allocate a chunk heap |
|
110 TPtrC testHeap=_L("TESTHEAP"); |
|
111 iHeap=User::ChunkHeap(&testHeap,0x1800,0x16000); |
|
112 |
|
113 RHybridHeap::STestCommand cmd; |
|
114 cmd.iCommand = RHybridHeap::EHeapMetaData; |
|
115 iHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&cmd ); |
|
116 iHybridHeap = (RHybridHeap*) cmd.iData; |
|
117 } |
|
118 |
|
119 |
|
120 void TestRHeap::Test1(void) |
|
121 { |
|
122 // |
|
123 // Splitting a new cell off 'top' chunk |
|
124 // Growing and shrinking 'top' chunk |
|
125 // Coalesceing of adjacent free cells |
|
126 // |
|
127 |
|
128 TInt topSizeBefore, topSizeAfter, allocSize; |
|
129 TInt growBy, pageSize; |
|
130 TestHybridHeap::GrowBy(growBy,iHybridHeap); |
|
131 TestHybridHeap::PageSize(pageSize,iHybridHeap); |
|
132 |
|
133 //Splitting a new cell off 'top' chunk |
|
134 TestHybridHeap::TopSize(topSizeBefore,iHybridHeap); |
|
135 TAny* p1=iHeap->Alloc(0x256); |
|
136 TestHybridHeap::TopSize(topSizeAfter,iHybridHeap); |
|
137 test(topSizeBefore > topSizeAfter); |
|
138 iHeap->Check(); |
|
139 iHeap->Free(p1); |
|
140 iHeap->Check(); |
|
141 |
|
142 //Growing 'top' chunk |
|
143 test(iHeap!=NULL); |
|
144 TestHybridHeap::TopSize(topSizeBefore,iHybridHeap); |
|
145 p1=iHeap->Alloc(pageSize*2); |
|
146 test(p1!=NULL); |
|
147 allocSize=iHeap->AllocLen(p1); |
|
148 TestHybridHeap::TopSize(topSizeAfter,iHybridHeap); |
|
149 test(topSizeBefore + growBy == topSizeAfter+allocSize+KHeadSize); |
|
150 |
|
151 //Splitting a new cell off 'top' chunk |
|
152 TAny *p2=iHeap->Alloc(pageSize/8); |
|
153 test(p2!=NULL); |
|
154 //Splitting a new cell off 'top' chunk |
|
155 TAny *p3=iHeap->Alloc(pageSize/2); |
|
156 test(p3!=NULL); |
|
157 //Growing 'top' chunk |
|
158 TAny *p4=iHeap->Alloc(pageSize*2); |
|
159 test(p4!=NULL); |
|
160 //Take allocSize of p4 |
|
161 allocSize=iHeap->AllocLen(p4); |
|
162 |
|
163 //Shrinking 'top' chunk |
|
164 TInt trimCheck; |
|
165 TestHybridHeap::TopSize(topSizeBefore,iHybridHeap); |
|
166 iHeap->Free(p4); |
|
167 TestHybridHeap::TopSize(topSizeAfter,iHybridHeap); |
|
168 TestHybridHeap::TrimCheck(trimCheck,iHybridHeap); |
|
169 test(topSizeAfter + trimCheck == topSizeBefore+allocSize+KHeadSize); |
|
170 iHeap->Check(); |
|
171 |
|
172 //Insert chunk into treebin |
|
173 TUint treeMap,treeMap2; |
|
174 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
175 test(treeMap==0); |
|
176 iHeap->Free(p2); |
|
177 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
178 test(treeMap>0); |
|
179 iHeap->Check(); |
|
180 |
|
181 //Coalesce adjacent free cells and insert chunk into treebin |
|
182 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
183 iHeap->Free(p1); |
|
184 TestHybridHeap::TreeMap(treeMap2,iHybridHeap); |
|
185 test(treeMap < treeMap2); |
|
186 iHeap->Check(); |
|
187 |
|
188 //free last allocation |
|
189 iHeap->Free(p3); |
|
190 iHeap->Check(); |
|
191 } |
|
192 |
|
193 |
|
194 void TestRHeap::Test2(void) |
|
195 { |
|
196 // |
|
197 // Allocation of exact sized cells from 'small cell' lists (smallbin) |
|
198 // Freeing of exact sized cells back to 'small cell' lists (smallbin) |
|
199 // |
|
200 TInt ArraySize=32; |
|
201 TInt cellSize=0; |
|
202 TInt topSizeBefore, topSizeAfter; |
|
203 |
|
204 TAny** ArrayOfCells; |
|
205 ArrayOfCells= new TAny*[ArraySize]; |
|
206 TInt ArrayIndex; |
|
207 // Allocate exact sized small cells 8,16,32,40---> |
|
208 // and put them to the array. They are allocated from TOP chunk |
|
209 for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++) |
|
210 { |
|
211 TestHybridHeap::TopSize(topSizeBefore,iHybridHeap); |
|
212 cellSize=cellSize+8; |
|
213 ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize); |
|
214 TestHybridHeap::TopSize(topSizeAfter,iHybridHeap); |
|
215 test(topSizeBefore > topSizeAfter); |
|
216 } |
|
217 iHeap->Check(); |
|
218 |
|
219 TUint smallMap, smallMap2; |
|
220 TInt dvSize, dvSize2; |
|
221 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
222 test(smallMap == 0); |
|
223 // Free some of small cells from the array. So they are inserted |
|
224 // to the smallbin |
|
225 for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5) |
|
226 { |
|
227 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
228 iHeap->Free(ArrayOfCells[ArrayIndex]); |
|
229 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
230 test(smallMap<smallMap2); |
|
231 } |
|
232 iHeap->Check(); |
|
233 |
|
234 // Allocate exact sized cells from smallbin (or Designated Victim) |
|
235 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
236 TAny* p1=iHeap->Alloc(32); |
|
237 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
238 test(smallMap>smallMap2); |
|
239 |
|
240 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
241 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
242 TAny* p2=iHeap->Alloc(32); |
|
243 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
244 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
245 if(dvSize <= dvSize2) |
|
246 test(smallMap>smallMap2); |
|
247 |
|
248 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
249 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
250 TAny* p3=iHeap->Alloc(32); |
|
251 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
252 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
253 if(dvSize <= dvSize2) |
|
254 test(smallMap>smallMap2); |
|
255 |
|
256 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
257 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
258 TAny* p4=iHeap->Alloc(32); |
|
259 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
260 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
261 if(dvSize <= dvSize2) |
|
262 test(smallMap>smallMap2); |
|
263 |
|
264 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
265 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
266 TAny* p5=iHeap->Alloc(48); |
|
267 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
268 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
269 if(dvSize <= dvSize2) |
|
270 test(smallMap>smallMap2); |
|
271 |
|
272 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
273 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
274 TAny* p6=iHeap->Alloc(64); |
|
275 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
276 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
277 if(dvSize <= dvSize2) |
|
278 test(smallMap>smallMap2); |
|
279 |
|
280 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
281 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
282 TAny* p7=iHeap->Alloc(80); |
|
283 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
284 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
285 if(dvSize <= dvSize2) |
|
286 test(smallMap>smallMap2); |
|
287 |
|
288 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
289 TestHybridHeap::DvSize(dvSize,iHybridHeap); |
|
290 TAny* p8=iHeap->Alloc(96); |
|
291 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
292 TestHybridHeap::DvSize(dvSize2,iHybridHeap); |
|
293 if(dvSize <= dvSize2) |
|
294 test(smallMap>smallMap2); |
|
295 iHeap->Check(); |
|
296 |
|
297 // Freeing of exact sized cells back to smallbin |
|
298 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
299 iHeap->Free(p1); |
|
300 iHeap->Free(p2); |
|
301 iHeap->Free(p3); |
|
302 iHeap->Free(p4); |
|
303 iHeap->Free(p5); |
|
304 iHeap->Free(p6); |
|
305 iHeap->Free(p7); |
|
306 iHeap->Free(p8); |
|
307 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
308 test(smallMap < smallMap2); |
|
309 iHeap->Check(); |
|
310 |
|
311 // Now free rest of the array with Reset |
|
312 iHeap->Reset(); |
|
313 iHeap->Check(); |
|
314 |
|
315 delete [] ArrayOfCells; |
|
316 } |
|
317 |
|
318 |
|
319 void TestRHeap::Test3(void) |
|
320 { |
|
321 // |
|
322 // Allocation of approximate sized cells from 'small cell' lists (smallbin) |
|
323 // |
|
324 const TInt ArraySize=32; |
|
325 TInt cellSize=0; |
|
326 TAny** ArrayOfCells; |
|
327 ArrayOfCells= new TAny*[ArraySize]; |
|
328 TInt ArrayIndex; |
|
329 TInt topSizeBefore, topSizeAfter; |
|
330 |
|
331 // Allocate small approximate sized cells and put |
|
332 //them to the array. They are allocated from TOP chunk |
|
333 TUint8 randomSize[ArraySize]; |
|
334 for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++) |
|
335 { |
|
336 TestHybridHeap::TopSize(topSizeBefore,iHybridHeap); |
|
337 // Ensure that the size of the cell does not exceed 256 bytes on debug builds |
|
338 randomSize[ArrayIndex] = (TUint8) (Math::Random() % (MAX_SMALL_REQUEST + 1 - RHeap::EDebugHdrSize)); |
|
339 cellSize=randomSize[ArrayIndex]; |
|
340 ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize); |
|
341 TestHybridHeap::TopSize(topSizeAfter,iHybridHeap); |
|
342 test(topSizeBefore > topSizeAfter); |
|
343 } |
|
344 iHeap->Check(); |
|
345 |
|
346 TUint smallMap, smallMap2; |
|
347 // Free some of allocated cells from the array. So they are inserted |
|
348 // to the smallbin |
|
349 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
350 for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5) |
|
351 { |
|
352 iHeap->Free(ArrayOfCells[ArrayIndex]); |
|
353 } |
|
354 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
355 test(smallMap<=smallMap2); |
|
356 iHeap->Check(); |
|
357 |
|
358 // Allocate approximate sized cells from smallbin |
|
359 const TInt ArraySize2=6; |
|
360 TInt cellSize2=0; |
|
361 TAny** ArrayOfCells2; |
|
362 ArrayOfCells2= new TAny*[ArraySize2]; |
|
363 TInt ArrayIndex2; |
|
364 TestHybridHeap::SmallMap(smallMap,iHybridHeap); |
|
365 TUint8 randomSize2[ArraySize2]; |
|
366 for(ArrayIndex2=0; ArrayIndex2<ArraySize2;ArrayIndex2++) |
|
367 { |
|
368 randomSize2[ArrayIndex2]=randomSize[2+ArrayIndex2*5]; |
|
369 cellSize2=randomSize2[ArrayIndex2]; |
|
370 ArrayOfCells2[ArrayIndex2]=iHeap->Alloc(cellSize2); |
|
371 } |
|
372 TestHybridHeap::SmallMap(smallMap2,iHybridHeap); |
|
373 test(smallMap>=smallMap2); |
|
374 iHeap->Check(); |
|
375 |
|
376 // Freeing of approximate sized cells back to smallbin |
|
377 for(ArrayIndex2=0; ArrayIndex2<ArraySize2-1; ArrayIndex2+=1) |
|
378 { |
|
379 iHeap->Free(ArrayOfCells2[ArrayIndex2]); |
|
380 } |
|
381 iHeap->Check(); |
|
382 |
|
383 // Now free rest of the array with Reset |
|
384 iHeap->Reset(); |
|
385 iHeap->Check(); |
|
386 |
|
387 delete [] ArrayOfCells; |
|
388 delete [] ArrayOfCells2; |
|
389 } |
|
390 |
|
391 |
|
392 void TestRHeap::Test4(void) |
|
393 { |
|
394 // |
|
395 // Allocation of approximate sized cells from digital trees (treebin) and splitting |
|
396 // Freeing of approximate sized cells back to digital trees (treebin) |
|
397 // |
|
398 const TInt ArraySize=32; |
|
399 TInt cellSize=0; |
|
400 TAny** ArrayOfCells; |
|
401 ArrayOfCells= new TAny*[ArraySize]; |
|
402 TInt ArrayIndex; |
|
403 |
|
404 // Allocate approximate sized cells bigger than 256 |
|
405 // and put them to the array. They are allocated from TOP chunk |
|
406 TUint8 randomSize[ArraySize]; |
|
407 for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++) |
|
408 { |
|
409 randomSize[ArrayIndex] = (TUint8)Math::Random(); |
|
410 cellSize=(randomSize[ArrayIndex]+MAX_SMALL_REQUEST+1); |
|
411 ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize); |
|
412 } |
|
413 iHeap->Check(); |
|
414 |
|
415 TUint treeMap,treeMap2; |
|
416 // Free some of allocated cells from the array. So they are inserted |
|
417 // to the treebin |
|
418 for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5) |
|
419 { |
|
420 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
421 iHeap->Free(ArrayOfCells[ArrayIndex]); |
|
422 TestHybridHeap::TreeMap(treeMap2,iHybridHeap); |
|
423 test(treeMap <= treeMap2); |
|
424 } |
|
425 iHeap->Check(); |
|
426 |
|
427 // Allocate approximate sized cells from treebin |
|
428 const TInt ArraySize2=16; |
|
429 TInt cellSize2=0; |
|
430 TAny** ArrayOfCells2; |
|
431 ArrayOfCells2= new TAny*[ArraySize2]; |
|
432 TInt ArrayIndex2; |
|
433 TUint8 randomSize2[ArraySize2]; |
|
434 for(ArrayIndex2=0; ArrayIndex2<ArraySize2;ArrayIndex2++) |
|
435 { |
|
436 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
437 randomSize2[ArrayIndex2] = (TUint8)Math::Random(); |
|
438 cellSize2=(randomSize2[ArrayIndex2]+MAX_SMALL_REQUEST+1); |
|
439 ArrayOfCells2[ArrayIndex2]=iHeap->Alloc(cellSize2); |
|
440 TestHybridHeap::TreeMap(treeMap2,iHybridHeap); |
|
441 test(treeMap >= treeMap2); |
|
442 } |
|
443 iHeap->Check(); |
|
444 |
|
445 // Freeing of approximate sized cells back to treebin |
|
446 TestHybridHeap::TreeMap(treeMap,iHybridHeap); |
|
447 for(ArrayIndex2=0; ArrayIndex2<ArraySize2-1; ArrayIndex2+=1) |
|
448 { |
|
449 iHeap->Free(ArrayOfCells2[ArrayIndex2]); |
|
450 } |
|
451 TestHybridHeap::TreeMap(treeMap2,iHybridHeap); |
|
452 test(treeMap <= treeMap2); |
|
453 iHeap->Check(); |
|
454 |
|
455 // Now free rest of the array with Reset |
|
456 iHeap->Reset(); |
|
457 iHeap->Check(); |
|
458 |
|
459 delete [] ArrayOfCells; |
|
460 delete [] ArrayOfCells2; |
|
461 } |
|
462 |
|
463 |
|
464 void TestRHeap::CloseTests() |
|
465 { |
|
466 // close heap so we don't exceed chunk limit |
|
467 iHeap->Close(); |
|
468 } |
|
469 |
|
470 |
|
471 GLDEF_C TInt E32Main(void) |
|
472 { |
|
473 test.Title(); |
|
474 |
|
475 __KHEAP_MARK; |
|
476 |
|
477 TestRHeap T; |
|
478 TUint i; |
|
479 test.Start(_L("Init DL allocator tests")); |
|
480 T.InitTests(); |
|
481 test.Next(_L("Test DL allocator 1")); |
|
482 for(i = 0; i < KTestIterations; i++) |
|
483 { |
|
484 T.Test1(); |
|
485 } |
|
486 test.Next(_L("Test DL allocator 2")); |
|
487 for(i = 0; i < KTestIterations; i++) |
|
488 { |
|
489 T.Test2(); |
|
490 } |
|
491 test.Next(_L("Test DL allocator 3")); |
|
492 for(i = 0; i < KTestIterations; i++) |
|
493 { |
|
494 T.Test3(); |
|
495 } |
|
496 test.Next(_L("Test DL allocator 4")); |
|
497 for(i = 0; i < KTestIterations; i++) |
|
498 { |
|
499 T.Test4(); |
|
500 } |
|
501 test.Next(_L("Close DL allocator tests")); |
|
502 T.CloseTests(); |
|
503 |
|
504 __KHEAP_CHECK(0); |
|
505 __KHEAP_MARKEND; |
|
506 |
|
507 test.End(); |
|
508 return(0); |
|
509 } |