kerneltest/e32test/heap/t_heappagealloc.cpp
changeset 109 b3a1d9898418
equal deleted inserted replaced
102:ef2a444a7410 109:b3a1d9898418
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\heap\t_page_alloc.cpp
       
    15 // Overview:
       
    16 // Tests RHeap class.
       
    17 // API Information:
       
    18 // RHeap
       
    19 // Details:
       
    20 // - Tests that the page bitmap is consistent (i.e. encoded sizes are sensible and 
       
    21 // encoded in the correct fashion.
       
    22 // - Tests that pages which appear in the page bitmap are present in memory by 
       
    23 // reading them.
       
    24 // -Tests that other pages are not readable  
       
    25 // - Tests page bitmap by creating an allocator where all allocations >= 4kB use
       
    26 // paged allocator, allocating a large number of regions of various sizes (from
       
    27 // 4 kB to b MB), checking that the walk function finds them all correctly, freeing
       
    28 // some of them, checking the walk function again, and so on. 
       
    29 // Platforms/Drives/Compatibility:
       
    30 // All
       
    31 // Assumptions/Requirement/Pre-requisites:
       
    32 // Failures and causes:
       
    33 // Base Port information:
       
    34 // 
       
    35 //
       
    36 
       
    37 #include <e32test.h>
       
    38 #include <e32hal.h>
       
    39 #include <e32def.h>
       
    40 #include <e32math.h>
       
    41 #include <e32def_private.h>
       
    42 #include "dla.h"
       
    43 #include "slab.h"
       
    44 #include "page_alloc.h"
       
    45 #include "heap_hybrid.h"
       
    46 
       
    47 
       
    48 struct TMetaData
       
    49     {
       
    50     TBool           iDLOnly;
       
    51     RFastLock*      iLock;
       
    52     TInt            iChunkSize;
       
    53     TInt            iSlabThreshold;
       
    54     unsigned        iSlabInitThreshold;
       
    55     unsigned        iSlabConfigBits;
       
    56     slab*           iPartialPage;
       
    57     slab*           iFullSlab;
       
    58     page*           iSparePage;
       
    59     TUint8*         iMemBase;
       
    60     unsigned char   iSizeMap[(MAXSLABSIZE>>2)+1];
       
    61     slabset         iSlabAlloc[MAXSLABSIZE>>2];
       
    62     slab**          iSlabAllocRealRootAddress[MAXSLABSIZE>>2];
       
    63     };
       
    64 
       
    65 LOCAL_D RTest test(_L("T_HEAPPAGEALLOC"));
       
    66 
       
    67 class TestHybridHeap
       
    68     {
       
    69 public:
       
    70     static TUint8* MemBase(const RHybridHeap * aHybridHeap);
       
    71     static void GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta);
       
    72     };
       
    73 
       
    74 TUint8* TestHybridHeap::MemBase(const RHybridHeap * aHybridHeap)
       
    75 	{
       
    76 	return aHybridHeap->iMemBase;
       
    77 	}
       
    78 
       
    79 void TestHybridHeap::GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta)
       
    80 {
       
    81     RHybridHeap::STestCommand cmd;
       
    82     cmd.iCommand = RHybridHeap::EHeapMetaData;
       
    83     TInt ret = aHeap.DebugFunction(RHeap::EHybridHeap, &cmd, 0);
       
    84     test(ret == KErrNone);
       
    85     
       
    86     RHybridHeap* hybridHeap = (RHybridHeap*) cmd.iData;
       
    87     
       
    88     aMeta.iDLOnly              = hybridHeap->iDLOnly;
       
    89     aMeta.iLock                = &hybridHeap->iLock;
       
    90     aMeta.iChunkSize           = hybridHeap->iChunkSize;
       
    91     aMeta.iSlabThreshold       = hybridHeap->iSlabThreshold;
       
    92     aMeta.iSlabInitThreshold   = hybridHeap->iSlabInitThreshold;
       
    93     aMeta.iSlabConfigBits      = hybridHeap->iSlabConfigBits;
       
    94     aMeta.iPartialPage         = hybridHeap->iPartialPage;
       
    95     aMeta.iFullSlab            = hybridHeap->iFullSlab;
       
    96     aMeta.iSparePage           = hybridHeap->iSparePage;
       
    97     aMeta.iMemBase             = hybridHeap->iMemBase;
       
    98 
       
    99     TInt i;
       
   100     TInt count;
       
   101     count = sizeof(aMeta.iSizeMap)/sizeof(unsigned char);
       
   102     for (i=0; i<count; ++i)
       
   103         {
       
   104         aMeta.iSizeMap[i] = hybridHeap->iSizeMap[i];
       
   105         }
       
   106     count = sizeof(aMeta.iSlabAlloc)/sizeof(slabset);
       
   107     for (i=0; i<count; ++i)
       
   108         {
       
   109         aMeta.iSlabAlloc[i].iPartial = hybridHeap->iSlabAlloc[i].iPartial;
       
   110         aMeta.iSlabAllocRealRootAddress[i] = &hybridHeap->iSlabAlloc[i].iPartial;
       
   111         }
       
   112 }
       
   113 
       
   114 LOCAL_C void GetMeta(RHeap& aHeap, TMetaData& aMeta)
       
   115 {
       
   116     TestHybridHeap::GetHeapMetaData(aHeap, aMeta);
       
   117 }
       
   118 
       
   119 class TestRHeap : public RHeap
       
   120 	{
       
   121 public:
       
   122 	void InitTests();
       
   123 	void Test1(void);
       
   124 	void Test2(void);
       
   125 	void Test3(void);
       
   126 	void CloseTests();
       
   127 	TUint GetRandomSize(TUint aMaxSize);
       
   128 	TUint GetRandomIndex(TUint aMaxIndex);
       
   129 	static void WalkCallback(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
       
   130 	TBool CheckWalkArrayEmpty();
       
   131 			
       
   132 private:
       
   133 	RHybridHeap* iHybridHeap;
       
   134 	RHeap *iHeap;
       
   135 	TUint8* iMemBase;			     // bottom of Paged/Slab memory (chunk base)
       
   136 	static TUint iWalkArraySize;
       
   137 	static TUint iWalkArrayIndex;
       
   138 	static TAny** iWalkArrayOfCells;
       
   139 	TUint iAllocatedArrayIndex;
       
   140 	TAny** iAllocatedArrayOfCells;
       
   141 	};
       
   142 
       
   143 TUint TestRHeap::iWalkArraySize = 100;
       
   144 TUint TestRHeap::iWalkArrayIndex = 0;
       
   145 TAny** TestRHeap::iWalkArrayOfCells = new TAny*[iWalkArraySize];
       
   146 
       
   147 void TestRHeap::InitTests()
       
   148 {
       
   149     // Allocate a chunk heap
       
   150 	TPtrC testHeap=_L("TESTHEAP");
       
   151 	iHeap=User::ChunkHeap(&testHeap,0x1800,0x800000); 
       
   152 	RHybridHeap::STestCommand cmd;
       
   153 	cmd.iCommand = RHybridHeap::EHeapMetaData;
       
   154 	iHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0);
       
   155 	iHybridHeap = (RHybridHeap*) cmd.iData;
       
   156 	iMemBase = TestHybridHeap::MemBase(iHybridHeap);
       
   157 	
       
   158 	// configure paged heap threshold 16 kB
       
   159 	cmd.iCommand = RHybridHeap::ESetConfig;
       
   160 	cmd.iConfig.iSlabBits = 0x0; //0xabe
       
   161 	cmd.iConfig.iDelayedSlabThreshold = 0x40000000;
       
   162 	cmd.iConfig.iPagePower = 14;
       
   163 	test(iHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0) == KErrNone);
       
   164 }
       
   165 
       
   166 
       
   167 TUint TestRHeap::GetRandomSize(TUint aMaxSize)
       
   168 {
       
   169 	TUint size = 0;
       
   170 	do
       
   171 	{
       
   172 		size = Math::Random() & aMaxSize;
       
   173 	}
       
   174 	while(size < 16384 ||  size > aMaxSize );
       
   175 	// subtract debug header size	
       
   176 	return size - 8;	
       
   177 }
       
   178 
       
   179 
       
   180 TUint TestRHeap::GetRandomIndex(TUint aMaxIndex)
       
   181 {
       
   182 	TUint index = 0;
       
   183 	do
       
   184 	    {
       
   185         index = Math::Random() & 0x7F;
       
   186 	    }
       
   187     while(index >= aMaxIndex || iWalkArrayOfCells[index] == 0);
       
   188 
       
   189 	return index;
       
   190 }
       
   191 
       
   192 
       
   193 void TestRHeap::WalkCallback(TAny* aPtr, TCellType aCellType, TAny* aBuffer, TInt aLen)
       
   194 {
       
   195     if (aLen>16375 && aPtr>0)    // Don't test DL allocator
       
   196         test(aCellType == EGoodAllocatedCell);
       
   197     
       
   198 	TUint i = 0;
       
   199 	for(i=0; i<iWalkArrayIndex; i++)
       
   200 	{
       
   201 		if(iWalkArrayOfCells[i] == aBuffer)
       
   202 		{
       
   203 			iWalkArrayOfCells[i] = NULL;
       
   204 			break;
       
   205 		}
       
   206 	}
       
   207 }
       
   208 
       
   209 TBool TestRHeap::CheckWalkArrayEmpty()
       
   210 {
       
   211 	TUint i = 0;
       
   212 	for(i=0; i<iWalkArrayIndex; i++)
       
   213 	{
       
   214 		if(iWalkArrayOfCells[i])
       
   215 		{
       
   216 			return EFalse;
       
   217 		}
       
   218 	}
       
   219 	return ETrue;
       
   220 }
       
   221 
       
   222 
       
   223 ///////////////////////////////////////////////////////////
       
   224 // Test page allocation with various sizes, 16 kB - 8 MB //
       
   225 // Simple test with fixed sizes.                         //
       
   226 ///////////////////////////////////////////////////////////
       
   227 void TestRHeap::Test1(void)
       
   228 {
       
   229 	// Allocate and free single paged buffers of different size
       
   230 	// Small buffer
       
   231 	TAny* p1 = NULL;
       
   232 	p1=iHeap->Alloc(0x4000);
       
   233 	test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap);
       
   234 	test(iHeap->Count() == 1);
       
   235 	iHeap->Free(p1);
       
   236 	p1 = NULL;
       
   237 	test(iHeap->Count() == 0);
       
   238 
       
   239 	// Medium buffer
       
   240 	p1=iHeap->Alloc(0x20000);
       
   241 	test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap);
       
   242 	test(iHeap->Count() == 1);
       
   243 	iHeap->Free(p1);
       
   244 	p1 = NULL;
       
   245 	test(iHeap->Count() == 0);
       
   246 	
       
   247 	// Large buffer
       
   248 	p1=iHeap->Alloc(0x700000);
       
   249 	test(p1 != NULL && p1 >= iMemBase && p1 < iHybridHeap);
       
   250 	test(iHeap->Count() == 1);
       
   251 	iHeap->Free(p1);
       
   252 	p1 = NULL;
       
   253 	test(iHeap->Count() == 0);
       
   254 
       
   255 	// Oversized buffer, not allocated
       
   256 	p1=iHeap->Alloc(0x900000);
       
   257 	test(p1 == NULL);
       
   258 	test(iHeap->Count() == 0);
       
   259 }
       
   260 
       
   261 
       
   262 ///////////////////////////////////////////////////////////////////////////
       
   263 // Allocate and free multiple random sized buffers, sizes under 65 kB.   //
       
   264 // Check that all are allocated succesfully with Count. Free every other //
       
   265 // of them, check the Count. Allocate more buffers sized under 655 kB    //
       
   266 // and free all buffers in reverse order. Check all are freed.           //
       
   267 ///////////////////////////////////////////////////////////////////////////
       
   268 void TestRHeap::Test2(void)
       
   269 {
       
   270     TInt ArraySize=10;
       
   271 	TInt ArrayIndex;
       
   272 	TAny** ArrayOfCells;
       
   273 	ArrayOfCells = new TAny*[ArraySize];
       
   274 
       
   275 	// Allocate set of buffers
       
   276 	for(ArrayIndex=0; ArrayIndex<ArraySize; ArrayIndex++)
       
   277 	{
       
   278 		ArrayOfCells[ArrayIndex] = 0;
       
   279 		ArrayOfCells[ArrayIndex] = iHeap->Alloc(GetRandomSize(0xFFFF));
       
   280 		test(ArrayOfCells[ArrayIndex] != NULL);
       
   281 	}
       
   282 	test(iHeap->Count() == 10);
       
   283 
       
   284 	// Free every other
       
   285 	for(ArrayIndex=0; ArrayIndex<ArraySize; ArrayIndex=ArrayIndex+2 )
       
   286 	{
       
   287 		iHeap->Free(ArrayOfCells[ArrayIndex]);
       
   288 		ArrayOfCells[ArrayIndex] = 0;
       
   289 	}
       
   290 	test(iHeap->Count() == 5);
       
   291 	
       
   292 	TInt ArraySize2=10;
       
   293 	TInt ArrayIndex2;
       
   294 	TAny** ArrayOfCells2;
       
   295 	ArrayOfCells2 = new TAny*[ArraySize2];
       
   296 
       
   297 	// Allocate larger buffers
       
   298 	for(ArrayIndex2=0; ArrayIndex2<ArraySize; ArrayIndex2++)
       
   299 	{
       
   300 		ArrayOfCells2[ArrayIndex2] = 0;
       
   301 		ArrayOfCells2[ArrayIndex2] = iHeap->Alloc(GetRandomSize(0x7FFFF));
       
   302 		test(ArrayOfCells2[ArrayIndex2] != NULL);
       
   303 	}
       
   304 	test(iHeap->Count() == 15);
       
   305 
       
   306 	// Free all buffers in reverse order
       
   307 	for(ArrayIndex=9; ArrayIndex>=0; ArrayIndex-- )
       
   308 	{
       
   309 		if(ArrayOfCells[ArrayIndex] != 0)
       
   310 		{
       
   311 			iHeap->Free(ArrayOfCells[ArrayIndex]);
       
   312 			ArrayOfCells[ArrayIndex] = 0;
       
   313 		}
       
   314 	}
       
   315 	for(ArrayIndex2=9; ArrayIndex2>=0; ArrayIndex2-- )
       
   316 	{
       
   317 		if(ArrayOfCells2[ArrayIndex2] != 0)
       
   318 		{
       
   319 			iHeap->Free(ArrayOfCells2[ArrayIndex2]);
       
   320 			ArrayOfCells2[ArrayIndex2] = 0;
       
   321 		}
       
   322 	}
       
   323 	test(iHeap->Count() == 0);
       
   324 }
       
   325 
       
   326 
       
   327 ///////////////////////////////////////////////////////////////////////
       
   328 // Allocate and free multiple random sized buffers. Use              // 
       
   329 // DebugFunction(EWalk) to check that all allocated cells are found. //
       
   330 ///////////////////////////////////////////////////////////////////////
       
   331 void TestRHeap::Test3(void)
       
   332 {
       
   333     TUint iAllocatedArraySize = 100;
       
   334     iAllocatedArrayOfCells = new TAny*[iAllocatedArraySize];
       
   335     
       
   336     // allocate 100 random cells and save them in iAllocatedArrayOfCells
       
   337     for(iAllocatedArrayIndex=0; iAllocatedArrayIndex<iAllocatedArraySize; iAllocatedArrayIndex++)
       
   338     {
       
   339         iAllocatedArrayOfCells[iAllocatedArrayIndex] = 0;
       
   340         iAllocatedArrayOfCells[iAllocatedArrayIndex] = iHeap->Alloc(GetRandomSize(0xFFFF));
       
   341         test(iAllocatedArrayOfCells[iAllocatedArrayIndex] != NULL);
       
   342     }
       
   343     test(iHeap->Count() == 100);    //check that all 100 allocations have succeedeed
       
   344 	
       
   345     // copy iAllocatedArrayOfCells => iWalkArrayOfCells
       
   346     iWalkArrayOfCells = new TAny*[iWalkArrayIndex];
       
   347     for(iWalkArrayIndex=0; iWalkArrayIndex<iWalkArraySize; iWalkArrayIndex++)
       
   348         {
       
   349             iWalkArrayOfCells[iWalkArrayIndex] = 0;
       
   350             iWalkArrayOfCells[iWalkArrayIndex] = iAllocatedArrayOfCells[iWalkArrayIndex];
       
   351             test(iWalkArrayOfCells[iWalkArrayIndex] == iAllocatedArrayOfCells[iWalkArrayIndex]);
       
   352         }
       
   353     
       
   354     //check that walk finds all allocated cells...
       
   355         iHeap->DebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this);  
       
   356         TBool ret = CheckWalkArrayEmpty();
       
   357         test(ret);     // ...and iWalkArrayOfCells is emptied
       
   358         
       
   359 	// copy iAllocatedArrayOfCells => iWalkArrayOfCells
       
   360 	    iWalkArrayOfCells = new TAny*[iWalkArrayIndex];
       
   361 	    for(iWalkArrayIndex=0; iWalkArrayIndex<iWalkArraySize; iWalkArrayIndex++)
       
   362 	        {
       
   363 	            iWalkArrayOfCells[iWalkArrayIndex] = 0;
       
   364 	            iWalkArrayOfCells[iWalkArrayIndex] = iAllocatedArrayOfCells[iWalkArrayIndex];
       
   365 	            test(iWalkArrayOfCells[iWalkArrayIndex] == iAllocatedArrayOfCells[iWalkArrayIndex]);
       
   366 	        }
       
   367 	
       
   368 	// free 40 random cells from iWalkArrayOfCells
       
   369 	TUint i;
       
   370 	for (i=0; i<40; i++)
       
   371 	    {
       
   372         TUint RandomIndex = GetRandomIndex(99);
       
   373         iHeap->Free(iWalkArrayOfCells[RandomIndex]);
       
   374         iWalkArrayOfCells[RandomIndex] = 0;
       
   375         iAllocatedArrayOfCells[RandomIndex] = 0;
       
   376 	    }
       
   377 	test(iHeap->Count() == 60);
       
   378 	
       
   379 	//check that walk finds all the remaining allocated cells...
       
   380 	iHeap->DebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this);  
       
   381 	ret = CheckWalkArrayEmpty();
       
   382 	test(ret);     // ...and iWalkArrayOfCells is emptied
       
   383 	
       
   384 	// allocate 20 more random cells starting on the first available free cell
       
   385 	iAllocatedArrayIndex = 0;
       
   386 	for (i=0; i<20; i++)
       
   387 	    {
       
   388         while (iAllocatedArrayOfCells[iAllocatedArrayIndex] != 0)
       
   389             {
       
   390             iAllocatedArrayIndex++;
       
   391             }
       
   392         iAllocatedArrayOfCells[iAllocatedArrayIndex] = iHeap->Alloc(GetRandomSize(0xFFFF));
       
   393 	    }
       
   394 	test(iHeap->Count() == 80);
       
   395 	
       
   396 	// copy iAllocatedArrayOfCells => iWalkArrayOfCells
       
   397 	iWalkArrayOfCells = new TAny*[iWalkArrayIndex];
       
   398 	    for(iWalkArrayIndex=0; iWalkArrayIndex<iWalkArraySize; iWalkArrayIndex++)
       
   399 	        {
       
   400 	            iWalkArrayOfCells[iWalkArrayIndex] = 0;
       
   401 	            iWalkArrayOfCells[iWalkArrayIndex] = iAllocatedArrayOfCells[iWalkArrayIndex];
       
   402 	            test(iWalkArrayOfCells[iWalkArrayIndex] == iAllocatedArrayOfCells[iWalkArrayIndex]);
       
   403 	        }
       
   404 	
       
   405 	//check that walk finds all the earlier and newly allocated cells...
       
   406 	iHeap->DebugFunction(EWalk, (TAny*)&WalkCallback, (TAny*)this);  
       
   407 	ret = CheckWalkArrayEmpty();
       
   408 	test(ret);     // ...and iWalkArrayOfCells is emptied
       
   409 }
       
   410 
       
   411 	
       
   412 void TestRHeap::CloseTests()
       
   413 	{
       
   414 		// close heap so we don't exceed chunk limit
       
   415 		iHeap->Close();  
       
   416 	}
       
   417 
       
   418 	
       
   419 GLDEF_C TInt E32Main(void)
       
   420 	{
       
   421 	test.Title();
       
   422 	__KHEAP_MARK;
       
   423 	
       
   424 	TestRHeap T;
       
   425 	
       
   426 	test.Start(_L("Page Allocator Test"));
       
   427 		    
       
   428 	TPtrC testHeapM=_L("TESTHEAP-MAIN");
       
   429     RHeap* iHeapM;
       
   430 
       
   431 	iHeapM=User::ChunkHeap(&testHeapM,0x1800,0x800000); 
       
   432 	
       
   433     TMetaData metaData;
       
   434     GetMeta(*iHeapM, metaData);
       
   435 
       
   436     iHeapM->Close();
       
   437     
       
   438     if (metaData.iDLOnly)
       
   439         {
       
   440         test.Printf(_L("Page allocator is not used, no tests to run.\n"));
       
   441         __KHEAP_MARKEND;
       
   442         test.End();
       
   443         return(0);
       
   444         }
       
   445     
       
   446     test.Next(_L("Init Paged allocator tests"));
       
   447     T.InitTests();
       
   448 	test.Next(_L("Test Paged allocator 1"));
       
   449 	T.Test1();
       
   450 	test.Next(_L("Test Paged allocator 2"));
       
   451 	T.Test2();
       
   452 	test.Next(_L("Test Paged allocator 3"));
       
   453 	T.Test3();
       
   454 	T.CloseTests();
       
   455 
       
   456 	__KHEAP_CHECK(0);
       
   457 	__KHEAP_MARKEND;
       
   458 	
       
   459 	test.End();
       
   460 	
       
   461 	return (0);    
       
   462     }