0
|
1 |
// Copyright (c) 2002-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_heap2.cpp
|
|
15 |
// Overview:
|
|
16 |
// Tests RHeap class, including a stress test and a "grow in place"
|
|
17 |
// ReAlloc test.
|
|
18 |
// API Information:
|
|
19 |
// RHeap
|
|
20 |
// Details:
|
|
21 |
// - Test allocation on fixed length heaps in local, disconnected chunks for
|
|
22 |
// different heap sizes and alignments. Assumes knowledge of heap
|
|
23 |
// implementation.
|
|
24 |
// - Test allocation, free, reallocation and compression on chunk heaps with
|
|
25 |
// different maximum and minimum lengths and alignments. Assumes knowledge
|
|
26 |
// of heap implementation.
|
|
27 |
// - Stress test heap implementation with a single thread that allocates, frees
|
|
28 |
// and reallocates cells, and checks the heap.
|
|
29 |
// - Stress test heap implementation with two threads that run concurrently.
|
|
30 |
// - Create a chunk heap, test growing in place by allocating a cell and
|
|
31 |
// then reallocating additional space until failure, verify that the cell
|
|
32 |
// did not move and the size was increased.
|
|
33 |
// - The heap is checked to verify that no cells remain allocated after the
|
|
34 |
// tests are complete.
|
|
35 |
// Platforms/Drives/Compatibility:
|
|
36 |
// All
|
|
37 |
// Assumptions/Requirement/Pre-requisites:
|
|
38 |
// Failures and causes:
|
|
39 |
// Base Port information:
|
|
40 |
//
|
|
41 |
//
|
|
42 |
|
|
43 |
#include <e32test.h>
|
|
44 |
#include <e32hal.h>
|
|
45 |
#include <e32def.h>
|
|
46 |
#include <e32def_private.h>
|
189
|
47 |
#include "dla.h"
|
|
48 |
#include "slab.h"
|
|
49 |
#include "page_alloc.h"
|
|
50 |
#include "heap_hybrid.h"
|
0
|
51 |
|
|
52 |
// Needed for KHeapShrinkHysRatio which is now ROM 'patchdata'
|
|
53 |
#include "TestRHeapShrink.h"
|
|
54 |
|
|
55 |
#define DECL_GET(T,x) inline T x() const {return i##x;}
|
|
56 |
#define DECL_GET2(T,x,y) inline T y() const {return i##x;}
|
|
57 |
|
|
58 |
|
|
59 |
#ifdef __EABI__
|
|
60 |
IMPORT_D extern const TInt KHeapMinCellSize;
|
|
61 |
#else
|
|
62 |
const TInt KHeapMinCellSize = 0;
|
|
63 |
#endif
|
|
64 |
|
189
|
65 |
const TInt KAllocCellSize = (TInt)RHeap::EAllocCellSize;
|
|
66 |
const TInt KSizeOfHeap = (TInt)sizeof(RHybridHeap);
|
|
67 |
|
|
68 |
|
0
|
69 |
RTest test(_L("T_HEAP2"));
|
|
70 |
|
|
71 |
#define TEST_ALIGN(p,a) test((TLinAddr(p)&((a)-1))==0)
|
|
72 |
|
|
73 |
struct STestCell
|
|
74 |
{
|
|
75 |
enum {EMagic = 0xb8aa3b29};
|
|
76 |
|
|
77 |
TUint32 iLength;
|
|
78 |
TUint32 iData[1];
|
|
79 |
|
|
80 |
void Set(TInt aLength);
|
|
81 |
void Verify(TInt aLength);
|
|
82 |
void Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength);
|
|
83 |
};
|
|
84 |
|
|
85 |
void STestCell::Set(TInt aLength)
|
|
86 |
{
|
|
87 |
TInt i;
|
|
88 |
TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic;
|
|
89 |
if (aLength==0)
|
|
90 |
return;
|
|
91 |
iLength = x;
|
|
92 |
aLength /= sizeof(TUint32);
|
|
93 |
for (i=0; i<aLength-1; ++i)
|
|
94 |
{
|
|
95 |
x *= 69069;
|
|
96 |
x += 41;
|
|
97 |
iData[i] = x;
|
|
98 |
}
|
|
99 |
}
|
|
100 |
|
|
101 |
void STestCell::Verify(TInt aLength)
|
|
102 |
{
|
|
103 |
Verify(this, aLength, aLength);
|
|
104 |
}
|
|
105 |
|
|
106 |
void STestCell::Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength)
|
|
107 |
{
|
|
108 |
TInt i;
|
|
109 |
TUint32 x = (TUint32)aInitPtr ^ (TUint32)aInitLength ^ (TUint32)EMagic;
|
189
|
110 |
if ( aLength < (TInt) sizeof(*this) )
|
0
|
111 |
return;
|
|
112 |
test(iLength == x);
|
|
113 |
aLength /= sizeof(TUint32);
|
|
114 |
for (i=0; i<aLength-1; ++i)
|
|
115 |
{
|
|
116 |
x *= 69069;
|
|
117 |
x += 41;
|
|
118 |
test(iData[i] == x);
|
|
119 |
}
|
|
120 |
}
|
|
121 |
|
189
|
122 |
|
|
123 |
|
0
|
124 |
class RTestHeap : public RHeap
|
|
125 |
{
|
|
126 |
public:
|
|
127 |
TInt CheckAllocatedCell(const TAny* aCell) const;
|
|
128 |
void FullCheckAllocatedCell(const TAny* aCell) const;
|
|
129 |
TAny* TestAlloc(TInt aSize);
|
|
130 |
void TestFree(TAny* aPtr);
|
|
131 |
TAny* TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
|
|
132 |
void FullCheck();
|
|
133 |
static void WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
|
|
134 |
};
|
|
135 |
|
|
136 |
TInt RTestHeap::CheckAllocatedCell(const TAny* aCell) const
|
|
137 |
{
|
189
|
138 |
TInt len = AllocLen(aCell);
|
0
|
139 |
return len;
|
|
140 |
}
|
|
141 |
|
|
142 |
void RTestHeap::FullCheckAllocatedCell(const TAny* aCell) const
|
|
143 |
{
|
|
144 |
((STestCell*)aCell)->Verify(CheckAllocatedCell(aCell));
|
|
145 |
}
|
|
146 |
|
|
147 |
TAny* RTestHeap::TestAlloc(TInt aSize)
|
|
148 |
{
|
|
149 |
TAny* p = Alloc(aSize);
|
|
150 |
if (p)
|
|
151 |
{
|
|
152 |
TInt len = CheckAllocatedCell(p);
|
189
|
153 |
test(len>=aSize);
|
0
|
154 |
((STestCell*)p)->Set(len);
|
|
155 |
}
|
|
156 |
return p;
|
|
157 |
}
|
|
158 |
|
|
159 |
void RTestHeap::TestFree(TAny* aPtr)
|
|
160 |
{
|
|
161 |
if (aPtr)
|
|
162 |
FullCheckAllocatedCell(aPtr);
|
|
163 |
Free(aPtr);
|
|
164 |
}
|
|
165 |
|
|
166 |
TAny* RTestHeap::TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode)
|
|
167 |
{
|
|
168 |
TInt old_len = aPtr ? CheckAllocatedCell(aPtr) : 0;
|
|
169 |
if (aPtr)
|
|
170 |
((STestCell*)aPtr)->Verify(old_len);
|
|
171 |
TAny* p = ReAlloc(aPtr, aSize, aMode);
|
|
172 |
if (!p)
|
|
173 |
{
|
|
174 |
((STestCell*)aPtr)->Verify(old_len);
|
|
175 |
return p;
|
|
176 |
}
|
|
177 |
TInt new_len = CheckAllocatedCell(p);
|
189
|
178 |
test(new_len>=aSize);
|
0
|
179 |
if (p == aPtr)
|
|
180 |
{
|
|
181 |
((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len));
|
|
182 |
if (new_len != old_len)
|
|
183 |
((STestCell*)p)->Set(new_len);
|
|
184 |
return p;
|
|
185 |
}
|
|
186 |
test(!(aMode & ENeverMove));
|
|
187 |
test((new_len > old_len) || (aMode & EAllowMoveOnShrink));
|
|
188 |
if (old_len)
|
189
|
189 |
((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, aSize));
|
|
190 |
((STestCell*)p)->Set(new_len);
|
0
|
191 |
return p;
|
|
192 |
}
|
|
193 |
|
|
194 |
struct SHeapCellInfo
|
|
195 |
{
|
|
196 |
RTestHeap* iHeap;
|
|
197 |
TInt iTotalAlloc;
|
|
198 |
TInt iTotalAllocSize;
|
|
199 |
TInt iTotalFree;
|
|
200 |
TUint8* iNextCell;
|
|
201 |
};
|
|
202 |
|
|
203 |
void RTestHeap::WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen)
|
|
204 |
{
|
|
205 |
(void)aCell;
|
|
206 |
::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr;
|
|
207 |
switch(aType)
|
|
208 |
{
|
|
209 |
case EGoodAllocatedCell:
|
|
210 |
{
|
189
|
211 |
TInt len = aLen;
|
|
212 |
info.iTotalAllocSize += len;
|
|
213 |
STestCell* pT = (STestCell*)aCell;
|
0
|
214 |
++info.iTotalAlloc;
|
|
215 |
pT->Verify(len);
|
|
216 |
break;
|
|
217 |
}
|
|
218 |
case EGoodFreeCell:
|
|
219 |
{
|
|
220 |
++info.iTotalFree;
|
|
221 |
break;
|
|
222 |
}
|
|
223 |
default:
|
|
224 |
test.Printf(_L("TYPE=%d ??\n"),aType);
|
|
225 |
test(0);
|
|
226 |
break;
|
|
227 |
}
|
|
228 |
}
|
|
229 |
|
|
230 |
void RTestHeap::FullCheck()
|
|
231 |
{
|
|
232 |
::SHeapCellInfo info;
|
|
233 |
Mem::FillZ(&info, sizeof(info));
|
|
234 |
info.iHeap = this;
|
|
235 |
DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info);
|
189
|
236 |
TInt count = AllocSize(iTotalAllocSize);
|
|
237 |
test(info.iTotalAlloc == count);
|
0
|
238 |
test(info.iTotalAllocSize == iTotalAllocSize);
|
|
239 |
|
|
240 |
}
|
|
241 |
|
|
242 |
struct SHeapStress
|
|
243 |
{
|
|
244 |
RThread iThread;
|
|
245 |
volatile TBool iStop;
|
|
246 |
TInt iAllocs;
|
|
247 |
TInt iFailedAllocs;
|
|
248 |
TInt iFrees;
|
|
249 |
TInt iReAllocs;
|
|
250 |
TInt iFailedReAllocs;
|
|
251 |
TInt iChecks;
|
|
252 |
TUint32 iSeed;
|
|
253 |
RAllocator* iAllocator;
|
|
254 |
|
|
255 |
TUint32 Random();
|
|
256 |
};
|
|
257 |
|
|
258 |
TUint32 SHeapStress::Random()
|
|
259 |
{
|
|
260 |
iSeed *= 69069;
|
|
261 |
iSeed += 41;
|
|
262 |
return iSeed;
|
|
263 |
}
|
|
264 |
|
|
265 |
TInt RandomLength(TUint32 aRandom)
|
|
266 |
{
|
|
267 |
TUint8 x = (TUint8)aRandom;
|
|
268 |
if (x & 0x80)
|
|
269 |
return (x & 0x7f) << 7;
|
|
270 |
return x & 0x7f;
|
|
271 |
}
|
|
272 |
|
|
273 |
TInt HeapStress(TAny* aPtr)
|
|
274 |
{
|
|
275 |
SHeapStress& hs = *(SHeapStress*)aPtr;
|
|
276 |
RTestHeap* h = (RTestHeap*)&User::Allocator();
|
|
277 |
TUint8* cell[256];
|
|
278 |
TInt len[256];
|
|
279 |
|
|
280 |
Mem::FillZ(cell, sizeof(cell));
|
|
281 |
Mem::FillZ(len, sizeof(len));
|
|
282 |
|
|
283 |
RThread::Rendezvous(KErrNone);
|
|
284 |
while (!hs.iStop)
|
|
285 |
{
|
|
286 |
// allocate all cells
|
|
287 |
TInt i;
|
|
288 |
for (i=0; i<256; ++i)
|
|
289 |
{
|
|
290 |
if (!cell[i])
|
|
291 |
{
|
|
292 |
++hs.iAllocs;
|
|
293 |
cell[i] = (TUint8*)h->TestAlloc(RandomLength(hs.Random()));
|
|
294 |
if (cell[i])
|
|
295 |
len[i] = h->AllocLen(cell[i]);
|
|
296 |
else
|
|
297 |
++hs.iFailedAllocs;
|
|
298 |
}
|
|
299 |
}
|
|
300 |
|
|
301 |
// free some cells
|
|
302 |
TInt n = 64 + (hs.Random() & 127);
|
|
303 |
while (--n)
|
|
304 |
{
|
|
305 |
i = hs.Random() & 0xff;
|
|
306 |
if (cell[i])
|
|
307 |
{
|
|
308 |
test(h->AllocLen(cell[i]) == len[i]);
|
|
309 |
h->TestFree(cell[i]);
|
|
310 |
cell[i] = NULL;
|
|
311 |
len[i] = 0;
|
|
312 |
++hs.iFrees;
|
|
313 |
}
|
|
314 |
}
|
|
315 |
|
|
316 |
// realloc some cells
|
|
317 |
n = 64 + (hs.Random() & 127);
|
|
318 |
while (--n)
|
|
319 |
{
|
|
320 |
TUint32 rn = hs.Random();
|
|
321 |
i = (rn >> 8) & 0xff;
|
|
322 |
TInt new_len = RandomLength(rn);
|
|
323 |
if (cell[i])
|
|
324 |
{
|
|
325 |
test(h->AllocLen(cell[i]) == len[i]);
|
|
326 |
++hs.iReAllocs;
|
|
327 |
TUint8* p = (TUint8*)h->TestReAlloc(cell[i], new_len, rn >> 16);
|
|
328 |
if (p)
|
|
329 |
{
|
|
330 |
cell[i] = p;
|
|
331 |
len[i] = h->AllocLen(p);
|
|
332 |
}
|
|
333 |
else
|
|
334 |
++hs.iFailedReAllocs;
|
|
335 |
}
|
|
336 |
}
|
|
337 |
|
|
338 |
// check the heap
|
|
339 |
h->Check();
|
|
340 |
++hs.iChecks;
|
|
341 |
}
|
|
342 |
return 0;
|
|
343 |
}
|
|
344 |
|
|
345 |
void CreateStressThread(SHeapStress& aInfo)
|
|
346 |
{
|
|
347 |
Mem::FillZ(&aInfo, _FOFF(SHeapStress, iSeed));
|
|
348 |
RThread& t = aInfo.iThread;
|
|
349 |
TInt r = t.Create(KNullDesC(), &HeapStress, 0x2000, aInfo.iAllocator, &aInfo);
|
|
350 |
test(r==KErrNone);
|
|
351 |
t.SetPriority(EPriorityLess);
|
|
352 |
TRequestStatus s;
|
|
353 |
t.Rendezvous(s);
|
|
354 |
test(s == KRequestPending);
|
|
355 |
t.Resume();
|
|
356 |
User::WaitForRequest(s);
|
|
357 |
test(s == KErrNone);
|
|
358 |
test(t.ExitType() == EExitPending);
|
|
359 |
t.SetPriority(EPriorityMuchLess);
|
|
360 |
}
|
|
361 |
|
|
362 |
void StopStressThread(SHeapStress& aInfo)
|
|
363 |
{
|
|
364 |
RThread& t = aInfo.iThread;
|
|
365 |
TRequestStatus s;
|
|
366 |
t.Logon(s);
|
|
367 |
aInfo.iStop = ETrue;
|
|
368 |
User::WaitForRequest(s);
|
|
369 |
const TDesC& exitCat = t.ExitCategory();
|
|
370 |
TInt exitReason = t.ExitReason();
|
|
371 |
TInt exitType = t.ExitType();
|
|
372 |
test.Printf(_L("Exit type %d,%d,%S\n"), exitType, exitReason, &exitCat);
|
|
373 |
test(exitType == EExitKill);
|
|
374 |
test(exitReason == KErrNone);
|
|
375 |
test(s == KErrNone);
|
|
376 |
test.Printf(_L("Total Allocs : %d\n"), aInfo.iAllocs);
|
|
377 |
test.Printf(_L("Failed Allocs : %d\n"), aInfo.iFailedAllocs);
|
|
378 |
test.Printf(_L("Total Frees : %d\n"), aInfo.iFrees);
|
|
379 |
test.Printf(_L("Total ReAllocs : %d\n"), aInfo.iReAllocs);
|
|
380 |
test.Printf(_L("Failed ReAllocs : %d\n"), aInfo.iFailedReAllocs);
|
|
381 |
test.Printf(_L("Heap checks : %d\n"), aInfo.iChecks);
|
|
382 |
}
|
|
383 |
|
|
384 |
void DoStressTest1(RAllocator* aAllocator)
|
|
385 |
{
|
|
386 |
RTestHeap* h = (RTestHeap*)aAllocator;
|
189
|
387 |
test.Printf(_L("Test Stress 1: max=%x\n"), h->MaxLength());
|
0
|
388 |
SHeapStress hs;
|
|
389 |
hs.iSeed = 0xb504f334;
|
|
390 |
hs.iAllocator = aAllocator;
|
|
391 |
CreateStressThread(hs);
|
|
392 |
User::After(10*1000000);
|
|
393 |
StopStressThread(hs);
|
|
394 |
CLOSE_AND_WAIT(hs.iThread);
|
|
395 |
h->FullCheck();
|
|
396 |
}
|
|
397 |
|
|
398 |
void DoStressTest2(RAllocator* aAllocator)
|
|
399 |
{
|
|
400 |
RTestHeap* h = (RTestHeap*)aAllocator;
|
189
|
401 |
test.Printf(_L("Test Stress 2: max=%x\n"), h->MaxLength());
|
0
|
402 |
SHeapStress hs1;
|
|
403 |
SHeapStress hs2;
|
|
404 |
hs1.iSeed = 0xb504f334;
|
|
405 |
hs1.iAllocator = aAllocator;
|
|
406 |
hs2.iSeed = 0xddb3d743;
|
|
407 |
hs2.iAllocator = aAllocator;
|
|
408 |
CreateStressThread(hs1);
|
|
409 |
CreateStressThread(hs2);
|
|
410 |
User::After(20*1000000);
|
|
411 |
StopStressThread(hs1);
|
|
412 |
StopStressThread(hs2);
|
|
413 |
CLOSE_AND_WAIT(hs1.iThread);
|
|
414 |
CLOSE_AND_WAIT(hs2.iThread);
|
|
415 |
h->FullCheck();
|
|
416 |
}
|
|
417 |
|
|
418 |
void StressTests()
|
|
419 |
{
|
|
420 |
RHeap* h;
|
|
421 |
h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4);
|
|
422 |
test(h != NULL);
|
|
423 |
DoStressTest1(h);
|
|
424 |
h->Reset();
|
|
425 |
DoStressTest2(h);
|
|
426 |
h->Close();
|
|
427 |
h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 8);
|
|
428 |
test(h != NULL);
|
|
429 |
DoStressTest1(h);
|
|
430 |
h->Reset();
|
|
431 |
DoStressTest2(h);
|
|
432 |
h->Close();
|
|
433 |
}
|
|
434 |
|
|
435 |
TInt TestHeapGrowInPlace(TInt aMode)
|
|
436 |
{
|
|
437 |
TBool reAllocs=EFalse;
|
|
438 |
RHeap* myHeap;
|
189
|
439 |
//
|
|
440 |
// Fixed DL heap used.
|
|
441 |
//
|
|
442 |
myHeap = UserHeap::ChunkHeap(NULL,0x4000,0x4000,0x1000);
|
0
|
443 |
|
|
444 |
TAny *testBuffer,*testBuffer2;
|
|
445 |
// Start size chosen so that 1st realloc will use up exactly all the heap.
|
|
446 |
// Later iterations wont, and there will be a free cell at the end of the heap.
|
189
|
447 |
TInt currentSize = ((0x800) - KSizeOfHeap) - KAllocCellSize;
|
0
|
448 |
TInt growBy = 0x800;
|
189
|
449 |
|
0
|
450 |
testBuffer2 = myHeap->Alloc(currentSize);
|
|
451 |
|
|
452 |
do
|
|
453 |
{
|
189
|
454 |
testBuffer = testBuffer2;
|
0
|
455 |
currentSize+=growBy;
|
|
456 |
testBuffer2 = myHeap->ReAlloc(testBuffer,currentSize,aMode);
|
|
457 |
|
|
458 |
if (testBuffer2)
|
|
459 |
{
|
|
460 |
|
|
461 |
if (testBuffer!=testBuffer2)
|
|
462 |
reAllocs = ETrue;
|
|
463 |
}
|
|
464 |
growBy-=16;
|
|
465 |
} while (testBuffer2);
|
|
466 |
currentSize-=growBy;
|
|
467 |
|
|
468 |
myHeap->Free(testBuffer);
|
|
469 |
myHeap->Close();
|
|
470 |
|
|
471 |
// How did we do?
|
|
472 |
if (reAllocs)
|
|
473 |
{
|
|
474 |
test.Printf(_L("Failure - Memory was moved!\n"));
|
|
475 |
return -100;
|
|
476 |
}
|
|
477 |
if (currentSize<= 0x3000)
|
|
478 |
{
|
|
479 |
test.Printf(_L("Failed to grow by a reasonable amount!\n"));
|
|
480 |
return -300;
|
|
481 |
}
|
|
482 |
|
|
483 |
return KErrNone;
|
|
484 |
}
|
|
485 |
|
|
486 |
void ReAllocTests()
|
|
487 |
{
|
|
488 |
test.Next(_L("Testing Grow In Place"));
|
|
489 |
test(TestHeapGrowInPlace(0)==KErrNone);
|
|
490 |
test(TestHeapGrowInPlace(RHeap::ENeverMove)==KErrNone);
|
|
491 |
}
|
|
492 |
|
|
493 |
RHeap* TestDEF078391Heap = 0;
|
|
494 |
|
|
495 |
TInt TestDEF078391ThreadFunction(TAny*)
|
|
496 |
{
|
|
497 |
TestDEF078391Heap = UserHeap::ChunkHeap(NULL,0x1000,0x100000,KMinHeapGrowBy,0,EFalse);
|
|
498 |
return TestDEF078391Heap ? KErrNone : KErrGeneral;
|
|
499 |
}
|
|
500 |
|
|
501 |
void TestDEF078391()
|
|
502 |
{
|
|
503 |
// Test that creating a multithreaded heap with UserHeap::ChunkHeap
|
|
504 |
// doesn't create any reference counts on the creating thread.
|
|
505 |
// This is done by creating a heap in a named thread, then exiting
|
|
506 |
// the thread and re-creating it with the same name.
|
|
507 |
// This will fail with KErrAlreadyExists if the orinal thread has
|
|
508 |
// not died because of an unclosed reference count.
|
|
509 |
test.Next(_L("Test that creating a multithreaded heap doesn't open references of creator"));
|
|
510 |
_LIT(KThreadName,"ThreadName");
|
|
511 |
RThread t;
|
|
512 |
TInt r=t.Create(KThreadName,TestDEF078391ThreadFunction,0x1000,0x1000,0x100000,NULL);
|
|
513 |
test(r==KErrNone);
|
|
514 |
TRequestStatus status;
|
|
515 |
t.Logon(status);
|
|
516 |
t.Resume();
|
|
517 |
User::WaitForRequest(status);
|
|
518 |
test(status==KErrNone);
|
|
519 |
test(t.ExitType()==EExitKill);
|
|
520 |
test(t.ExitReason()==KErrNone);
|
|
521 |
CLOSE_AND_WAIT(t);
|
|
522 |
test(TestDEF078391Heap!=0);
|
|
523 |
User::After(1000000); // give more opportunity for thread cleanup to happen
|
|
524 |
|
|
525 |
// create thread a second time
|
|
526 |
r=t.Create(KThreadName,TestDEF078391ThreadFunction,0x1000,0x1000,0x100000,NULL);
|
|
527 |
test(r==KErrNone);
|
|
528 |
t.Kill(0);
|
|
529 |
CLOSE_AND_WAIT(t);
|
|
530 |
|
|
531 |
// close the heap that got created earlier
|
|
532 |
TestDEF078391Heap->Close();
|
|
533 |
}
|
|
534 |
|
189
|
535 |
void PageBitmapGrowTest()
|
|
536 |
{
|
|
537 |
// Create a large heap to allocate 4 Mb memory (64 * 68 kb).
|
|
538 |
test.Next(_L("Allocate 64 * 68 kbytes to cause page bitmap growing"));
|
|
539 |
RHeap* myHeap;
|
|
540 |
myHeap = UserHeap::ChunkHeap(NULL,0x1000,0x500000,0x1000);
|
|
541 |
test(myHeap!=NULL);
|
|
542 |
TInt OrigSize = myHeap->Size();
|
|
543 |
TUint8* cell[64];
|
|
544 |
// allocate all cells
|
|
545 |
TInt i;
|
|
546 |
RTestHeap* h = (RTestHeap*)myHeap;
|
|
547 |
for (i=0; i<64; ++i)
|
|
548 |
{
|
|
549 |
cell[i] = (TUint8*)h->TestAlloc(0x11000);
|
|
550 |
test(cell[i]!=NULL);
|
|
551 |
}
|
|
552 |
h->FullCheck();
|
|
553 |
|
|
554 |
// Release all allocated buffers by reseting heap
|
|
555 |
TInt Size = myHeap->Size();
|
|
556 |
test(Size > 0x400000);
|
|
557 |
myHeap->Reset();
|
|
558 |
TInt Count = myHeap->AllocSize(Size);
|
|
559 |
test(Count==0);
|
|
560 |
test(Size==0);
|
|
561 |
Size = myHeap->Size();
|
|
562 |
test(Size==OrigSize);
|
|
563 |
|
|
564 |
h->Close();
|
|
565 |
|
|
566 |
}
|
|
567 |
|
0
|
568 |
TInt E32Main()
|
|
569 |
{
|
|
570 |
test.Title();
|
|
571 |
__KHEAP_MARK;
|
|
572 |
test.Start(_L("Testing heaps"));
|
|
573 |
TestDEF078391();
|
|
574 |
StressTests();
|
|
575 |
ReAllocTests();
|
189
|
576 |
//
|
|
577 |
// Some special tests for slab- and paged allocator
|
|
578 |
//
|
|
579 |
PageBitmapGrowTest();
|
0
|
580 |
test.End();
|
|
581 |
__KHEAP_MARKEND;
|
|
582 |
return 0;
|
|
583 |
}
|