os/kernelhwsrv/kerneltest/e32test/heap/t_heap2.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\heap\t_heap2.cpp
sl@0
    15
// Overview:
sl@0
    16
// Tests RHeap class, including a stress test and a "grow in place"
sl@0
    17
// ReAlloc test.
sl@0
    18
// API Information:
sl@0
    19
// RHeap
sl@0
    20
// Details:
sl@0
    21
// - Test allocation on fixed length heaps in local, disconnected chunks for
sl@0
    22
// different heap sizes and alignments.  Assumes knowledge of heap
sl@0
    23
// implementation.
sl@0
    24
// - Test allocation, free, reallocation and compression on chunk heaps with
sl@0
    25
// different maximum and minimum lengths and alignments.  Assumes knowledge
sl@0
    26
// of heap implementation.      
sl@0
    27
// - Stress test heap implementation with a single thread that allocates, frees
sl@0
    28
// and reallocates cells, and checks the heap.
sl@0
    29
// - Stress test heap implementation with two threads that run concurrently.
sl@0
    30
// - Create a chunk heap, test growing in place by allocating a cell and 
sl@0
    31
// then reallocating additional space until failure, verify that the cell 
sl@0
    32
// did not move and the size was increased.
sl@0
    33
// - The heap is checked to verify that no cells remain allocated after the 
sl@0
    34
// tests are complete.
sl@0
    35
// Platforms/Drives/Compatibility:
sl@0
    36
// All
sl@0
    37
// Assumptions/Requirement/Pre-requisites:
sl@0
    38
// Failures and causes:
sl@0
    39
// Base Port information:
sl@0
    40
// 
sl@0
    41
//
sl@0
    42
sl@0
    43
#include <e32test.h>
sl@0
    44
#include <e32hal.h>
sl@0
    45
#include <e32def.h>
sl@0
    46
#include <e32def_private.h>
sl@0
    47
sl@0
    48
// Needed for KHeapShrinkHysRatio which is now ROM 'patchdata'
sl@0
    49
#include "TestRHeapShrink.h"
sl@0
    50
sl@0
    51
#define DECL_GET(T,x)		inline T x() const {return i##x;}
sl@0
    52
#define DECL_GET2(T,x,y)	inline T y() const {return i##x;}
sl@0
    53
sl@0
    54
sl@0
    55
#ifdef __EABI__
sl@0
    56
       IMPORT_D extern const TInt KHeapMinCellSize;
sl@0
    57
#else
sl@0
    58
       const TInt KHeapMinCellSize = 0;
sl@0
    59
#endif
sl@0
    60
sl@0
    61
RTest test(_L("T_HEAP2"));
sl@0
    62
sl@0
    63
#define	TEST_ALIGN(p,a)		test((TLinAddr(p)&((a)-1))==0)
sl@0
    64
sl@0
    65
struct STestCell
sl@0
    66
	{
sl@0
    67
	enum {EMagic = 0xb8aa3b29};
sl@0
    68
sl@0
    69
	TUint32 iLength;
sl@0
    70
	TUint32 iData[1];
sl@0
    71
sl@0
    72
	void Set(TInt aLength);
sl@0
    73
	void Verify(TInt aLength);
sl@0
    74
	void Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength);
sl@0
    75
	};
sl@0
    76
sl@0
    77
void STestCell::Set(TInt aLength)
sl@0
    78
	{
sl@0
    79
	TInt i;
sl@0
    80
	TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic;
sl@0
    81
	aLength -= RHeap::EAllocCellSize;
sl@0
    82
	if (aLength==0)
sl@0
    83
		return;
sl@0
    84
	iLength = x;
sl@0
    85
	aLength /= sizeof(TUint32);
sl@0
    86
	for (i=0; i<aLength-1; ++i)
sl@0
    87
		{
sl@0
    88
		x *= 69069;
sl@0
    89
		x += 41;
sl@0
    90
		iData[i] = x;
sl@0
    91
		}
sl@0
    92
	}
sl@0
    93
sl@0
    94
void STestCell::Verify(TInt aLength)
sl@0
    95
	{
sl@0
    96
	Verify(this, aLength, aLength);
sl@0
    97
	}
sl@0
    98
sl@0
    99
void STestCell::Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength)
sl@0
   100
	{
sl@0
   101
	TInt i;
sl@0
   102
	TUint32 x = (TUint32)aInitPtr ^ (TUint32)aInitLength ^ (TUint32)EMagic;
sl@0
   103
	aLength -= RHeap::EAllocCellSize;
sl@0
   104
	if (aLength==0)
sl@0
   105
		return;
sl@0
   106
	test(iLength == x);
sl@0
   107
	aLength /= sizeof(TUint32);
sl@0
   108
	for (i=0; i<aLength-1; ++i)
sl@0
   109
		{
sl@0
   110
		x *= 69069;
sl@0
   111
		x += 41;
sl@0
   112
		test(iData[i] == x);
sl@0
   113
		}
sl@0
   114
	}
sl@0
   115
sl@0
   116
class RTestHeap : public RHeap
sl@0
   117
	{
sl@0
   118
public:
sl@0
   119
	DECL_GET(TInt,AccessCount)
sl@0
   120
	DECL_GET(TInt,HandleCount)
sl@0
   121
	DECL_GET(TInt*,Handles)
sl@0
   122
	DECL_GET(TUint32,Flags)
sl@0
   123
	DECL_GET(TInt,CellCount)
sl@0
   124
	DECL_GET(TInt,TotalAllocSize)
sl@0
   125
	DECL_GET(TInt,MinLength)
sl@0
   126
	DECL_GET(TInt,Offset)
sl@0
   127
	DECL_GET(TInt,GrowBy)
sl@0
   128
	DECL_GET(TInt,ChunkHandle)
sl@0
   129
	DECL_GET2(const RFastLock&,Lock,LockRef)
sl@0
   130
	DECL_GET(TUint8*,Top)
sl@0
   131
	DECL_GET(TInt,Align)
sl@0
   132
	DECL_GET(TInt,MinCell)
sl@0
   133
	DECL_GET(TInt,PageSize)
sl@0
   134
	DECL_GET2(const SCell&,Free,FreeRef)
sl@0
   135
public:
sl@0
   136
	TInt CheckAllocatedCell(const TAny* aCell) const;
sl@0
   137
	void FullCheckAllocatedCell(const TAny* aCell) const;
sl@0
   138
	TAny* TestAlloc(TInt aSize);
sl@0
   139
	void TestFree(TAny* aPtr);
sl@0
   140
	TAny* TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
sl@0
   141
	void FullCheck();
sl@0
   142
	static void WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
sl@0
   143
	TInt FreeCellLen(const TAny* aPtr) const;
sl@0
   144
	static RTestHeap* FixedHeap(TInt aMaxLength, TInt aAlign=0, TBool aSingleThread=ETrue);
sl@0
   145
	void TakeChunkOwnership(RChunk aChunk);
sl@0
   146
	TInt LastFreeCellLen(void) const;
sl@0
   147
	TInt CalcComp(TInt aCompSize);
sl@0
   148
	void ForceCompress(TInt aFreed);
sl@0
   149
	};
sl@0
   150
sl@0
   151
TInt RTestHeap::CheckAllocatedCell(const TAny* aCell) const
sl@0
   152
	{
sl@0
   153
	SCell* pC = GetAddress(aCell);
sl@0
   154
	TInt len = pC->len;
sl@0
   155
	TUint8* pEnd = (TUint8*)pC + len;
sl@0
   156
	TEST_ALIGN(aCell, iAlign);
sl@0
   157
	TEST_ALIGN(len, iAlign);
sl@0
   158
	test(len >= iMinCell);
sl@0
   159
	test((TUint8*)pC>=iBase && pEnd<=iTop);
sl@0
   160
	return len;
sl@0
   161
	}
sl@0
   162
sl@0
   163
void RTestHeap::FullCheckAllocatedCell(const TAny* aCell) const
sl@0
   164
	{
sl@0
   165
	((STestCell*)aCell)->Verify(CheckAllocatedCell(aCell));
sl@0
   166
	}
sl@0
   167
sl@0
   168
TAny* RTestHeap::TestAlloc(TInt aSize)
sl@0
   169
	{
sl@0
   170
	TAny* p = Alloc(aSize);
sl@0
   171
	if (p)
sl@0
   172
		{
sl@0
   173
		TInt len = CheckAllocatedCell(p);
sl@0
   174
		test((len-RHeap::EAllocCellSize)>=aSize);
sl@0
   175
		((STestCell*)p)->Set(len);
sl@0
   176
		}
sl@0
   177
	return p;
sl@0
   178
	}
sl@0
   179
sl@0
   180
void RTestHeap::TestFree(TAny* aPtr)
sl@0
   181
	{
sl@0
   182
	if (aPtr)
sl@0
   183
		FullCheckAllocatedCell(aPtr);
sl@0
   184
	Free(aPtr);
sl@0
   185
	}
sl@0
   186
sl@0
   187
TAny* RTestHeap::TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode)
sl@0
   188
	{
sl@0
   189
	TInt old_len = aPtr ? CheckAllocatedCell(aPtr) : 0;
sl@0
   190
	if (aPtr)
sl@0
   191
		((STestCell*)aPtr)->Verify(old_len);
sl@0
   192
	TAny* p = ReAlloc(aPtr, aSize, aMode);
sl@0
   193
	if (!p)
sl@0
   194
		{
sl@0
   195
		((STestCell*)aPtr)->Verify(old_len);
sl@0
   196
		return p;
sl@0
   197
		}
sl@0
   198
	TInt new_len = CheckAllocatedCell(p);
sl@0
   199
	test((new_len-RHeap::EAllocCellSize)>=aSize);
sl@0
   200
	if (p == aPtr)
sl@0
   201
		{
sl@0
   202
		((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len));
sl@0
   203
		if (new_len != old_len)
sl@0
   204
			((STestCell*)p)->Set(new_len);
sl@0
   205
		return p;
sl@0
   206
		}
sl@0
   207
	test(!(aMode & ENeverMove));
sl@0
   208
	test((new_len > old_len) || (aMode & EAllowMoveOnShrink));
sl@0
   209
	if (old_len)
sl@0
   210
		((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, new_len));
sl@0
   211
	if (new_len != old_len)
sl@0
   212
		((STestCell*)p)->Set(new_len);
sl@0
   213
	return p;
sl@0
   214
	}
sl@0
   215
sl@0
   216
struct SHeapCellInfo
sl@0
   217
	{
sl@0
   218
	RTestHeap* iHeap;
sl@0
   219
	TInt iTotalAlloc;
sl@0
   220
	TInt iTotalAllocSize;
sl@0
   221
	TInt iTotalFree;
sl@0
   222
	TUint8* iNextCell;
sl@0
   223
	};
sl@0
   224
sl@0
   225
void RTestHeap::WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen)
sl@0
   226
	{
sl@0
   227
	(void)aCell;
sl@0
   228
	::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr;
sl@0
   229
	switch(aType)
sl@0
   230
		{
sl@0
   231
		case EGoodAllocatedCell:
sl@0
   232
			{
sl@0
   233
			test(aCell == info.iNextCell);
sl@0
   234
			TInt len = ((SCell*)aCell)->len;
sl@0
   235
			test(len == aLen);
sl@0
   236
			info.iNextCell += len;
sl@0
   237
			++info.iTotalAlloc;
sl@0
   238
			info.iTotalAllocSize += (aLen-EAllocCellSize);
sl@0
   239
			STestCell* pT = (STestCell*)((TUint8*)aCell + EAllocCellSize);
sl@0
   240
			pT->Verify(len);
sl@0
   241
			break;
sl@0
   242
			}
sl@0
   243
		case EGoodFreeCell:
sl@0
   244
			{
sl@0
   245
			test(aCell == info.iNextCell);
sl@0
   246
			TInt len = ((SCell*)aCell)->len;
sl@0
   247
			test(len == aLen);
sl@0
   248
			info.iNextCell += len;
sl@0
   249
			++info.iTotalFree;
sl@0
   250
			break;
sl@0
   251
			}
sl@0
   252
		default:
sl@0
   253
			test.Printf(_L("TYPE=%d ??\n"),aType);
sl@0
   254
			test(0);
sl@0
   255
			break;
sl@0
   256
		}
sl@0
   257
	}
sl@0
   258
sl@0
   259
void RTestHeap::FullCheck()
sl@0
   260
	{
sl@0
   261
	::SHeapCellInfo info;
sl@0
   262
	Mem::FillZ(&info, sizeof(info));
sl@0
   263
	info.iHeap = this;
sl@0
   264
	info.iNextCell = iBase;
sl@0
   265
	DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info);
sl@0
   266
	test(info.iNextCell == iTop);
sl@0
   267
	test(info.iTotalAlloc == iCellCount);
sl@0
   268
	test(info.iTotalAllocSize == iTotalAllocSize);
sl@0
   269
	}
sl@0
   270
sl@0
   271
TInt RTestHeap::FreeCellLen(const TAny* aPtr) const
sl@0
   272
	{
sl@0
   273
	SCell* p = iFree.next;
sl@0
   274
	SCell* q = (SCell*)((TUint8*)aPtr - EAllocCellSize);
sl@0
   275
	for (; p && p!=q; p = p->next) {}
sl@0
   276
	if (p == q)
sl@0
   277
		return p->len - EAllocCellSize;
sl@0
   278
	return -1;
sl@0
   279
	}
sl@0
   280
sl@0
   281
TInt RTestHeap::LastFreeCellLen(void) const
sl@0
   282
	{
sl@0
   283
	SCell* p = iFree.next;
sl@0
   284
	if (p==NULL)
sl@0
   285
		return -1;	
sl@0
   286
	for (; p->next; p=p->next){}
sl@0
   287
	return p->len;
sl@0
   288
	}
sl@0
   289
sl@0
   290
sl@0
   291
/** Checks whether a call to Compress() will actually perform a reduction 
sl@0
   292
	of the heap.
sl@0
   293
	Relies on the free last cell on the heap being cell that has just been freed
sl@0
   294
	plus any extra.
sl@0
   295
	Intended for use by t_heap2.cpp - DoTest4().  
sl@0
   296
	@param aFreedSize The size in bytes of the cell that was freed
sl@0
   297
*/
sl@0
   298
TInt RTestHeap::CalcComp(TInt aFreedSize)
sl@0
   299
	{	
sl@0
   300
	TInt largestCell=0;
sl@0
   301
	largestCell = LastFreeCellLen();
sl@0
   302
	// if the largest cell is too small or it would have been compressed by the
sl@0
   303
	// free operation then return 0.
sl@0
   304
	if (largestCell < iPageSize || aFreedSize >= KHeapShrinkHysRatio*(iGrowBy>>8))
sl@0
   305
		{
sl@0
   306
		return 0;			
sl@0
   307
		}
sl@0
   308
		else
sl@0
   309
		{
sl@0
   310
		return _ALIGN_DOWN(aFreedSize,iPageSize);
sl@0
   311
		}	
sl@0
   312
	}
sl@0
   313
	
sl@0
   314
/** compress the heap if the KHeapShrinkRatio is too large for what we are
sl@0
   315
	expecting in DoTest4().
sl@0
   316
*/
sl@0
   317
void RTestHeap::ForceCompress(TInt aFreed)
sl@0
   318
	{	
sl@0
   319
	if (aFreed < KHeapShrinkHysRatio*(iGrowBy>>8))
sl@0
   320
		{
sl@0
   321
		Compress();
sl@0
   322
		}
sl@0
   323
	}
sl@0
   324
RTestHeap* RTestHeap::FixedHeap(TInt aMaxLength, TInt aAlign, TBool aSingleThread)
sl@0
   325
	{
sl@0
   326
	RChunk c;
sl@0
   327
	TInt bottom = 0x40000;
sl@0
   328
	TInt top = bottom + aMaxLength;
sl@0
   329
	TInt r = c.CreateDisconnectedLocal(bottom, top, top + bottom, EOwnerThread);
sl@0
   330
	if (r!=KErrNone)
sl@0
   331
		return NULL;
sl@0
   332
	TUint8* base = c.Base() + bottom;
sl@0
   333
	RTestHeap* h = (RTestHeap*)UserHeap::FixedHeap(base, aMaxLength, aAlign, aSingleThread);
sl@0
   334
	if (!aAlign)
sl@0
   335
		aAlign = RHeap::ECellAlignment;
sl@0
   336
	test((TUint8*)h == base);
sl@0
   337
	test(h->AccessCount() == 1);
sl@0
   338
	test(h->HandleCount() == (aSingleThread ? 0 : 1));
sl@0
   339
	test(h->Handles() == (aSingleThread ? NULL : (TInt*)&h->LockRef()));
sl@0
   340
	test(h->Flags() == TUint32(RAllocator::EFixedSize | (aSingleThread ? RAllocator::ESingleThreaded : 0)));
sl@0
   341
	test(h->CellCount() == 0);
sl@0
   342
	test(h->TotalAllocSize() == 0);
sl@0
   343
	test(h->MaxLength() == aMaxLength);
sl@0
   344
	test(h->MinLength() == h->Top() - (TUint8*)h);
sl@0
   345
	test(h->Offset() == 0);
sl@0
   346
	test(h->GrowBy() == 0);
sl@0
   347
	test(h->ChunkHandle() == 0);
sl@0
   348
	test(h->Align() == aAlign);
sl@0
   349
	TInt min_cell = _ALIGN_UP((KHeapMinCellSize + Max((TInt)RHeap::EAllocCellSize, (TInt)RHeap::EFreeCellSize)), aAlign);
sl@0
   350
	TInt hdr_len = _ALIGN_UP(sizeof(RHeap) + RHeap::EAllocCellSize, aAlign) - RHeap::EAllocCellSize;
sl@0
   351
	TInt user_len = _ALIGN_DOWN(aMaxLength - hdr_len, aAlign);
sl@0
   352
	test(h->Base() == base + hdr_len);
sl@0
   353
	test(h->MinCell() == min_cell);
sl@0
   354
	test(h->Top() - h->Base() == user_len);
sl@0
   355
	test(h->FreeRef().next == (RHeap::SCell*)h->Base());
sl@0
   356
	h->TakeChunkOwnership(c);
sl@0
   357
	return h;
sl@0
   358
	}
sl@0
   359
sl@0
   360
void RTestHeap::TakeChunkOwnership(RChunk aChunk)
sl@0
   361
	{
sl@0
   362
	iChunkHandle = aChunk.Handle();
sl@0
   363
	++iHandleCount;
sl@0
   364
	iHandles = &iChunkHandle;
sl@0
   365
	}
sl@0
   366
sl@0
   367
sl@0
   368
#define	ACCESS_COUNT(h)		(((RTestHeap*)h)->AccessCount())
sl@0
   369
#define	HANDLE_COUNT(h)		(((RTestHeap*)h)->HandleCount())
sl@0
   370
#define	HANDLES(h)			(((RTestHeap*)h)->Handles())
sl@0
   371
#define	FLAGS(h)			(((RTestHeap*)h)->Flags())
sl@0
   372
#define	CELL_COUNT(h)		(((RTestHeap*)h)->CellCount())
sl@0
   373
#define	TOTAL_ALLOC_SIZE(h)	(((RTestHeap*)h)->TotalAllocSize())
sl@0
   374
#define	MIN_LENGTH(h)		(((RTestHeap*)h)->MinLength())
sl@0
   375
#define	OFFSET(h)			(((RTestHeap*)h)->Offset())
sl@0
   376
#define	GROW_BY(h)			(((RTestHeap*)h)->GrowBy())
sl@0
   377
#define	CHUNK_HANDLE(h)		(((RTestHeap*)h)->ChunkHandle())
sl@0
   378
#define	LOCK_REF(h)			(((RTestHeap*)h)->LockRef())
sl@0
   379
#define	TOP(h)				(((RTestHeap*)h)->Top())
sl@0
   380
#define	ALIGN(h)			(((RTestHeap*)h)->Align())
sl@0
   381
#define	MIN_CELL(h)			(((RTestHeap*)h)->MinCell())
sl@0
   382
#define	PAGE_SIZE(h)		(((RTestHeap*)h)->PageSize())
sl@0
   383
#define	FREE_REF(h)			(((RTestHeap*)h)->FreeRef())
sl@0
   384
sl@0
   385
void DoTest1(RHeap* aH)
sl@0
   386
	{
sl@0
   387
	RTestHeap* h = (RTestHeap*)aH;
sl@0
   388
	test.Printf(_L("Test Alloc: min=%x max=%x align=%d growby=%d\n"),
sl@0
   389
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
   390
	TInt l;
sl@0
   391
	TAny* p = NULL;
sl@0
   392
	TUint8* next = h->Base();
sl@0
   393
	TUint8* top = h->Top();
sl@0
   394
	TUint8* limit = (TUint8*)h + h->MaxLength();
sl@0
   395
	TBool fixed = h->Flags() & RAllocator::EFixedSize;
sl@0
   396
	for (l=1; l<=1024; ++l)
sl@0
   397
		{
sl@0
   398
		TInt remain1 = top - next;
sl@0
   399
		TInt xl1 = _ALIGN_UP(Max((l+RHeap::EAllocCellSize), h->MinCell()), h->Align());
sl@0
   400
		p = h->TestAlloc(l);
sl@0
   401
		if ( (fixed && remain1 < xl1) || (next + xl1 > limit) )
sl@0
   402
			{
sl@0
   403
			test(p == NULL);
sl@0
   404
			test(top == h->Top());
sl@0
   405
			test.Printf(_L("Alloc failed at l=%d next=%08x\n"), l, next);
sl@0
   406
			break;
sl@0
   407
			}
sl@0
   408
		test(p == next + RHeap::EAllocCellSize);
sl@0
   409
		if (xl1 > remain1)
sl@0
   410
			{
sl@0
   411
			// no room for this cell
sl@0
   412
			TInt g = h->GrowBy();
sl@0
   413
			while (xl1 > remain1)
sl@0
   414
				{
sl@0
   415
				top += g;
sl@0
   416
				remain1 += g;
sl@0
   417
				}
sl@0
   418
			}
sl@0
   419
		test(top == h->Top());
sl@0
   420
		if (xl1 + h->MinCell() > remain1)
sl@0
   421
			{
sl@0
   422
			// this cell fits but remainder is too small or nonexistent
sl@0
   423
			xl1 = top - next;
sl@0
   424
			next = top;
sl@0
   425
			test(h->FreeRef().next == NULL);
sl@0
   426
			}
sl@0
   427
		else
sl@0
   428
			{
sl@0
   429
			// this cell fits and remainder can be reused
sl@0
   430
			next += xl1;
sl@0
   431
			}
sl@0
   432
		test(aH->AllocLen(p) == xl1 - RHeap::EAllocCellSize);
sl@0
   433
		}
sl@0
   434
	h->FullCheck();
sl@0
   435
	}
sl@0
   436
sl@0
   437
void DoTest2(RHeap* aH)
sl@0
   438
	{
sl@0
   439
	RTestHeap* h = (RTestHeap*)aH;
sl@0
   440
	test.Printf(_L("Test Free: min=%x max=%x align=%d growby=%d\n"),
sl@0
   441
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
   442
	TInt al;
sl@0
   443
	TInt min = h->MinCell();
sl@0
   444
	TBool pad = EFalse;
sl@0
   445
	for (al=1; al<256; (void)((pad=!pad)!=0 || (al+=al+1)) )
sl@0
   446
		{
sl@0
   447
		TAny* p[32];
sl@0
   448
		TInt last_len = 0;
sl@0
   449
		TAny* last = NULL;
sl@0
   450
		TInt i;
sl@0
   451
		test.Printf(_L("al=%d pad=%d\n"), al, pad);
sl@0
   452
		TUint8* top=0;
sl@0
   453
		TAny* spare=0;
sl@0
   454
		TBool heapReduced = EFalse;
sl@0
   455
		for (i=0; i<32; ++i)
sl@0
   456
			{
sl@0
   457
			// Check whether the cell created for the allocation of al would end up
sl@0
   458
			// including extra bytes from the last free cell that aren't enough
sl@0
   459
			// to create a new free cell.
sl@0
   460
			top = h->Top();
sl@0
   461
			TInt freeLen=h->LastFreeCellLen();
sl@0
   462
			TInt actualAllocBytes = Max(_ALIGN_UP(al + RHeap::EAllocCellSize, h->Align()), min);
sl@0
   463
			TInt remainingBytes = freeLen - actualAllocBytes;
sl@0
   464
			if (remainingBytes < min)
sl@0
   465
				{
sl@0
   466
				// Force the heap to grow so that once this allocation is freed
sl@0
   467
				// the free cell left will be large enough to include the al allocation
sl@0
   468
				// and to create a new free cell if necessary.
sl@0
   469
				actualAllocBytes = _ALIGN_UP(actualAllocBytes + min, h->Align());
sl@0
   470
				TAny* q = h->TestAlloc(actualAllocBytes);
sl@0
   471
				// Check heap has grown
sl@0
   472
				test(top < h->Top());
sl@0
   473
				top = h->Top();
sl@0
   474
				test(q!=NULL);
sl@0
   475
				// Have grown the heap so allocate a cell as a place holder to stop
sl@0
   476
				// the heap being shrunk and the actual cell we want to allocate from being the
sl@0
   477
				// wrong size
sl@0
   478
				spare=h->TestAlloc(8);
sl@0
   479
				h->TestFree(q);
sl@0
   480
				// Ensure heap wasn't shrunk after free
sl@0
   481
				test(top == h->Top());
sl@0
   482
				}
sl@0
   483
			top = h->Top();
sl@0
   484
			// Allocate the new 
sl@0
   485
			p[i] = h->TestAlloc(al);
sl@0
   486
			test(p[i]!=NULL);
sl@0
   487
			if (remainingBytes < min)
sl@0
   488
				{// now safe to free any padding as p[i] now allocated and its size can't change
sl@0
   489
				h->TestFree(spare);
sl@0
   490
				}
sl@0
   491
			TInt tmp1=h->AllocLen(p[i]);
sl@0
   492
			TInt tmp2=Max(_ALIGN_UP(al+RHeap::EAllocCellSize,h->Align()), min)-RHeap::EAllocCellSize;
sl@0
   493
			test(tmp1 == tmp2);
sl@0
   494
			}
sl@0
   495
		last = (TUint8*)p[31] + _ALIGN_UP(Max((al + RHeap::EAllocCellSize), min), h->Align());
sl@0
   496
		last_len = h->FreeCellLen(last);
sl@0
   497
		test(last_len > 0);
sl@0
   498
		if (pad)
sl@0
   499
			{
sl@0
   500
			test(h->TestAlloc(last_len) == last);
sl@0
   501
			test(h->FreeRef().next == NULL);
sl@0
   502
			}
sl@0
   503
		else
sl@0
   504
			last = NULL;
sl@0
   505
		top = h->Top();
sl@0
   506
		for (i=0,heapReduced=EFalse; i<32; ++i)
sl@0
   507
			{
sl@0
   508
			h->TestFree(p[i]);
sl@0
   509
			TInt fl = h->FreeCellLen(p[i]);
sl@0
   510
			TInt xfl = _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
sl@0
   511
			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   512
				{
sl@0
   513
				top = h->Top();
sl@0
   514
				heapReduced = ETrue;
sl@0
   515
				}
sl@0
   516
sl@0
   517
			if (i < 31 || pad)
sl@0
   518
				test(fl == xfl);
sl@0
   519
			else
sl@0
   520
				{
sl@0
   521
				if (!heapReduced)
sl@0
   522
					test(fl == xfl + RHeap::EAllocCellSize + last_len);
sl@0
   523
				else
sl@0
   524
					{
sl@0
   525
					heapReduced = EFalse;
sl@0
   526
					}
sl@0
   527
				}
sl@0
   528
			test(h->TestAlloc(al)==p[i]);
sl@0
   529
			}
sl@0
   530
		for (i=0,heapReduced=EFalse; i<31; ++i)
sl@0
   531
			{
sl@0
   532
			TInt j = i+1;
sl@0
   533
			TUint8* q;
sl@0
   534
			// Free to adjacent cells and check that the free cell left is the combined
sl@0
   535
			// size of the 2 adjacent cells just freed
sl@0
   536
			h->TestFree(p[i]);
sl@0
   537
			h->TestFree(p[j]);
sl@0
   538
			TInt fl = h->FreeCellLen(p[i]);
sl@0
   539
			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   540
				{
sl@0
   541
				top = h->Top();
sl@0
   542
				heapReduced = ETrue;
sl@0
   543
				}
sl@0
   544
			TInt xfl = 2 * _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
sl@0
   545
			if (j < 31 || pad)
sl@0
   546
				test(fl == xfl);
sl@0
   547
			else
sl@0
   548
				{
sl@0
   549
				if (!heapReduced)
sl@0
   550
					test(fl == xfl + RHeap::EAllocCellSize + last_len);
sl@0
   551
				else
sl@0
   552
					{
sl@0
   553
					heapReduced = EFalse;
sl@0
   554
					}
sl@0
   555
				}
sl@0
   556
			test(h->FreeCellLen(p[j]) < 0);
sl@0
   557
			test(h->TestAlloc(fl)==p[i]);
sl@0
   558
			test(h->Top() == top);
sl@0
   559
			h->TestFree(p[i]);
sl@0
   560
			test(h->FreeCellLen(p[i]) == fl);
sl@0
   561
			// test when you alloc a cell that is larger than cells just freed
sl@0
   562
			// that its position is not the same as the freed cells
sl@0
   563
			// will hold for all cells except top/last one
sl@0
   564
			if (j < 31 && !pad && fl < last_len)
sl@0
   565
				{
sl@0
   566
				q = (TUint8*)h->TestAlloc(fl+1);
sl@0
   567
				if (h->Top() > top)
sl@0
   568
					top = h->Top();
sl@0
   569
				test(h->Top() == top);
sl@0
   570
				test(q > p[i]);
sl@0
   571
				h->TestFree(q);
sl@0
   572
				if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   573
					{
sl@0
   574
					top = h->Top();
sl@0
   575
					heapReduced = ETrue;
sl@0
   576
					}
sl@0
   577
				}
sl@0
   578
			// check cell that is just smaller than space but not small enough 
sl@0
   579
			// for a new free cell to be created, is the size of whole free cell
sl@0
   580
			test(h->TestAlloc(fl-min+1)==p[i]);
sl@0
   581
			test(h->Top() == top);
sl@0
   582
			test(h->AllocLen(p[i])==fl);
sl@0
   583
			h->TestFree(p[i]);
sl@0
   584
			// Check cell that is small enough for new free cell and alloc'd cell to be
sl@0
   585
			// created at p[i] cell is created at p[i]
sl@0
   586
			test(h->TestAlloc(fl-min)==p[i]);
sl@0
   587
			test(h->Top() == top);
sl@0
   588
			// check free cell is at expected position
sl@0
   589
			q = (TUint8*)p[i] + fl - min + RHeap::EAllocCellSize;
sl@0
   590
			test(h->FreeCellLen(q) == min - RHeap::EAllocCellSize);
sl@0
   591
			// alloc 0 length cell at q, will work as new cell of min length will be created
sl@0
   592
			test(h->TestAlloc(0) == q);
sl@0
   593
			test(h->Top() == top);
sl@0
   594
			h->TestFree(p[i]);
sl@0
   595
			test(h->FreeCellLen(p[i]) == fl - min);
sl@0
   596
			h->TestFree(q);
sl@0
   597
			// again check free cells are combined
sl@0
   598
			test(h->FreeCellLen(q) < 0);
sl@0
   599
			test(h->FreeCellLen(p[i]) == fl);
sl@0
   600
			// check reallocating the cells places them back to same positions
sl@0
   601
			test(h->TestAlloc(al)==p[i]);
sl@0
   602
			test(h->Top() == top);
sl@0
   603
			test(h->TestAlloc(al)==p[j]);
sl@0
   604
			test(h->Top() == top);
sl@0
   605
			if (pad)
sl@0
   606
				test(h->FreeRef().next == NULL);
sl@0
   607
			}
sl@0
   608
		for (i=0,heapReduced=EFalse; i<30; ++i)
sl@0
   609
			{
sl@0
   610
			TInt j = i+1;
sl@0
   611
			TInt k = i+2;
sl@0
   612
			TUint8* q;
sl@0
   613
			// Free 3 adjacent cells and check free cell created is combined size
sl@0
   614
			h->TestFree(p[i]);
sl@0
   615
			h->TestFree(p[k]);
sl@0
   616
			h->TestFree(p[j]);
sl@0
   617
			h->FullCheck();
sl@0
   618
			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   619
				{
sl@0
   620
				top = h->Top();
sl@0
   621
				heapReduced = ETrue;
sl@0
   622
				}
sl@0
   623
			TInt fl = h->FreeCellLen(p[i]);
sl@0
   624
			TInt xfl = 3 * _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
sl@0
   625
			if (k < 31 || pad)
sl@0
   626
				test(fl == xfl);
sl@0
   627
			else
sl@0
   628
				{
sl@0
   629
				if (!heapReduced)
sl@0
   630
					test(fl == xfl + RHeap::EAllocCellSize + last_len);
sl@0
   631
				else
sl@0
   632
					{
sl@0
   633
					heapReduced = EFalse;
sl@0
   634
					}
sl@0
   635
				}
sl@0
   636
			test(h->FreeCellLen(p[j]) < 0);
sl@0
   637
			test(h->FreeCellLen(p[k]) < 0);
sl@0
   638
			//ensure created free cell is allocated to new cell of free cell size
sl@0
   639
			test(h->TestAlloc(fl)==p[i]);
sl@0
   640
			test(h->Top() == top);
sl@0
   641
			h->TestFree(p[i]);
sl@0
   642
			test(h->FreeCellLen(p[i]) == fl);
sl@0
   643
			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   644
				top = h->Top();
sl@0
   645
			if (k < 31 && !pad && fl < last_len)
sl@0
   646
				{
sl@0
   647
				// Test new cell one larger than free cell size is allocated somewhere else
sl@0
   648
				q = (TUint8*)h->TestAlloc(fl+1);
sl@0
   649
				if (h->Top() > top)
sl@0
   650
					top = h->Top();
sl@0
   651
				test(h->Top() == top); 
sl@0
   652
				test(q > p[i]);
sl@0
   653
				h->TestFree(q);
sl@0
   654
				if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
sl@0
   655
					{
sl@0
   656
					top = h->Top();
sl@0
   657
					heapReduced = ETrue;
sl@0
   658
					}
sl@0
   659
				}
sl@0
   660
			// check allocating cell just smaller than free cell size but
sl@0
   661
			// too large for neew free cell to be created, is size of whole free cell
sl@0
   662
			test(h->TestAlloc(fl-min+1)==p[i]);
sl@0
   663
			test(h->Top() == top);
sl@0
   664
			test(h->AllocLen(p[i])==fl);
sl@0
   665
			h->TestFree(p[i]);
sl@0
   666
			// ensure free cell is created this time as well as alloc'd cell
sl@0
   667
			test(h->TestAlloc(fl-min)==p[i]);
sl@0
   668
			test(h->Top() == top);
sl@0
   669
			q = (TUint8*)p[i] + fl - min + RHeap::EAllocCellSize;
sl@0
   670
			test(h->FreeCellLen(q) == min - RHeap::EAllocCellSize);
sl@0
   671
			test(h->TestAlloc(0) == q);
sl@0
   672
			test(h->Top() == top);
sl@0
   673
			h->TestFree(p[i]);
sl@0
   674
			test(h->FreeCellLen(p[i]) == fl - min);
sl@0
   675
			h->TestFree(q);
sl@0
   676
			test(h->FreeCellLen(q) < 0);
sl@0
   677
			test(h->FreeCellLen(p[i]) == fl);
sl@0
   678
			// realloc all cells and check heap not expanded
sl@0
   679
			test(h->TestAlloc(al)==p[i]);
sl@0
   680
			test(h->Top() == top);
sl@0
   681
			test(h->TestAlloc(al)==p[j]);
sl@0
   682
			test(h->Top() == top);
sl@0
   683
			test(h->TestAlloc(al)==p[k]);
sl@0
   684
			test(h->Top() == top);
sl@0
   685
			// If padding than no space should left on heap
sl@0
   686
			if (pad)
sl@0
   687
				test(h->FreeRef().next == NULL);
sl@0
   688
			}
sl@0
   689
		// when padding this will free padding from top of heap
sl@0
   690
		h->TestFree(last);
sl@0
   691
		}
sl@0
   692
	h->FullCheck();
sl@0
   693
	}
sl@0
   694
sl@0
   695
void DoTest3(RHeap* aH)
sl@0
   696
	{
sl@0
   697
	RTestHeap* h = (RTestHeap*)aH;
sl@0
   698
	test.Printf(_L("Test ReAlloc: min=%x max=%x align=%d growby=%d\n"),
sl@0
   699
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
   700
	// allocate continuous heap cell, then free them and reallocate again
sl@0
   701
	TInt al;
sl@0
   702
	for (al=1; al<256; al+=al+1)
sl@0
   703
		{
sl@0
   704
		TAny* p0 = h->TestAlloc(al);
sl@0
   705
		TInt al0 = h->AllocLen(p0);
sl@0
   706
		h->TestFree(p0);
sl@0
   707
		TAny* p1 = h->TestReAlloc(NULL, al, 0);
sl@0
   708
		TInt al1 = h->AllocLen(p1);
sl@0
   709
		test(p1 == p0);
sl@0
   710
		test(al1 == al0);
sl@0
   711
		h->TestFree(p1);
sl@0
   712
		TAny* p2 = h->TestAlloc(1);
sl@0
   713
		TAny* p3 = h->TestReAlloc(p2, al, 0);
sl@0
   714
		test(p3 == p0);
sl@0
   715
		TInt al3 = h->AllocLen(p3);
sl@0
   716
		test(al3 == al0);
sl@0
   717
		h->TestFree(p3);
sl@0
   718
		TAny* p4 = h->TestAlloc(1024);
sl@0
   719
		TAny* p5 = h->TestReAlloc(p4, al, 0);
sl@0
   720
		test(p5 == p0);
sl@0
   721
		TInt al5 = h->AllocLen(p5);
sl@0
   722
		test(al5 == al0);
sl@0
   723
		h->TestFree(p5);
sl@0
   724
		}
sl@0
   725
	TInt i;
sl@0
   726
	TInt j;
sl@0
   727
	for (j=0; j<30; j+=3)
sl@0
   728
		{
sl@0
   729
		TAny* p[30];
sl@0
   730
		TInt ala[30];
sl@0
   731
		TInt fla[30];
sl@0
   732
		h->Reset();
sl@0
   733
		for (i=0; i<30; ++i)
sl@0
   734
			{
sl@0
   735
			p[i] = h->TestAlloc(8*i*i);
sl@0
   736
			ala[i] = h->AllocLen(p[i]);
sl@0
   737
			fla[i] = 0;
sl@0
   738
			}
sl@0
   739
		for (i=1; i<30; i+=3)
sl@0
   740
			{
sl@0
   741
			h->TestFree(p[i]);
sl@0
   742
			fla[i] = h->FreeCellLen(p[i]);
sl@0
   743
			test(fla[i] == ala[i]);
sl@0
   744
			test(h->FreeCellLen(p[i-1]) < 0);
sl@0
   745
			test(h->FreeCellLen(p[i+1]) < 0);
sl@0
   746
			}
sl@0
   747
		h->FullCheck();
sl@0
   748
		TInt al1 = _ALIGN_UP(Max((RHeap::EAllocCellSize + 1), h->MinCell()), h->Align());
sl@0
   749
		// adjust al1 for some case when reallocated heap cell will not be shrinked because remainder will not big enough
sl@0
   750
		// to form a new free cell due to a big KHeapMinCellSize value
sl@0
   751
		TInt alaj = ala[j] + RHeap::EAllocCellSize;
sl@0
   752
		if (al1 < alaj && alaj - al1 < h->MinCell())
sl@0
   753
			al1 = alaj;
sl@0
   754
		TAny* p1 = h->TestReAlloc(p[j], 1, RHeap::ENeverMove);
sl@0
   755
		test(p1 == p[j]);
sl@0
   756
		test(h->AllocLen(p1) == al1 - RHeap::EAllocCellSize);
sl@0
   757
		TAny* p1b = (TUint8*)p1 + al1;
sl@0
   758
		test(h->FreeCellLen(p1b) == fla[j+1] + RHeap::EAllocCellSize + ala[j] - al1);
sl@0
   759
		TInt l2 = ala[j] + fla[j+1] + RHeap::EAllocCellSize; // max without moving
sl@0
   760
		TInt l3 = l2 - h->MinCell();
sl@0
   761
		TAny* p3 = h->TestReAlloc(p[j], l3, RHeap::ENeverMove);
sl@0
   762
		test(p3 == p[j]);
sl@0
   763
		TAny* p3b = (TUint8*)p3 + h->AllocLen(p3) + RHeap::EAllocCellSize;
sl@0
   764
		test(h->FreeCellLen(p3b) == h->MinCell() - RHeap::EAllocCellSize);
sl@0
   765
		TAny* p2 = h->TestReAlloc(p[j], l2, RHeap::ENeverMove);
sl@0
   766
		test(p2 == p[j]);
sl@0
   767
		test(h->AllocLen(p2) == l2);
sl@0
   768
		TAny* p4 = h->TestReAlloc(p[j], l2+1, RHeap::ENeverMove);
sl@0
   769
		test(p4 == NULL);
sl@0
   770
		test(h->AllocLen(p2) == l2);
sl@0
   771
		TAny* p5 = h->TestReAlloc(p[j], l2+1, 0);
sl@0
   772
		TInt k = 0;
sl@0
   773
		for (; k<30 && fla[k] <= l2; ++k) {}
sl@0
   774
		if (k < 30)
sl@0
   775
			test(p5 == p[k]);
sl@0
   776
		else
sl@0
   777
			test(p5 >= (TUint8*)p[29] + ala[29]);
sl@0
   778
		test(h->FreeCellLen(p2) == ala[j] + ala[j+1] + RHeap::EAllocCellSize);
sl@0
   779
		TInt ali = _ALIGN_UP(RHeap::EAllocCellSize,h->Align());
sl@0
   780
		TAny* p6b = (TUint8*)p[j+2] + ala[j+2] - ali + RHeap::EAllocCellSize;
sl@0
   781
		test(h->FreeCellLen(p6b) < 0);
sl@0
   782
		TAny* p6 = h->TestReAlloc(p[j+2], ala[j+2] - ali , 0);
sl@0
   783
		test(p6 == p[j+2]);
sl@0
   784
		if (h->AllocLen(p6) != ala[j+2]) // allocated heap cell size changed
sl@0
   785
			test(h->FreeCellLen(p6b) == h->MinCell() - RHeap::EAllocCellSize);
sl@0
   786
		TInt g = h->GrowBy();
sl@0
   787
		TAny* p7 = h->TestReAlloc(p5, 8*g, 0);
sl@0
   788
		test(p7 >= p5);
sl@0
   789
		TUint8* p8 = (TUint8*)p7 - RHeap::EAllocCellSize + al1;
sl@0
   790
		TUint8* p9 = (TUint8*)_ALIGN_UP(TLinAddr(p8), h->PageSize());
sl@0
   791
		if (p9-p8 < h->MinCell())
sl@0
   792
			p9 += h->PageSize();
sl@0
   793
		TAny* p7b = h->TestReAlloc(p7, 1, 0);
sl@0
   794
		test(p7b == p7);
sl@0
   795
		test(h->Top() + (RHeap::EAllocCellSize & (h->Align()-1)) == p9);
sl@0
   796
sl@0
   797
		h->FullCheck();
sl@0
   798
		}
sl@0
   799
	}
sl@0
   800
sl@0
   801
// Test compression
sl@0
   802
// {1 free cell, >1 free cell} x {reduce cell, eliminate cell, reduce cell but too small}
sl@0
   803
//
sl@0
   804
void DoTest4(RHeap* aH)
sl@0
   805
	{
sl@0
   806
	RTestHeap* h = (RTestHeap*)aH;
sl@0
   807
	test.Printf(_L("Test Compress: min=%x max=%x align=%d growby=%d\n"),
sl@0
   808
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
   809
	TInt page_size;
sl@0
   810
	UserHal::PageSizeInBytes(page_size);
sl@0
   811
	test(page_size == h->PageSize());
sl@0
   812
	TInt g = h->GrowBy();
sl@0
   813
	TEST_ALIGN(g, page_size);
sl@0
   814
	test(g >= page_size);
sl@0
   815
	RChunk c;
sl@0
   816
	c.SetHandle(h->ChunkHandle());
sl@0
   817
	TInt align = h->Align();
sl@0
   818
	TInt minc = h->MinCell();
sl@0
   819
sl@0
   820
	TInt orig_size = c.Size();
sl@0
   821
	TUint8* orig_top = h->Top();
sl@0
   822
sl@0
   823
	// size in bytes that last free cell on the top of the heap must be 
sl@0
   824
	// before the heap will be shrunk, size must include the no of bytes to
sl@0
   825
	// store the cell data/header i.e RHeap::EAllocCellSize
sl@0
   826
	TInt shrinkThres = KHeapShrinkHysRatio*(g>>8);
sl@0
   827
sl@0
   828
	TInt pass;
sl@0
   829
	for (pass=0; pass<2; ++pass)
sl@0
   830
		{
sl@0
   831
		TUint8* p0 = (TUint8*)h->TestAlloc(4);
sl@0
   832
		test(p0 == h->Base() + RHeap::EAllocCellSize);
sl@0
   833
		TInt l1 = h->Top() - (TUint8*)h->FreeRef().next;
sl@0
   834
		TEST_ALIGN(l1, align);
sl@0
   835
		l1 -= RHeap::EAllocCellSize;
sl@0
   836
		TUint8* p1;
sl@0
   837
		// Grow heap by 2*iGrowBy bytes
sl@0
   838
		p1 = (TUint8*)h->TestAlloc(l1 + 2*g);
sl@0
   839
		test(p1 == p0 + h->AllocLen(p0) + RHeap::EAllocCellSize);
sl@0
   840
		test(h->Top() - orig_top == 2*g);
sl@0
   841
		test(c.Size() - orig_size == 2*g);
sl@0
   842
		// May compress heap, may not
sl@0
   843
		h->TestFree(p1);
sl@0
   844
		h->ForceCompress(2*g);
sl@0
   845
		test(h->Top() == orig_top);
sl@0
   846
		test(c.Size() == orig_size);
sl@0
   847
		test((TUint8*)h->FreeRef().next == p1 - RHeap::EAllocCellSize);
sl@0
   848
		h->FullCheck();
sl@0
   849
		//if KHeapShrinkHysRatio is > 2.0 then heap compression will occur here
sl@0
   850
		test(h->Compress() == 0);
sl@0
   851
		test(h->TestAlloc(l1) == p1);
sl@0
   852
		test(h->FreeRef().next == NULL);
sl@0
   853
		if (pass)
sl@0
   854
			h->TestFree(p0);	// leave another free cell on second pass
sl@0
   855
		TInt l2 = g - RHeap::EAllocCellSize;
sl@0
   856
		// Will grow heap by iGrowBy bytes
sl@0
   857
		TUint8* p2 = (TUint8*)h->TestAlloc(l2);
sl@0
   858
		test(p2 == orig_top + RHeap::EAllocCellSize);
sl@0
   859
		test(h->Top() - orig_top == g);
sl@0
   860
		test(c.Size() - orig_size == g);
sl@0
   861
		// may or may not compress heap
sl@0
   862
		h->TestFree(p2);
sl@0
   863
		if (l2+RHeap::EAllocCellSize >= shrinkThres)
sl@0
   864
			{
sl@0
   865
			// When KHeapShrinkRatio small enough heap will have been compressed
sl@0
   866
			test(h->Top() == orig_top);			
sl@0
   867
			if (pass)
sl@0
   868
				{
sl@0
   869
				test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
sl@0
   870
				test((TUint8*)h->FreeRef().next->next == NULL);
sl@0
   871
				}
sl@0
   872
			else
sl@0
   873
				test((TUint8*)h->FreeRef().next == NULL);
sl@0
   874
			}
sl@0
   875
		else
sl@0
   876
			{			
sl@0
   877
			test(h->Top() - orig_top == g);
sl@0
   878
			if (pass)
sl@0
   879
				{
sl@0
   880
				test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
sl@0
   881
				test((TUint8*)h->FreeRef().next->next == orig_top);
sl@0
   882
				}
sl@0
   883
			else
sl@0
   884
				test((TUint8*)h->FreeRef().next == orig_top);
sl@0
   885
			}
sl@0
   886
		// this compress will only do anything if the KHeapShrinkRatio is large 
sl@0
   887
		// enough to introduce hysteresis otherwise the heap would have been compressed 
sl@0
   888
		// by the free operation itself
sl@0
   889
		TInt tmp1,tmp2;
sl@0
   890
		tmp2=h->CalcComp(g);
sl@0
   891
		tmp1=h->Compress();
sl@0
   892
		test(tmp1 == tmp2);
sl@0
   893
		test(h->Top() == orig_top);
sl@0
   894
		test(c.Size() == orig_size);
sl@0
   895
		h->FullCheck();
sl@0
   896
		// shouldn't compress heap as already compressed
sl@0
   897
		test(h->Compress() == 0);
sl@0
   898
		//grow heap by iGrowBy bytes
sl@0
   899
		test(h->TestAlloc(l2) == p2);
sl@0
   900
		//grow heap by iGrowBy bytes
sl@0
   901
		TUint8* p3 = (TUint8*)h->TestAlloc(l2);
sl@0
   902
		test(p3 == p2 + g);
sl@0
   903
		test(h->Top() - orig_top == 2*g);
sl@0
   904
		test(c.Size() - orig_size == 2*g);
sl@0
   905
		// may or may not reduce heap
sl@0
   906
		h->TestFree(p2);
sl@0
   907
		// may or may not reduce heap
sl@0
   908
		h->TestFree(p3);
sl@0
   909
		h->ForceCompress(2*g);
sl@0
   910
		test(h->Top() == orig_top);
sl@0
   911
		test(c.Size() == orig_size);
sl@0
   912
		h->FullCheck();
sl@0
   913
		if (pass)
sl@0
   914
			{
sl@0
   915
			test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
sl@0
   916
			test((TUint8*)h->FreeRef().next->next == NULL);
sl@0
   917
			}
sl@0
   918
		else
sl@0
   919
			test((TUint8*)h->FreeRef().next == NULL);
sl@0
   920
		//grow heap by iGrowBy bytes
sl@0
   921
		test(h->TestAlloc(l2) == p2);
sl@0
   922
		//grow heap by iGrowBy*2 + page size bytes
sl@0
   923
		test(h->TestAlloc(l2 + g + page_size) == p3);
sl@0
   924
		test(h->Top() - orig_top == 4*g);
sl@0
   925
		test(c.Size() - orig_size == 4*g);
sl@0
   926
		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatioDflt
sl@0
   927
		test(h->TestReAlloc(p3, page_size - RHeap::EAllocCellSize, 0) == p3);
sl@0
   928
		h->ForceCompress(g+page_size);
sl@0
   929
		test(h->Top() - orig_top == g + page_size);
sl@0
   930
		test(c.Size() - orig_size == g + page_size);
sl@0
   931
		h->FullCheck();
sl@0
   932
		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatio1
sl@0
   933
		h->TestFree(p2);
sl@0
   934
		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatio1 && g<=page_size
sl@0
   935
		// or KHeapShrinkHysRatio >= 2.0 and g==page_size
sl@0
   936
		h->TestFree(p3);
sl@0
   937
		// may or may not perform further compression
sl@0
   938
		tmp1=h->CalcComp(g+page_size);
sl@0
   939
		tmp2=h->Compress();
sl@0
   940
		test(tmp1 == tmp2);
sl@0
   941
		test(h->Top() == orig_top);
sl@0
   942
		test(c.Size() == orig_size);
sl@0
   943
		h->FullCheck();
sl@0
   944
		test(h->TestAlloc(l2 - minc) == p2);
sl@0
   945
		test(h->TestAlloc(l2 + g + page_size + minc) == p3 - minc);
sl@0
   946
		test(h->Top() - orig_top == 4*g);
sl@0
   947
		test(c.Size() - orig_size == 4*g);
sl@0
   948
		h->TestFree(p3 - minc);
sl@0
   949
		h->ForceCompress(l2 + g + page_size + minc);
sl@0
   950
		test(h->Top() - orig_top == g);
sl@0
   951
		test(c.Size() - orig_size == g);
sl@0
   952
		h->FullCheck();
sl@0
   953
		if (pass)
sl@0
   954
			{
sl@0
   955
			test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
sl@0
   956
			test((TUint8*)h->FreeRef().next->next == p3 - minc - RHeap::EAllocCellSize);
sl@0
   957
			}
sl@0
   958
		else
sl@0
   959
			test((TUint8*)h->FreeRef().next == p3 - minc - RHeap::EAllocCellSize);
sl@0
   960
		h->TestFree(p2);
sl@0
   961
		if (l2+RHeap::EAllocCellSize >= shrinkThres)
sl@0
   962
			{
sl@0
   963
			// When KHeapShrinkRatio small enough heap will have been compressed
sl@0
   964
			test(h->Top() == orig_top);
sl@0
   965
			test(c.Size() - orig_size == 0);
sl@0
   966
			}
sl@0
   967
		else
sl@0
   968
			{
sl@0
   969
			test(h->Top() - orig_top == g);
sl@0
   970
			test(c.Size() - orig_size == g);
sl@0
   971
			}
sl@0
   972
		h->FullCheck();
sl@0
   973
		if ( ((TLinAddr)orig_top & (align-1)) == 0)
sl@0
   974
			{
sl@0
   975
			TAny* free;
sl@0
   976
			TEST_ALIGN(p2 - RHeap::EAllocCellSize, page_size);
sl@0
   977
			// will have free space of g-minc
sl@0
   978
			test(h->TestAlloc(l2 + minc) == p2);
sl@0
   979
			test(h->Top() - orig_top == 2*g);
sl@0
   980
			test(c.Size() - orig_size == 2*g);
sl@0
   981
			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
sl@0
   982
			test(free != NULL);
sl@0
   983
			test(h->TestReAlloc(p2, l2 - 4, 0) == p2);
sl@0
   984
			TInt freeSp = g-minc + (l2+minc - (l2-4));
sl@0
   985
			TInt adjust = 0;
sl@0
   986
			if (freeSp >= shrinkThres && freeSp-page_size >= minc)
sl@0
   987
				{
sl@0
   988
				// if page_size is less than growBy (g) then heap will be shrunk
sl@0
   989
				// by less than a whole g.
sl@0
   990
				adjust = g-((page_size<g)?page_size:0);
sl@0
   991
				}
sl@0
   992
			test(h->Top() - orig_top == 2*g - adjust);
sl@0
   993
			test(c.Size() - orig_size == 2*g - adjust);
sl@0
   994
			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
sl@0
   995
			test(free != NULL);
sl@0
   996
			TEST_ALIGN(TLinAddr(free)+4, page_size);
sl@0
   997
			test(h->TestAlloc(l2 + g + page_size + 4) == p3 - 4);
sl@0
   998
			test(h->Top() - orig_top == 4*g - adjust);
sl@0
   999
			test(c.Size() - orig_size == 4*g - adjust);
sl@0
  1000
			h->TestFree(p3 - 4);
sl@0
  1001
			h->ForceCompress(l2 + g + page_size + 4);
sl@0
  1002
			test(h->Top() - orig_top == g + page_size);
sl@0
  1003
			test(c.Size() - orig_size == g + page_size);
sl@0
  1004
			h->FullCheck();
sl@0
  1005
			h->TestFree(p2);
sl@0
  1006
			h->ForceCompress(l2-4);
sl@0
  1007
			test(h->Compress() == 0);
sl@0
  1008
			// check heap is grown, will have free space of g-minc
sl@0
  1009
			test(h->TestAlloc(l2 + minc) == p2);
sl@0
  1010
			test(h->Top() - orig_top == 2*g);
sl@0
  1011
			test(c.Size() - orig_size == 2*g);
sl@0
  1012
			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
sl@0
  1013
			test(free != NULL);
sl@0
  1014
			// may shrink heap as will now have g+minc free bytes
sl@0
  1015
			test(h->TestReAlloc(p2, l2 - minc, 0) == p2);
sl@0
  1016
			if (g+minc >= shrinkThres)
sl@0
  1017
				{
sl@0
  1018
				test(h->Top() - orig_top == g);
sl@0
  1019
				test(c.Size() - orig_size == g);
sl@0
  1020
				}
sl@0
  1021
			else
sl@0
  1022
				{
sl@0
  1023
				test(h->Top() - orig_top == 2*g);
sl@0
  1024
				test(c.Size() - orig_size == 2*g);
sl@0
  1025
				}
sl@0
  1026
			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
sl@0
  1027
			test(free != NULL);
sl@0
  1028
			TEST_ALIGN(TLinAddr(free)+minc, page_size);
sl@0
  1029
			test(h->TestAlloc(l2 + g + page_size + minc) == p3 - minc);
sl@0
  1030
			test(h->Top() - orig_top == 4*g);
sl@0
  1031
			test(c.Size() - orig_size == 4*g);
sl@0
  1032
			h->TestFree(p3 - minc);
sl@0
  1033
			h->ForceCompress(l2 + g + page_size + minc);
sl@0
  1034
			test(h->Top() - orig_top == g);
sl@0
  1035
			test(c.Size() - orig_size == g);
sl@0
  1036
			h->FullCheck();
sl@0
  1037
			h->TestFree(p2);
sl@0
  1038
			}
sl@0
  1039
sl@0
  1040
		h->TestFree(p1);
sl@0
  1041
		if (pass == 0)
sl@0
  1042
			h->TestFree(p0);
sl@0
  1043
		h->Compress();
sl@0
  1044
		}
sl@0
  1045
	h->FullCheck();
sl@0
  1046
	}
sl@0
  1047
sl@0
  1048
void Test1()
sl@0
  1049
	{
sl@0
  1050
	RHeap* h;
sl@0
  1051
	h = RTestHeap::FixedHeap(0x1000, 0);
sl@0
  1052
	test(h != NULL);
sl@0
  1053
	DoTest1(h);
sl@0
  1054
	h->Close();
sl@0
  1055
	h = RTestHeap::FixedHeap(0x1000, 0, EFalse);
sl@0
  1056
	test(h != NULL);
sl@0
  1057
	DoTest1(h);
sl@0
  1058
	h->Close();
sl@0
  1059
	h = RTestHeap::FixedHeap(0x10000, 64);
sl@0
  1060
	test(h != NULL);
sl@0
  1061
	DoTest1(h);
sl@0
  1062
	h->Close();
sl@0
  1063
	h = RTestHeap::FixedHeap(0x100000, 4096);
sl@0
  1064
	test(h != NULL);
sl@0
  1065
	DoTest1(h);
sl@0
  1066
	h->Close();
sl@0
  1067
	h = RTestHeap::FixedHeap(0x100000, 8192);
sl@0
  1068
	test(h != NULL);
sl@0
  1069
	DoTest1(h);
sl@0
  1070
	h->Close();
sl@0
  1071
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x1000, 0x1000, 4);
sl@0
  1072
	test(h != NULL);
sl@0
  1073
	DoTest1(h);
sl@0
  1074
	h->Close();
sl@0
  1075
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x10000, 0x1000, 4);
sl@0
  1076
	test(h != NULL);
sl@0
  1077
	DoTest1(h);
sl@0
  1078
	h->Close();
sl@0
  1079
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4096);
sl@0
  1080
	test(h != NULL);
sl@0
  1081
	DoTest1(h);
sl@0
  1082
	h->Close();
sl@0
  1083
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4);
sl@0
  1084
	test(h != NULL);
sl@0
  1085
	DoTest1(h);
sl@0
  1086
	h->Reset();
sl@0
  1087
	DoTest2(h);
sl@0
  1088
	h->Reset();
sl@0
  1089
	DoTest3(h);
sl@0
  1090
	h->Reset();
sl@0
  1091
	DoTest4(h);
sl@0
  1092
	h->Close();
sl@0
  1093
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 8);
sl@0
  1094
	test(h != NULL);
sl@0
  1095
	DoTest1(h);
sl@0
  1096
	h->Reset();
sl@0
  1097
	DoTest2(h);
sl@0
  1098
	h->Reset();
sl@0
  1099
	DoTest3(h);
sl@0
  1100
	h->Reset();
sl@0
  1101
	DoTest4(h);
sl@0
  1102
	h->Close();
sl@0
  1103
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 16);
sl@0
  1104
	test(h != NULL);
sl@0
  1105
	DoTest1(h);
sl@0
  1106
	h->Reset();
sl@0
  1107
	DoTest2(h);
sl@0
  1108
	h->Reset();
sl@0
  1109
	DoTest3(h);
sl@0
  1110
	h->Reset();
sl@0
  1111
	DoTest4(h);
sl@0
  1112
	h->Close();
sl@0
  1113
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 32);
sl@0
  1114
	test(h != NULL);
sl@0
  1115
	DoTest1(h);
sl@0
  1116
	h->Reset();
sl@0
  1117
	DoTest2(h);
sl@0
  1118
	h->Reset();
sl@0
  1119
	DoTest3(h);
sl@0
  1120
	h->Reset();
sl@0
  1121
	DoTest4(h);
sl@0
  1122
	h->Close();
sl@0
  1123
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x3000, 0x100000, 0x3000, 4);
sl@0
  1124
	test(h != NULL);
sl@0
  1125
	DoTest1(h);
sl@0
  1126
	h->Reset();
sl@0
  1127
	DoTest2(h);
sl@0
  1128
	h->Reset();
sl@0
  1129
	DoTest3(h);
sl@0
  1130
	h->Reset();
sl@0
  1131
	DoTest4(h);
sl@0
  1132
	h->Close();
sl@0
  1133
	}
sl@0
  1134
sl@0
  1135
struct SHeapStress
sl@0
  1136
	{
sl@0
  1137
	RThread iThread;
sl@0
  1138
	volatile TBool iStop;
sl@0
  1139
	TInt iAllocs;
sl@0
  1140
	TInt iFailedAllocs;
sl@0
  1141
	TInt iFrees;
sl@0
  1142
	TInt iReAllocs;
sl@0
  1143
	TInt iFailedReAllocs;
sl@0
  1144
	TInt iChecks;
sl@0
  1145
	TUint32 iSeed;
sl@0
  1146
	RAllocator* iAllocator;
sl@0
  1147
sl@0
  1148
	TUint32 Random();
sl@0
  1149
	};
sl@0
  1150
sl@0
  1151
TUint32 SHeapStress::Random()
sl@0
  1152
	{
sl@0
  1153
	iSeed *= 69069;
sl@0
  1154
	iSeed += 41;
sl@0
  1155
	return iSeed;
sl@0
  1156
	}
sl@0
  1157
sl@0
  1158
TInt RandomLength(TUint32 aRandom)
sl@0
  1159
	{
sl@0
  1160
	TUint8 x = (TUint8)aRandom;
sl@0
  1161
	if (x & 0x80)
sl@0
  1162
		return (x & 0x7f) << 7;
sl@0
  1163
	return x & 0x7f;
sl@0
  1164
	}
sl@0
  1165
sl@0
  1166
TInt HeapStress(TAny* aPtr)
sl@0
  1167
	{
sl@0
  1168
	SHeapStress& hs = *(SHeapStress*)aPtr;
sl@0
  1169
	RTestHeap* h = (RTestHeap*)&User::Allocator();
sl@0
  1170
	TUint8* cell[256];
sl@0
  1171
	TInt len[256];
sl@0
  1172
sl@0
  1173
	Mem::FillZ(cell, sizeof(cell));
sl@0
  1174
	Mem::FillZ(len, sizeof(len));
sl@0
  1175
sl@0
  1176
	RThread::Rendezvous(KErrNone);
sl@0
  1177
	while (!hs.iStop)
sl@0
  1178
		{
sl@0
  1179
		// allocate all cells
sl@0
  1180
		TInt i;
sl@0
  1181
		for (i=0; i<256; ++i)
sl@0
  1182
			{
sl@0
  1183
			if (!cell[i])
sl@0
  1184
				{
sl@0
  1185
				++hs.iAllocs;
sl@0
  1186
				cell[i] = (TUint8*)h->TestAlloc(RandomLength(hs.Random()));
sl@0
  1187
				if (cell[i])
sl@0
  1188
					len[i] = h->AllocLen(cell[i]);
sl@0
  1189
				else
sl@0
  1190
					++hs.iFailedAllocs;
sl@0
  1191
				}
sl@0
  1192
			}
sl@0
  1193
sl@0
  1194
		// free some cells
sl@0
  1195
		TInt n = 64 + (hs.Random() & 127);
sl@0
  1196
		while (--n)
sl@0
  1197
			{
sl@0
  1198
			i = hs.Random() & 0xff;
sl@0
  1199
			if (cell[i])
sl@0
  1200
				{
sl@0
  1201
				test(h->AllocLen(cell[i]) == len[i]);
sl@0
  1202
				h->TestFree(cell[i]);
sl@0
  1203
				cell[i] = NULL;
sl@0
  1204
				len[i] = 0;
sl@0
  1205
				++hs.iFrees;
sl@0
  1206
				}
sl@0
  1207
			}
sl@0
  1208
sl@0
  1209
		// realloc some cells
sl@0
  1210
		n = 64 + (hs.Random() & 127);
sl@0
  1211
		while (--n)
sl@0
  1212
			{
sl@0
  1213
			TUint32 rn = hs.Random();
sl@0
  1214
			i = (rn >> 8) & 0xff;
sl@0
  1215
			TInt new_len = RandomLength(rn);
sl@0
  1216
			if (cell[i])
sl@0
  1217
				{
sl@0
  1218
				test(h->AllocLen(cell[i]) == len[i]);
sl@0
  1219
				++hs.iReAllocs;
sl@0
  1220
				TUint8* p = (TUint8*)h->TestReAlloc(cell[i], new_len, rn >> 16);
sl@0
  1221
				if (p)
sl@0
  1222
					{
sl@0
  1223
					cell[i] = p;
sl@0
  1224
					len[i] = h->AllocLen(p);
sl@0
  1225
					}
sl@0
  1226
				else
sl@0
  1227
					++hs.iFailedReAllocs;
sl@0
  1228
				}
sl@0
  1229
			}
sl@0
  1230
sl@0
  1231
		// check the heap
sl@0
  1232
		h->Check();
sl@0
  1233
		++hs.iChecks;
sl@0
  1234
		}
sl@0
  1235
	return 0;
sl@0
  1236
	}
sl@0
  1237
sl@0
  1238
void CreateStressThread(SHeapStress& aInfo)
sl@0
  1239
	{
sl@0
  1240
	Mem::FillZ(&aInfo, _FOFF(SHeapStress, iSeed));
sl@0
  1241
	RThread& t = aInfo.iThread;
sl@0
  1242
	TInt r = t.Create(KNullDesC(), &HeapStress, 0x2000, aInfo.iAllocator, &aInfo);
sl@0
  1243
	test(r==KErrNone);
sl@0
  1244
	t.SetPriority(EPriorityLess);
sl@0
  1245
	TRequestStatus s;
sl@0
  1246
	t.Rendezvous(s);
sl@0
  1247
	test(s == KRequestPending);
sl@0
  1248
	t.Resume();
sl@0
  1249
	User::WaitForRequest(s);
sl@0
  1250
	test(s == KErrNone);
sl@0
  1251
	test(t.ExitType() == EExitPending);
sl@0
  1252
	t.SetPriority(EPriorityMuchLess);
sl@0
  1253
	}
sl@0
  1254
sl@0
  1255
void StopStressThread(SHeapStress& aInfo)
sl@0
  1256
	{
sl@0
  1257
	RThread& t = aInfo.iThread;
sl@0
  1258
	TRequestStatus s;
sl@0
  1259
	t.Logon(s);
sl@0
  1260
	aInfo.iStop = ETrue;
sl@0
  1261
	User::WaitForRequest(s);
sl@0
  1262
	const TDesC& exitCat = t.ExitCategory();
sl@0
  1263
	TInt exitReason = t.ExitReason();
sl@0
  1264
	TInt exitType = t.ExitType();
sl@0
  1265
	test.Printf(_L("Exit type %d,%d,%S\n"), exitType, exitReason, &exitCat);
sl@0
  1266
	test(exitType == EExitKill);
sl@0
  1267
	test(exitReason == KErrNone);
sl@0
  1268
	test(s == KErrNone);
sl@0
  1269
	test.Printf(_L("Total Allocs    : %d\n"), aInfo.iAllocs);
sl@0
  1270
	test.Printf(_L("Failed Allocs   : %d\n"), aInfo.iFailedAllocs);
sl@0
  1271
	test.Printf(_L("Total Frees		: %d\n"), aInfo.iFrees);
sl@0
  1272
	test.Printf(_L("Total ReAllocs  : %d\n"), aInfo.iReAllocs);
sl@0
  1273
	test.Printf(_L("Failed ReAllocs : %d\n"), aInfo.iFailedReAllocs);
sl@0
  1274
	test.Printf(_L("Heap checks     : %d\n"), aInfo.iChecks);
sl@0
  1275
	}
sl@0
  1276
sl@0
  1277
void DoStressTest1(RAllocator* aAllocator)
sl@0
  1278
	{
sl@0
  1279
	RTestHeap* h = (RTestHeap*)aAllocator;
sl@0
  1280
	test.Printf(_L("Test Stress 1: min=%x max=%x align=%d growby=%d\n"),
sl@0
  1281
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
  1282
	SHeapStress hs;
sl@0
  1283
	hs.iSeed = 0xb504f334;
sl@0
  1284
	hs.iAllocator = aAllocator;
sl@0
  1285
	CreateStressThread(hs);
sl@0
  1286
	User::After(10*1000000);
sl@0
  1287
	StopStressThread(hs);
sl@0
  1288
	CLOSE_AND_WAIT(hs.iThread);
sl@0
  1289
	h->FullCheck();
sl@0
  1290
	}
sl@0
  1291
sl@0
  1292
void DoStressTest2(RAllocator* aAllocator)
sl@0
  1293
	{
sl@0
  1294
	RTestHeap* h = (RTestHeap*)aAllocator;
sl@0
  1295
	test.Printf(_L("Test Stress 2: min=%x max=%x align=%d growby=%d\n"),
sl@0
  1296
						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
sl@0
  1297
	SHeapStress hs1;
sl@0
  1298
	SHeapStress hs2;
sl@0
  1299
	hs1.iSeed = 0xb504f334;
sl@0
  1300
	hs1.iAllocator = aAllocator;
sl@0
  1301
	hs2.iSeed = 0xddb3d743;
sl@0
  1302
	hs2.iAllocator = aAllocator;
sl@0
  1303
	CreateStressThread(hs1);
sl@0
  1304
	CreateStressThread(hs2);
sl@0
  1305
	User::After(20*1000000);
sl@0
  1306
	StopStressThread(hs1);
sl@0
  1307
	StopStressThread(hs2);
sl@0
  1308
	CLOSE_AND_WAIT(hs1.iThread);
sl@0
  1309
	CLOSE_AND_WAIT(hs2.iThread);
sl@0
  1310
	h->FullCheck();
sl@0
  1311
	}
sl@0
  1312
sl@0
  1313
void StressTests()
sl@0
  1314
	{
sl@0
  1315
	RHeap* h;
sl@0
  1316
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4);
sl@0
  1317
	test(h != NULL);
sl@0
  1318
	DoStressTest1(h);
sl@0
  1319
	h->Reset();
sl@0
  1320
	DoStressTest2(h);
sl@0
  1321
	h->Close();
sl@0
  1322
	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 8);
sl@0
  1323
	test(h != NULL);
sl@0
  1324
	DoStressTest1(h);
sl@0
  1325
	h->Reset();
sl@0
  1326
	DoStressTest2(h);
sl@0
  1327
	h->Close();
sl@0
  1328
	}
sl@0
  1329
		
sl@0
  1330
TInt TestHeapGrowInPlace(TInt aMode)
sl@0
  1331
    {
sl@0
  1332
    TBool reAllocs=EFalse;
sl@0
  1333
    TBool heapGrew=EFalse;
sl@0
  1334
    
sl@0
  1335
    RHeap* myHeap;
sl@0
  1336
    
sl@0
  1337
    myHeap = UserHeap::ChunkHeap(NULL,0x1000,0x4000,0x1000);
sl@0
  1338
    
sl@0
  1339
    TAny *testBuffer,*testBuffer2;
sl@0
  1340
    // Start size chosen so that 1st realloc will use up exactly all the heap.
sl@0
  1341
    // Later iterations wont, and there will be a free cell at the end of the heap.
sl@0
  1342
    TInt currentSize = ((0x800) - sizeof(RHeap)) - RHeap::EAllocCellSize;
sl@0
  1343
    TInt growBy = 0x800;
sl@0
  1344
    TInt newSpace, space;
sl@0
  1345
    
sl@0
  1346
    testBuffer2 = myHeap->Alloc(currentSize);
sl@0
  1347
sl@0
  1348
    newSpace = myHeap->Size();
sl@0
  1349
    do 
sl@0
  1350
    {
sl@0
  1351
    	space = newSpace;
sl@0
  1352
		testBuffer = testBuffer2;
sl@0
  1353
	    currentSize+=growBy;
sl@0
  1354
		testBuffer2 = myHeap->ReAlloc(testBuffer,currentSize,aMode);	
sl@0
  1355
		
sl@0
  1356
		newSpace = myHeap->Size();
sl@0
  1357
		
sl@0
  1358
		if (testBuffer2) 
sl@0
  1359
			{
sl@0
  1360
				
sl@0
  1361
			if (testBuffer!=testBuffer2)
sl@0
  1362
					reAllocs = ETrue;
sl@0
  1363
				
sl@0
  1364
			if (newSpace>space)
sl@0
  1365
					heapGrew = ETrue;
sl@0
  1366
			}
sl@0
  1367
		growBy-=16;
sl@0
  1368
 	} while (testBuffer2);
sl@0
  1369
    currentSize-=growBy;	
sl@0
  1370
    
sl@0
  1371
    myHeap->Free(testBuffer);
sl@0
  1372
    myHeap->Close();
sl@0
  1373
    
sl@0
  1374
    // How did we do?
sl@0
  1375
    if (reAllocs) 
sl@0
  1376
    	{
sl@0
  1377
    	test.Printf(_L("Failure - Memory was moved!\n"));
sl@0
  1378
    	return -100;
sl@0
  1379
    	}
sl@0
  1380
    if (!heapGrew) 
sl@0
  1381
    	{
sl@0
  1382
    	test.Printf(_L("Failure - Heap Never Grew!\n"));
sl@0
  1383
    	return -200;
sl@0
  1384
    	}
sl@0
  1385
    if (currentSize<= 0x3000) 
sl@0
  1386
    	{
sl@0
  1387
    	test.Printf(_L("Failed to grow by a reasonable amount!\n"));
sl@0
  1388
    	return -300;
sl@0
  1389
    	}
sl@0
  1390
        
sl@0
  1391
    return KErrNone;
sl@0
  1392
    }
sl@0
  1393
    
sl@0
  1394
void ReAllocTests()
sl@0
  1395
	{
sl@0
  1396
	test.Next(_L("Testing Grow In Place"));
sl@0
  1397
	test(TestHeapGrowInPlace(0)==KErrNone);
sl@0
  1398
    test(TestHeapGrowInPlace(RHeap::ENeverMove)==KErrNone);
sl@0
  1399
	}
sl@0
  1400
sl@0
  1401
RHeap* TestDEF078391Heap = 0;
sl@0
  1402
sl@0
  1403
TInt TestDEF078391ThreadFunction(TAny*)
sl@0
  1404
	{
sl@0
  1405
    TestDEF078391Heap = UserHeap::ChunkHeap(NULL,0x1000,0x100000,KMinHeapGrowBy,0,EFalse);
sl@0
  1406
	return TestDEF078391Heap ? KErrNone : KErrGeneral;
sl@0
  1407
	}
sl@0
  1408
sl@0
  1409
void TestDEF078391()
sl@0
  1410
	{
sl@0
  1411
	// Test that creating a multithreaded heap with UserHeap::ChunkHeap
sl@0
  1412
	// doesn't create any reference counts on the creating thread.
sl@0
  1413
	// This is done by creating a heap in a named thread, then exiting
sl@0
  1414
	// the thread and re-creating it with the same name.
sl@0
  1415
	// This will fail with KErrAlreadyExists if the orinal thread has
sl@0
  1416
	// not died because of an unclosed reference count.
sl@0
  1417
	test.Next(_L("Test that creating a multithreaded heap doesn't open references of creator"));
sl@0
  1418
	_LIT(KThreadName,"ThreadName");
sl@0
  1419
	RThread t;
sl@0
  1420
	TInt r=t.Create(KThreadName,TestDEF078391ThreadFunction,0x1000,0x1000,0x100000,NULL);
sl@0
  1421
	test(r==KErrNone);
sl@0
  1422
	TRequestStatus status;
sl@0
  1423
	t.Logon(status);
sl@0
  1424
	t.Resume();
sl@0
  1425
	User::WaitForRequest(status);
sl@0
  1426
	test(status==KErrNone);
sl@0
  1427
	test(t.ExitType()==EExitKill);
sl@0
  1428
	test(t.ExitReason()==KErrNone);
sl@0
  1429
	CLOSE_AND_WAIT(t);
sl@0
  1430
	test(TestDEF078391Heap!=0);
sl@0
  1431
	User::After(1000000); // give more opportunity for thread cleanup to happen
sl@0
  1432
sl@0
  1433
	// create thread a second time
sl@0
  1434
	r=t.Create(KThreadName,TestDEF078391ThreadFunction,0x1000,0x1000,0x100000,NULL);
sl@0
  1435
	test(r==KErrNone);
sl@0
  1436
	t.Kill(0);
sl@0
  1437
	CLOSE_AND_WAIT(t);
sl@0
  1438
sl@0
  1439
	// close the heap that got created earlier
sl@0
  1440
	TestDEF078391Heap->Close();
sl@0
  1441
	}
sl@0
  1442
sl@0
  1443
TInt E32Main()
sl@0
  1444
	{
sl@0
  1445
	test.Title();
sl@0
  1446
	__KHEAP_MARK;
sl@0
  1447
	test.Start(_L("Testing heaps"));
sl@0
  1448
	TestDEF078391();
sl@0
  1449
	Test1();
sl@0
  1450
	StressTests();
sl@0
  1451
	ReAllocTests();
sl@0
  1452
	test.End();
sl@0
  1453
	__KHEAP_MARKEND;
sl@0
  1454
	return 0;
sl@0
  1455
	}