diff -r a232af6b0b1f -r a5496987b1da kerneltest/e32test/heap/t_heappagealloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/heap/t_heappagealloc.cpp Thu Jul 01 17:57:33 2010 +0100 @@ -0,0 +1,462 @@ +// Copyright (c) 1995-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_page_alloc.cpp +// Overview: +// Tests RHeap class. +// API Information: +// RHeap +// Details: +// - Tests that the page bitmap is consistent (i.e. encoded sizes are sensible and +// encoded in the correct fashion. +// - Tests that pages which appear in the page bitmap are present in memory by +// reading them. +// -Tests that other pages are not readable +// - Tests page bitmap by creating an allocator where all allocations >= 4kB use +// paged allocator, allocating a large number of regions of various sizes (from +// 4 kB to b MB), checking that the walk function finds them all correctly, freeing +// some of them, checking the walk function again, and so on. +// Platforms/Drives/Compatibility: +// All +// Assumptions/Requirement/Pre-requisites: +// Failures and causes: +// Base Port information: +// +// + +#include +#include +#include +#include +#include +#include "dla.h" +#include "slab.h" +#include "page_alloc.h" +#include "heap_hybrid.h" + + +struct TMetaData + { + TBool iDLOnly; + RFastLock* iLock; + TInt iChunkSize; + TInt iSlabThreshold; + unsigned iSlabInitThreshold; + unsigned iSlabConfigBits; + slab* iPartialPage; + slab* iFullSlab; + page* iSparePage; + TUint8* iMemBase; + unsigned char iSizeMap[(MAXSLABSIZE>>2)+1]; + slabset iSlabAlloc[MAXSLABSIZE>>2]; + slab** iSlabAllocRealRootAddress[MAXSLABSIZE>>2]; + }; + +LOCAL_D RTest test(_L("T_HEAPPAGEALLOC")); + +class TestHybridHeap + { +public: + static TUint8* MemBase(const RHybridHeap * aHybridHeap); + static void GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta); + }; + +TUint8* TestHybridHeap::MemBase(const RHybridHeap * aHybridHeap) + { + return aHybridHeap->iMemBase; + } + +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.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); +} + +class TestRHeap : public RHeap + { +public: + void InitTests(); + void Test1(void); + void Test2(void); + void Test3(void); + void CloseTests(); + TUint GetRandomSize(TUint aMaxSize); + TUint GetRandomIndex(TUint aMaxIndex); + static void WalkCallback(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen); + TBool CheckWalkArrayEmpty(); + +private: + RHybridHeap* iHybridHeap; + RHeap *iHeap; + TUint8* iMemBase; // bottom of Paged/Slab memory (chunk base) + static TUint iWalkArraySize; + static TUint iWalkArrayIndex; + static TAny** iWalkArrayOfCells; + TUint iAllocatedArrayIndex; + TAny** iAllocatedArrayOfCells; + }; + +TUint TestRHeap::iWalkArraySize = 100; +TUint TestRHeap::iWalkArrayIndex = 0; +TAny** TestRHeap::iWalkArrayOfCells = new TAny*[iWalkArraySize]; + +void TestRHeap::InitTests() +{ + // Allocate a chunk heap + TPtrC testHeap=_L("TESTHEAP"); + iHeap=User::ChunkHeap(&testHeap,0x1800,0x800000); + RHybridHeap::STestCommand cmd; + cmd.iCommand = RHybridHeap::EHeapMetaData; + iHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0); + iHybridHeap = (RHybridHeap*) cmd.iData; + iMemBase = TestHybridHeap::MemBase(iHybridHeap); + + // configure paged heap threshold 16 kB + cmd.iCommand = RHybridHeap::ESetConfig; + cmd.iConfig.iSlabBits = 0x0; //0xabe + cmd.iConfig.iDelayedSlabThreshold = 0x40000000; + cmd.iConfig.iPagePower = 14; + test(iHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0) == KErrNone); +} + + +TUint TestRHeap::GetRandomSize(TUint aMaxSize) +{ + TUint size = 0; + do + { + size = Math::Random() & aMaxSize; + } + while(size < 16384 || size > aMaxSize ); + // subtract debug header size + return size - 8; +} + + +TUint TestRHeap::GetRandomIndex(TUint aMaxIndex) +{ + TUint index = 0; + do + { + index = Math::Random() & 0x7F; + } + while(index >= aMaxIndex || iWalkArrayOfCells[index] == 0); + + return index; +} + + +void TestRHeap::WalkCallback(TAny* aPtr, TCellType aCellType, TAny* aBuffer, TInt aLen) +{ + if (aLen>16375 && aPtr>0) // Don't test DL allocator + test(aCellType == EGoodAllocatedCell); + + TUint i = 0; + for(i=0; iAlloc(0x4000); + test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap); + test(iHeap->Count() == 1); + iHeap->Free(p1); + p1 = NULL; + test(iHeap->Count() == 0); + + // Medium buffer + p1=iHeap->Alloc(0x20000); + test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap); + test(iHeap->Count() == 1); + iHeap->Free(p1); + p1 = NULL; + test(iHeap->Count() == 0); + + // Large buffer + p1=iHeap->Alloc(0x700000); + test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap); + test(iHeap->Count() == 1); + iHeap->Free(p1); + p1 = NULL; + test(iHeap->Count() == 0); + + // Oversized buffer, not allocated + p1=iHeap->Alloc(0x900000); + test(p1 == NULL); + test(iHeap->Count() == 0); +} + + +/////////////////////////////////////////////////////////////////////////// +// Allocate and free multiple random sized buffers, sizes under 65 kB. // +// Check that all are allocated succesfully with Count. Free every other // +// of them, check the Count. Allocate more buffers sized under 655 kB // +// and free all buffers in reverse order. Check all are freed. // +/////////////////////////////////////////////////////////////////////////// +void TestRHeap::Test2(void) +{ + TInt ArraySize=10; + TInt ArrayIndex; + TAny** ArrayOfCells; + ArrayOfCells = new TAny*[ArraySize]; + + // Allocate set of buffers + for(ArrayIndex=0; ArrayIndexAlloc(GetRandomSize(0xFFFF)); + test(ArrayOfCells[ArrayIndex] != NULL); + } + test(iHeap->Count() == 10); + + // Free every other + for(ArrayIndex=0; ArrayIndexFree(ArrayOfCells[ArrayIndex]); + ArrayOfCells[ArrayIndex] = 0; + } + test(iHeap->Count() == 5); + + TInt ArraySize2=10; + TInt ArrayIndex2; + TAny** ArrayOfCells2; + ArrayOfCells2 = new TAny*[ArraySize2]; + + // Allocate larger buffers + for(ArrayIndex2=0; ArrayIndex2Alloc(GetRandomSize(0x7FFFF)); + test(ArrayOfCells2[ArrayIndex2] != NULL); + } + test(iHeap->Count() == 15); + + // Free all buffers in reverse order + for(ArrayIndex=9; ArrayIndex>=0; ArrayIndex-- ) + { + if(ArrayOfCells[ArrayIndex] != 0) + { + iHeap->Free(ArrayOfCells[ArrayIndex]); + ArrayOfCells[ArrayIndex] = 0; + } + } + for(ArrayIndex2=9; ArrayIndex2>=0; ArrayIndex2-- ) + { + if(ArrayOfCells2[ArrayIndex2] != 0) + { + iHeap->Free(ArrayOfCells2[ArrayIndex2]); + ArrayOfCells2[ArrayIndex2] = 0; + } + } + test(iHeap->Count() == 0); +} + + +/////////////////////////////////////////////////////////////////////// +// Allocate and free multiple random sized buffers. Use // +// DebugFunction(EWalk) to check that all allocated cells are found. // +/////////////////////////////////////////////////////////////////////// +void TestRHeap::Test3(void) +{ + TUint iAllocatedArraySize = 100; + iAllocatedArrayOfCells = new TAny*[iAllocatedArraySize]; + + // allocate 100 random cells and save them in iAllocatedArrayOfCells + for(iAllocatedArrayIndex=0; iAllocatedArrayIndexAlloc(GetRandomSize(0xFFFF)); + test(iAllocatedArrayOfCells[iAllocatedArrayIndex] != NULL); + } + test(iHeap->Count() == 100); //check that all 100 allocations have succeedeed + + // copy iAllocatedArrayOfCells => iWalkArrayOfCells + iWalkArrayOfCells = new TAny*[iWalkArrayIndex]; + for(iWalkArrayIndex=0; iWalkArrayIndexDebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this); + TBool ret = CheckWalkArrayEmpty(); + test(ret); // ...and iWalkArrayOfCells is emptied + + // copy iAllocatedArrayOfCells => iWalkArrayOfCells + iWalkArrayOfCells = new TAny*[iWalkArrayIndex]; + for(iWalkArrayIndex=0; iWalkArrayIndexFree(iWalkArrayOfCells[RandomIndex]); + iWalkArrayOfCells[RandomIndex] = 0; + iAllocatedArrayOfCells[RandomIndex] = 0; + } + test(iHeap->Count() == 60); + + //check that walk finds all the remaining allocated cells... + iHeap->DebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this); + ret = CheckWalkArrayEmpty(); + test(ret); // ...and iWalkArrayOfCells is emptied + + // allocate 20 more random cells starting on the first available free cell + iAllocatedArrayIndex = 0; + for (i=0; i<20; i++) + { + while (iAllocatedArrayOfCells[iAllocatedArrayIndex] != 0) + { + iAllocatedArrayIndex++; + } + iAllocatedArrayOfCells[iAllocatedArrayIndex] = iHeap->Alloc(GetRandomSize(0xFFFF)); + } + test(iHeap->Count() == 80); + + // copy iAllocatedArrayOfCells => iWalkArrayOfCells + iWalkArrayOfCells = new TAny*[iWalkArrayIndex]; + for(iWalkArrayIndex=0; iWalkArrayIndexDebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this); + ret = CheckWalkArrayEmpty(); + test(ret); // ...and iWalkArrayOfCells is emptied +} + + +void TestRHeap::CloseTests() + { + // close heap so we don't exceed chunk limit + iHeap->Close(); + } + + +GLDEF_C TInt E32Main(void) + { + test.Title(); + __KHEAP_MARK; + + TestRHeap T; + + test.Start(_L("Page Allocator Test")); + + TPtrC testHeapM=_L("TESTHEAP-MAIN"); + RHeap* iHeapM; + + iHeapM=User::ChunkHeap(&testHeapM,0x1800,0x800000); + + TMetaData metaData; + GetMeta(*iHeapM, metaData); + + iHeapM->Close(); + + if (metaData.iDLOnly) + { + test.Printf(_L("Page allocator is not used, no tests to run.\n")); + __KHEAP_MARKEND; + test.End(); + return(0); + } + + test.Next(_L("Init Paged allocator tests")); + T.InitTests(); + test.Next(_L("Test Paged allocator 1")); + T.Test1(); + test.Next(_L("Test Paged allocator 2")); + T.Test2(); + test.Next(_L("Test Paged allocator 3")); + T.Test3(); + T.CloseTests(); + + __KHEAP_CHECK(0); + __KHEAP_MARKEND; + + test.End(); + + return (0); + }