diff -r a179b74831c9 -r c1f20ce4abcf kerneltest/e32test/heap/t_heapstress.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/heap/t_heapstress.cpp Tue Aug 31 16:34:26 2010 +0300 @@ -0,0 +1,1233 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\heap\t_heaphybridstress.cpp +// Overview: +// Tests RHybridHeap class: stress test +// API Information: +// RHybridHeap/RHeap +// Details: +// - Stress test heap implementation that allocates, frees +// and reallocates cells in random patterns, and checks the heap. +// - Allocated/reallocated buffer content is verified, when buffer is freed/reallocated. +// - Stress test with a single thread +// - Stress test with two threads that run concurrently. +// - Tests configured for slab, doug lea, paged and hybrid allocators +// Platforms/Drives/Compatibility: +// All +// Assumptions/Requirement/Pre-requisites: +// Failures and causes: +// Base Port information: +// +// + +#include +#include +#include +#include +#include "dla.h" +#include "slab.h" +#include "page_alloc.h" +#include "heap_hybrid.h" + +// Needed for KHeapShrinkHysRatio which is now ROM 'patchdata' +#include "TestRHeapShrink.h" + +//------------------------------------------- + +//#define TSTDBG_PRINTMETA(a) a +#define TSTDBG_PRINTMETA(a) + +//------------------------------------------- + + +#ifdef __EABI__ + IMPORT_D extern const TInt KHeapMinCellSize; +#else + const TInt KHeapMinCellSize = 0; +#endif + +RTest test(_L("T_HEAPSTRESS")); + +#define TEST_ALIGN(p,a) test((TLinAddr(p)&((a)-1))==0) + + +#define TST_HEAP_MAX_LTH 0x4000000 // 64M +#define MAX_CELL_COUNT 0x100000 // 0x100 0x1000 0x10000 0x100000 +#define MAX_THREAD_COUNT 2 +LOCAL_D TUint8* HeapStressCell[MAX_THREAD_COUNT][MAX_CELL_COUNT]; +LOCAL_D TInt HeapStressLen[MAX_THREAD_COUNT][MAX_CELL_COUNT]; + +enum TTestHybridHeapFunc {ETstOnlySlab, ETstOnlyDl, ETstOnlyPaged, ETstHybrid}; +enum TTestType {ETestE32Test, ETestForeverOne, ETestForeverAll}; + +LOCAL_D TTimeIntervalMicroSeconds32 TickPeriod; + +//--------- config parameters - begin +LOCAL_D TTestType TestType; +LOCAL_D TInt TestTimeAsSeconds; +LOCAL_D TBool TestForeverMultiThreadTest; +LOCAL_D TTestHybridHeapFunc TestHybridHeapFunc; +LOCAL_D TInt CurrMaxCellCount; +LOCAL_D TInt HeapMaxLength; +//--------- config parameters - end + +LOCAL_D TBool DlOnly; + +LOCAL_D TInt SlabThreshold; +LOCAL_D TInt PageThreshold; + + +struct TMetaData + { + TBool iDLOnly; + RFastLock* iLock; + TInt iChunkSize; + TInt iSlabThreshold; + TInt iPageThreshold; + TInt iSlabInitThreshold; + TUint32 iSlabConfigBits; + slab* iPartialPage; + slab* iFullSlab; + page* iSparePage; + TUint8* iMemBase; + TUint8 iSizeMap[(MAXSLABSIZE>>2)+1]; + slabset iSlabAlloc[MAXSLABSIZE>>2]; + slab** iSlabAllocRealRootAddress[MAXSLABSIZE>>2]; + }; + +class TestHybridHeap + { +public: + static void GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta); + }; + +void TestHybridHeap::GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta) +{ + RHybridHeap::STestCommand cmd; + cmd.iCommand = RHybridHeap::EHeapMetaData; + TInt ret = aHeap.DebugFunction(RHeap::EHybridHeap, &cmd, 0); + test(ret == KErrNone); + + RHybridHeap* hybridHeap = (RHybridHeap*)cmd.iData; + + aMeta.iDLOnly = hybridHeap->iDLOnly; + aMeta.iLock = &hybridHeap->iLock; + aMeta.iChunkSize = hybridHeap->iChunkSize; + aMeta.iSlabThreshold = hybridHeap->iSlabThreshold; + aMeta.iPageThreshold = hybridHeap->iPageThreshold; + aMeta.iSlabInitThreshold = hybridHeap->iSlabInitThreshold; + aMeta.iSlabConfigBits = hybridHeap->iSlabConfigBits; + aMeta.iPartialPage = hybridHeap->iPartialPage; + aMeta.iFullSlab = hybridHeap->iFullSlab; + aMeta.iSparePage = hybridHeap->iSparePage; + aMeta.iMemBase = hybridHeap->iMemBase; + + TInt i; + TInt count; + count = sizeof(aMeta.iSizeMap)/sizeof(unsigned char); + for (i=0; iiSizeMap[i]; + } + count = sizeof(aMeta.iSlabAlloc)/sizeof(slabset); + for (i=0; iiSlabAlloc[i].iPartial; + aMeta.iSlabAllocRealRootAddress[i] = &hybridHeap->iSlabAlloc[i].iPartial; + } +} + +LOCAL_C void GetMeta(RHeap& aHeap, TMetaData& aMeta) +{ + TestHybridHeap::GetHeapMetaData(aHeap, aMeta); +} + + +TSTDBG_PRINTMETA( +LOCAL_C void PrintMeta(const char* aText, TMetaData& aMeta) +{ + RDebug::Printf("=========== HeapMetaData (local) - begin: %s", aText); + + RDebug::Printf("iDLOnly: 0x%08x", aMeta.iDLOnly); + RDebug::Printf("iChunkSize: 0x%08x", aMeta.iChunkSize); + RDebug::Printf("iSlabThreshold: 0x%08x / %d", aMeta.iSlabThreshold, aMeta.iSlabThreshold); + RDebug::Printf("iPageThreshold: 0x%08x / %d", aMeta.iPageThreshold, aMeta.iPageThreshold); + RDebug::Printf("iSlabInitThreshold: 0x%08x / %d", aMeta.iSlabInitThreshold, aMeta.iSlabInitThreshold); + RDebug::Printf("iSlabConfigBits: 0x%08x", aMeta.iSlabConfigBits); + RDebug::Printf("iPartialPage: 0x%08x", aMeta.iPartialPage); + RDebug::Printf("iFullSlab: 0x%08x", aMeta.iFullSlab); + RDebug::Printf("iSparePage: 0x%08x", aMeta.iSparePage); + RDebug::Printf("iMemBase: 0x%08x", aMeta.iMemBase); + + TInt i; + TInt count; + count = sizeof(aMeta.iSizeMap)/sizeof(unsigned char); + for (i=0; i use slab at once from the beginning + cmd.iConfig.iPagePower = 0; // 0 -> no page allocator + } + else if (TestHybridHeapFunc == ETstOnlyDl) + { + cmd.iCommand = RHybridHeap::ESetConfig; + cmd.iConfig.iSlabBits = 0xabe; + cmd.iConfig.iDelayedSlabThreshold = 0x40000000; // 1G -> slab never used + cmd.iConfig.iPagePower = 0; // 0 -> no page allocator + } + else if (TestHybridHeapFunc == ETstOnlyPaged) + { + cmd.iCommand = RHybridHeap::ESetConfig; + cmd.iConfig.iSlabBits = 0xabe; + cmd.iConfig.iDelayedSlabThreshold = 0x40000000; // 1G -> slab never used + cmd.iConfig.iPagePower = 14; // min page 14 -> 16K + } + else if (TestHybridHeapFunc == ETstHybrid) + { + cmd.iCommand = RHybridHeap::ESetConfig; + cmd.iConfig.iSlabBits = 0xabe; + cmd.iConfig.iDelayedSlabThreshold = 0; // 0 -> use slab at once from the beginning + cmd.iConfig.iPagePower = 14; // min page 14 -> 16K + } + else + { + test(0); + } + + TInt ret = aHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0); + test(ret == KErrNone); +} + +LOCAL_C TInt MinPagedAllocLength(void) +{ + return (1 << PageThreshold); +} + +LOCAL_C TUint32 RandomPagedLength(TUint32 aRandom) +{ + TUint32 ret; + ret = aRandom; + ret <<= PageThreshold; + if (TestHybridHeapFunc == ETstOnlyPaged) + { + //ret &= 0xfffff; // below 1M + ret &= 0x7ffff; // below 512K + } + else + { + ret &= 0x1ffff; // below 128K + } + if (ret == 0) + { + ret = MinPagedAllocLength(); + } + return ret; +} + +#if 0 +LOCAL_C TUint TicksAsMilliSeconds(TUint aTicks) +{ + TUint time = TUint((TUint64)aTicks*(TUint64)TickPeriod.Int()/(TUint64)1000); + return time; +} +#endif + +LOCAL_C TBool IsDlOnly(void) +{ + TestHybridHeapFunc = ETstHybrid; + + RHeap* heap; + heap = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x4000, 0x1000, 4); + test(heap != NULL); + + ConfHeap(heap); + + TMetaData metaData; + GetMeta(*heap, metaData); + + heap->Close(); + return metaData.iDLOnly; +} + +LOCAL_C RHeap* CreateTestHeap(TInt aAlign) +{ + if (HeapMaxLength > TST_HEAP_MAX_LTH) + { + HeapMaxLength = TST_HEAP_MAX_LTH; + } + + if (CurrMaxCellCount > MAX_CELL_COUNT) + { + CurrMaxCellCount = MAX_CELL_COUNT; + } + + RHeap* heap; + heap = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, HeapMaxLength, 0x1000, aAlign); + test(heap != NULL); + + ConfHeap(heap); + + TMetaData metaData; + GetMeta(*heap, metaData); + + if (TestHybridHeapFunc == ETstOnlySlab) + { + SlabThreshold = metaData.iSlabThreshold; + test(SlabThreshold != 0); + } + else if (TestHybridHeapFunc == ETstOnlyDl) + { + } + else if (TestHybridHeapFunc == ETstOnlyPaged) + { + PageThreshold = metaData.iPageThreshold; + test(PageThreshold >= 14); + } + else if (TestHybridHeapFunc == ETstHybrid) + { + } + else + { + test(0); + } + + return heap; +} + +//------------------------------------------------------------------- + +struct STestCell + { + enum {EMagic = 0xb8aa3b29}; + + TUint32 iLength; + TUint32 iData[1]; + + void Set(TInt aLength); + void Verify(TInt aLength); + void Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength); + }; + +void STestCell::Set(TInt aLength) + { + TInt i; + TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic; + if (aLength < (TInt) sizeof(iLength)) + { + return; + } + iLength = x; + aLength /= sizeof(TUint32); + for (i=0; iVerify(CheckAllocatedCell(aCell)); + } + +TAny* RTestHeap::TestAlloc(TInt aSize) + { + TAny* p = Alloc(aSize); + if (p) + { + TInt len = CheckAllocatedCell(p); + test(len>=aSize); + ((STestCell*)p)->Set(len); + } + return p; + } + +void RTestHeap::TestFree(TAny* aPtr) + { + if (aPtr) + { + FullCheckAllocatedCell(aPtr); + } + Free(aPtr); + } + +TAny* RTestHeap::TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode) + { + TInt old_len = aPtr ? CheckAllocatedCell(aPtr) : 0; + if (aPtr) + ((STestCell*)aPtr)->Verify(old_len); + TAny* p = ReAlloc(aPtr, aSize, aMode); + if (!p) + { + ((STestCell*)aPtr)->Verify(old_len); + return p; + } + TInt new_len = CheckAllocatedCell(p); + test(new_len>=aSize); + if (p == aPtr) + { + ((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len)); + if (new_len != old_len) + ((STestCell*)p)->Set(new_len); + return p; + } + test(!(aMode & ENeverMove)); + test((new_len > old_len) || (aMode & EAllowMoveOnShrink)); + if (old_len) + ((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, aSize)); + ((STestCell*)p)->Set(new_len); + return p; + } + +struct SHeapCellInfo + { + RTestHeap* iHeap; + TInt iTotalAlloc; + TInt iTotalAllocSize; + TInt iTotalFree; + TUint8* iNextCell; + }; + +void RTestHeap::WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen) + { + (void)aCell; + ::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr; + switch(aType) + { + case EGoodAllocatedCell: + { + TInt len = aLen; + info.iTotalAllocSize += len; + STestCell* pT = (STestCell*)aCell; + ++info.iTotalAlloc; + pT->Verify(len); + break; + } + case EGoodFreeCell: + { + ++info.iTotalFree; + break; + } + default: + test.Printf(_L("TYPE=%d ??\n"),aType); + test(0); + break; + } + } + +void RTestHeap::FullCheck() + { + ::SHeapCellInfo info; + Mem::FillZ(&info, sizeof(info)); + info.iHeap = this; + DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info); + TInt count = AllocSize(iTotalAllocSize); + test(info.iTotalAlloc == count); + test(info.iTotalAllocSize == iTotalAllocSize); + } + + +struct STestStress + { + RThread iThread; + volatile TBool iStop; + TInt iAllocs; + TInt iFailedAllocs; + TInt iFrees; + TInt iReAllocs; + TInt iFailedReAllocs; + TInt iChecks; + TUint32 iSeed; + RAllocator* iAllocator; + TInt iThreadIndex; + + TUint32 Random(); + }; + +TUint32 FirstSeed(TInt aThreadIndex) + { + static TUint32 seed0 = 0xb504f334; + static TUint32 seed1 = 0xddb3d743; + static TBool first = ETrue; + + TUint32 ret; + + if (aThreadIndex == 0) + { + ret = seed0; + } + else + { + ret = seed1; + } + + if (first) + { + first = EFalse; + } + + if (aThreadIndex == 0) + { + seed0 *= 69069; + seed0 += 41; + } + else + { + seed1 *= 69069; + seed1 += 41; + } + + test.Printf(_L("FirstSeed: 0x%08x\n"), ret); + return ret; + } + +TUint32 STestStress::Random() + { + iSeed *= 69069; + iSeed += 41; + return iSeed; + } + +TInt RandomLength(TUint32 aRandom) + { + TUint32 ret = 0; + + if (TestHybridHeapFunc == ETstOnlySlab) + { + test(SlabThreshold != 0); + ret = aRandom; + TInt realSlabThreshold = SlabThreshold; +#ifdef _DEBUG + realSlabThreshold -= RHeap::EDebugHdrSize; +#endif + ret %= realSlabThreshold; + } + else if (TestHybridHeapFunc == ETstOnlyDl) + { + TUint8 x = (TUint8)aRandom; + if (x & 0x80) + { + ret = x & 0x7f; + } + else + { + ret = (x & 0x7f) << 7; + } + } + else if (TestHybridHeapFunc == ETstOnlyPaged) + { + ret = RandomPagedLength(aRandom); + } + else if (TestHybridHeapFunc == ETstHybrid) + { + TUint8 x = (TUint8)aRandom; + if (x & 0x80) + { + ret = x & 0x7f; + } + else + { + if (x & 0x10) + { + ret = (x & 0x7f) << 7; + } + else + { + ret = RandomPagedLength(aRandom); + } + } + } + else + { + test(0); + } + + return (TInt)ret; + } + +TInt HeapStress(TAny* aPtr) + { + STestStress& stress = *(STestStress*)aPtr; + RTestHeap* heap = (RTestHeap*)&User::Allocator(); + TUint8** cell; + TInt* len; + + if (stress.iThreadIndex >= MAX_THREAD_COUNT) + { + test(0); + } + cell = &HeapStressCell[stress.iThreadIndex][0]; + len = &HeapStressLen[stress.iThreadIndex][0]; + + Mem::FillZ(cell, sizeof(*cell)*CurrMaxCellCount); + Mem::FillZ(len, sizeof(*len)*CurrMaxCellCount); + + RThread::Rendezvous(KErrNone); + while (!stress.iStop) + { + // allocate all cells + TInt i; + for (i=0; iTestAlloc(RandomLength(stress.Random())); + if (cell[i]) + len[i] = heap->AllocLen(cell[i]); + else + ++stress.iFailedAllocs; + } + } + + // free some cells + TInt n = (CurrMaxCellCount/4) + (stress.Random() & (CurrMaxCellCount/2-1)); + while (--n) + { + i = stress.Random() & (CurrMaxCellCount-1); + if (cell[i]) + { + test(heap->AllocLen(cell[i]) == len[i]); + heap->TestFree(cell[i]); + cell[i] = NULL; + len[i] = 0; + ++stress.iFrees; + } + } + + // realloc some cells + n = (CurrMaxCellCount/4) + (stress.Random() & (CurrMaxCellCount/2-1)); + while (--n) + { + TUint32 rn = stress.Random(); + i = (rn >> 8) & (CurrMaxCellCount-1); + TInt new_len = RandomLength(rn); + if (cell[i]) + { + test(heap->AllocLen(cell[i]) == len[i]); + ++stress.iReAllocs; + TUint8* p = (TUint8*)heap->TestReAlloc(cell[i], new_len, rn >> 16); + if (p) + { + cell[i] = p; + len[i] = heap->AllocLen(p); + } + else + { + ++stress.iFailedReAllocs; + } + } + } + + // check the heap + heap->Check(); + ++stress.iChecks; + } + + return 0; + } + +void PrintSummary(STestStress& aStress) + { + test.Printf(_L("Total Allocs : %11d\n"), aStress.iAllocs); + test.Printf(_L("Failed Allocs : %11d\n"), aStress.iFailedAllocs); + test.Printf(_L("Total Frees : %11d\n"), aStress.iFrees); + test.Printf(_L("Total ReAllocs : %11d\n"), aStress.iReAllocs); + test.Printf(_L("Failed ReAllocs : %11d\n"), aStress.iFailedReAllocs); + test.Printf(_L("Heap checks : %11d\n"), aStress.iChecks); + } + +void CreateStressThread(STestStress& aStress) + { + RThread& thread = aStress.iThread; + TInt err = thread.Create(KNullDesC(), &HeapStress, 0x2000, aStress.iAllocator, &aStress); + test(err==KErrNone); + thread.SetPriority(EPriorityLess); + TRequestStatus status; + thread.Rendezvous(status); + test(status == KRequestPending); + thread.Resume(); + User::WaitForRequest(status); + test(status == KErrNone); + test(thread.ExitType() == EExitPending); + thread.SetPriority(EPriorityMuchLess); + } + +void StopStressThread(STestStress& aStress) + { + RThread& thread = aStress.iThread; + TRequestStatus status; + thread.Logon(status); + aStress.iStop = ETrue; + User::WaitForRequest(status); + const TDesC& exitCat = thread.ExitCategory(); + TInt exitReason = thread.ExitReason(); + TInt exitType = thread.ExitType(); + test.Printf(_L("Exit type %d,%d,%S\n"), exitType, exitReason, &exitCat); + test(exitType == EExitKill); + test(exitReason == KErrNone); + test(status == KErrNone); + PrintSummary(aStress); + } + +void WaitForKey(STestStress* aStress1, STestStress* aStress2) +{ + TRequestStatus keyStatus; + CConsoleBase* console = test.Console(); + console->Read(keyStatus); + + for (;;) + { + User::WaitForRequest(keyStatus); + if (keyStatus != KRequestPending) + { + test(keyStatus == KErrNone); + if (console->KeyCode() == EKeyEscape) + { + test.Printf(_L("Forever test aborted by user\n")); + break; + } + else if (console->KeyCode() == EKeySpace) + { + if (aStress1 != NULL) + { + PrintSummary(*aStress1); + } + if (aStress2 != NULL) + { + PrintSummary(*aStress2); + } + } + } + console->Read(keyStatus); + } +} + +TBool WaitForTimeoutOrKey(STestStress* aStress1, STestStress* aStress2) +{ + TBool abortedByUser = EFalse; + RTimer timer; + TRequestStatus timerStatus; + TInt err = timer.CreateLocal(); + test(err == KErrNone); + timer.After(timerStatus, TestTimeAsSeconds*1000000); + + TRequestStatus keyStatus; + CConsoleBase* console = test.Console(); + console->Read(keyStatus); + + for (;;) + { + User::WaitForRequest(keyStatus, timerStatus); + if (keyStatus != KRequestPending) + { + test(keyStatus == KErrNone); + if (console->KeyCode() == EKeyEscape) + { + abortedByUser = ETrue; + timer.Cancel(); + test.Printf(_L("Forever test aborted by user\n")); + break; + } + else if (console->KeyCode() == EKeySpace) + { + if (aStress1 != NULL) + { + PrintSummary(*aStress1); + } + if (aStress2 != NULL) + { + PrintSummary(*aStress2); + } + } + console->Read(keyStatus); + } + if (timerStatus != KRequestPending) + { + if (timerStatus != KErrNone) + { + test(0); + } + console->ReadCancel(); + break; + } + } + timer.Close(); + return abortedByUser; +} + +TBool DoStressTest1(RAllocator* aAllocator) + { + TBool abortedByUser = EFalse; + + RTestHeap* heap = (RTestHeap*)aAllocator; + //test.Printf(_L("Test Stress 1: max=0x%x\n"), heap->MaxLength()); + + STestStress stress; + Mem::FillZ(&stress, sizeof(STestStress)); + stress.iAllocator = aAllocator; + stress.iThreadIndex = 0; + if (TestType == ETestForeverAll) + { + stress.iSeed = FirstSeed(stress.iThreadIndex); + } + else + { + stress.iSeed = 0xb504f334;; + } + + CreateStressThread(stress); + + if (TestType == ETestE32Test) + { + User::After(TestTimeAsSeconds*1000000); + } + else if (TestType == ETestForeverAll) + { + abortedByUser = WaitForTimeoutOrKey(&stress, NULL); + } + else if (TestType == ETestForeverOne) + { + WaitForKey(&stress, NULL); + abortedByUser = ETrue; + } + else + { + test(0); + } + + StopStressThread(stress); + CLOSE_AND_WAIT(stress.iThread); + heap->FullCheck(); + return abortedByUser; + } + +TBool DoStressTest2(RAllocator* aAllocator) + { + TBool abortedByUser = EFalse; + + RTestHeap* heap = (RTestHeap*)aAllocator; + //test.Printf(_L("Test Stress 2: max=0x%x\n"), heap->MaxLength()); + + STestStress stress1; + Mem::FillZ(&stress1, sizeof(STestStress)); + stress1.iAllocator = aAllocator; + stress1.iThreadIndex = 0; + + STestStress stress2; + Mem::FillZ(&stress2, sizeof(STestStress)); + stress2.iAllocator = aAllocator; + stress2.iThreadIndex = 1; + + if (TestType == ETestForeverAll) + { + stress1.iSeed = FirstSeed(stress1.iThreadIndex); + stress2.iSeed = FirstSeed(stress2.iThreadIndex); + } + else + { + stress1.iSeed = 0xb504f334; + stress2.iSeed = 0xddb3d743; + } + CreateStressThread(stress1); + CreateStressThread(stress2); + + if (TestType == ETestE32Test) + { + User::After(2*TestTimeAsSeconds*1000000); + } + else if (TestType == ETestForeverAll) + { + abortedByUser = WaitForTimeoutOrKey(&stress1, &stress2); + } + else if (TestType == ETestForeverOne) + { + WaitForKey(&stress1, &stress2); + abortedByUser = ETrue; + } + else + { + test(0); + } + + StopStressThread(stress1); + StopStressThread(stress2); + CLOSE_AND_WAIT(stress1.iThread); + CLOSE_AND_WAIT(stress2.iThread); + heap->FullCheck(); + return abortedByUser; + } + +TBool StressTests(void) + { + TBool abortedByUser = EFalse; + RHeap* heap = 0; + + for (;;) + { + if (TestType == ETestE32Test || + TestType == ETestForeverAll) + { + heap = CreateTestHeap(4); + test(heap != NULL); + test.Next(_L("one thread, align 4")); + abortedByUser = DoStressTest1(heap); + if (abortedByUser) + { + break; + } + heap->Close(); + + heap = CreateTestHeap(4); + test.Next(_L("two threads, align 4")); + abortedByUser = DoStressTest2(heap); + if (abortedByUser) + { + break; + } + heap->Close(); + + heap = CreateTestHeap(8); + test(heap != NULL); + test.Next(_L("one thread, align 8")); + abortedByUser = DoStressTest1(heap); + if (abortedByUser) + { + break; + } + heap->Close(); + + heap = CreateTestHeap(8); + test.Next(_L("two threads, align 8")); + abortedByUser = DoStressTest2(heap); + } + else if (TestType == ETestForeverOne) + { + heap = CreateTestHeap(4); + test(heap != NULL); + if (TestForeverMultiThreadTest) + { + test.Next(_L("two threads, align 4")); + abortedByUser = DoStressTest2(heap); + } + else + { + test.Next(_L("one thread, align 4")); + abortedByUser = DoStressTest1(heap); + } + } + else + { + test(0); + } + break; + } + heap->Close(); + + return abortedByUser; + } + + +void ForeverOneTest(void) + { + //--------- config parameters - begin + TestForeverMultiThreadTest = ETrue; // EFalse + TestHybridHeapFunc = ETstOnlySlab; // ETstOnlySlab // ETstOnlyDl // ETstOnlyPaged // ETstHybrid + //--------- config parameters - end + + if (TestHybridHeapFunc == ETstOnlySlab && !DlOnly) + { + // slab tests +#ifdef __WINS__ + test.Next(_L("slab test 48M")); + CurrMaxCellCount = 0x100000; //0x10000; 0x100000 + HeapMaxLength = 0x3000000; // 48M +#else + test.Next(_L("slab test 3M")); + CurrMaxCellCount = 0x10000; //0x10000; 0x100000 + HeapMaxLength = 0x300000; // 3M +#endif + StressTests(); + } + else if (TestHybridHeapFunc == ETstOnlyDl) + { + // DL tests + test.Next(_L("DL test 32M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x2000000; // 32M + StressTests(); + } + else if (TestHybridHeapFunc == ETstOnlyPaged && !DlOnly) + { + // paged tests + test.Next(_L("paged test 64M")); + CurrMaxCellCount = 0x100; //0x10000; + HeapMaxLength = 0x4000000; // 64M + StressTests(); + } + else if (TestHybridHeapFunc == ETstHybrid && !DlOnly) + { + // hybrid tests + test.Next(_L("hybrid test 64M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x4000000; // 64M + StressTests(); + } + else + { + test(0); + } + } + +void ForeverAllTests(void) + { + //--------- config parameters - begin + TInt basicTimeAsSeconds = 30; //10; + //--------- config parameters - end + + for (;;) + { + if (!DlOnly) + { + // slab tests + TestHybridHeapFunc = ETstOnlySlab; + TestTimeAsSeconds = basicTimeAsSeconds * 3; +#ifdef __WINS__ + test.Next(_L("slab test 48M")); + CurrMaxCellCount = 0x100000; //0x10000; 0x100000 + HeapMaxLength = 0x3000000; // 48M +#else + test.Next(_L("slab test 3M")); + CurrMaxCellCount = 0x10000; //0x10000; 0x100000 + HeapMaxLength = 0x300000; // 3M +#endif + if (StressTests()) + { + break; + } + } + + // DL tests + TestHybridHeapFunc = ETstOnlyDl; + TestTimeAsSeconds = basicTimeAsSeconds; + + test.Next(_L("DL test 32M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x2000000; // 32M + if (StressTests()) + { + break; + } + + test.Next(_L("DL test 16M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x1000000; // 16M + if (StressTests()) + { + break; + } + + if (!DlOnly) + { + // paged tests + TestHybridHeapFunc = ETstOnlyPaged; + TestTimeAsSeconds = basicTimeAsSeconds; + + test.Next(_L("paged test 64M")); + CurrMaxCellCount = 0x100; //0x10000; + HeapMaxLength = 0x4000000; // 64M + if (StressTests()) + { + break; + } + } + + if (!DlOnly) + { + // hybrid tests + TestHybridHeapFunc = ETstHybrid; + TestTimeAsSeconds = basicTimeAsSeconds * 2; + + test.Next(_L("hybrid test 64M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x4000000; // 64M + if (StressTests()) + { + break; + } + } + } + } + +void TestUsedInE32Tests(void) + { + //--------- config parameters - begin + TInt basicTimeAsSeconds = 10; + //--------- config parameters - end + + if (!DlOnly) + { + // slab tests + TestHybridHeapFunc = ETstOnlySlab; + TestTimeAsSeconds = basicTimeAsSeconds * 3; +#ifdef __WINS__ + test.Next(_L("slab test 48M")); + CurrMaxCellCount = 0x100000; //0x10000; 0x100000 + HeapMaxLength = 0x3000000; // 48M +#else + test.Next(_L("slab test 3M")); + CurrMaxCellCount = 0x10000; //0x10000; 0x100000 + HeapMaxLength = 0x300000; // 3M +#endif + StressTests(); + } + + // DL tests + TestHybridHeapFunc = ETstOnlyDl; + TestTimeAsSeconds = basicTimeAsSeconds; + + test.Next(_L("DL test 32M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x2000000; // 32M + StressTests(); + + test.Next(_L("DL test 16M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x1000000; // 16M + StressTests(); + + if (!DlOnly) + { + // paged tests + TestHybridHeapFunc = ETstOnlyPaged; + TestTimeAsSeconds = basicTimeAsSeconds; + + test.Next(_L("paged test 64M")); + CurrMaxCellCount = 0x100; //0x10000; + HeapMaxLength = 0x4000000; // 64M + StressTests(); + } + + if (!DlOnly) + { + // hybrid tests + TestHybridHeapFunc = ETstHybrid; + TestTimeAsSeconds = basicTimeAsSeconds * 2; + + test.Next(_L("hybrid test 64M")); + CurrMaxCellCount = 0x1000; //0x10000; + HeapMaxLength = 0x4000000; // 64M + StressTests(); + } + } + +TInt E32Main() + { + test.Title(); + __KHEAP_MARK; + test.Start(_L("Testing heaps")); + + TInt err = UserHal::TickPeriod(TickPeriod); + test(err == KErrNone); + + DlOnly = IsDlOnly(); + + TestType = ETestE32Test; //ETestE32Test // ETestForeverOne // ETestForeverAll + // see other config parameters: TestUsedInE32Tests()/ForeverOneTest()/ForeverAllTests() + + if (TestType == ETestE32Test) + { + TestUsedInE32Tests(); + } + else if (TestType == ETestForeverOne) + { + ForeverOneTest(); + } + else if (TestType == ETestForeverAll) + { + ForeverAllTests(); + } + else + { + test(0); + } + + test.End(); + __KHEAP_MARKEND; + return 0; + }