--- a/kerneltest/e32test/heap/t_heap.cpp Thu Aug 19 11:14:22 2010 +0300
+++ b/kerneltest/e32test/heap/t_heap.cpp Tue Aug 31 16:34:26 2010 +0300
@@ -66,6 +66,10 @@
#include <e32hal.h>
#include <e32def.h>
#include <e32def_private.h>
+#include "dla.h"
+#include "slab.h"
+#include "page_alloc.h"
+#include "heap_hybrid.h"
// Sets data for Test6
#define SetData(size) pHeap->Reset();\
@@ -90,7 +94,8 @@
#endif
const TInt KHeadSize = (TInt)RHeap::EAllocCellSize;
-const TInt KAlign = _FOFF(RHeap::_s_align, d);
+
+const TInt KAlign = RHeap::ECellAlignment;
const TInt KMinCellLength = _ALIGN_UP((KHeapMinCellSize + Max(TInt(RHeap::EFreeCellSize),TInt(RHeap::EAllocCellSize))),KAlign) - RHeap::EAllocCellSize;
const TInt KMinFreeSize = _ALIGN_UP((KHeapMinCellSize + Max(TInt(RHeap::EFreeCellSize),TInt(RHeap::EAllocCellSize))),KAlign);
@@ -108,7 +113,7 @@
RChunk iChunk;
TUint8 *iBase;
TUint8 *iTop;
- RHeap::SCell iFree;
+ //RHeap::SCell iFree;
};
#pragma warning ( disable :4705 ) // statement has no effect
@@ -118,12 +123,15 @@
#if defined(_DEBUG)
void RTestHeap::__DbgTest(void* aPtr) const
{
+ (void) aPtr;
+/*
RHeapDump& d = *(RHeapDump*)aPtr;
d.iMinLength=iMinLength;
d.iChunk.SetHandle(iChunkHandle);
d.iBase=iBase;
d.iTop=iTop;
d.iFree=iFree;
+*/
}
#endif
@@ -131,6 +139,8 @@
#if defined(_DEBUG)
TBool Invariant(RHeap* aHeap)
{
+ (void) aHeap;
+/*
RHeapDump dump;
((RTestHeap*)aHeap)->__DbgTest(&dump);
if(dump.iMinLength!=OrigDump.iMinLength) return(EFalse);
@@ -141,6 +151,7 @@
if(dump.iTop[-1]!=OrigDump.iTop[-1]) return(EFalse);
if(dump.iFree.len!=OrigDump.iFree.len) return(EFalse);
// iFree.Next changes during allocation/freeing etc.
+*/
return(ETrue);
}
#define INV(x) x;
@@ -153,6 +164,23 @@
LOCAL_D RHeap *gHeapPtr;
LOCAL_D RHeap *gHeapPtr2;
+/*
+Friend class of RHeapHybrid to access to hybrid heap metadata
+*/
+class TestHybridHeap
+{
+public:
+ static TBool IsHybrid(const RHybridHeap * aHybridHeap);
+};
+
+TBool TestHybridHeap::IsHybrid(const RHybridHeap * aHybridHeap)
+ {
+ if (aHybridHeap->iDLOnly)
+ return EFalse;
+ else
+ return ETrue;
+ }
+
class TestRHeap
{
public:
@@ -216,8 +244,9 @@
((RTestHeap*)pHeap)->__DbgTest(&OrigDump);
((RTestHeap*)pHeap)->__DbgTest(&dump);
- test(dump.iBase==pHeap->Base());
- test((dump.iTop-dump.iBase)==pHeap->Size());
+
+// test(dump.iBase==pHeap->Base());
+// test((dump.iTop-dump.iBase)==pHeap->Size());
pHeap->Check();
test(Invariant(pHeap));
pHeap->Close();
@@ -510,33 +539,12 @@
// Resize positively
for(TInt aSize=0; aSize<=BiggestBlock; aSize++, pHeap->Available(BiggestBlock))
{
- test(pHeap->ReAlloc(aCell, aSize)!=NULL);
+ aCell = pHeap->ReAlloc(aCell, aSize);
+ test(aCell!=NULL);
CellSize=pHeap->AllocLen(aCell);
test(CellSize>=aSize);
- if (aSize<KMinCellLength)
- test(CellSize==KMinCellLength);
- else
- test(CellSize<aSize+KAlign);
}
- // Note: when increasing a cell size the size is rounded up to the nearest 4 but when
- // decreasing a cell the size is rounded down to the nearest 8 - this is due to the fact
- // that when memory is released its size must be big enough to hold a free cell header which
- // is greater(8) than an allocated header(4)
- // i.e. size = 16, resize to 17 => result is 20. But resize to 15 stays as 16, resize to 9
- // stays as 16 but resize as 8 will resize to 8
-
- for(TInt aSize2=(TInt)pHeap->AllocLen(aCell); aSize2>=0; aSize2--)
- {
- test(pHeap->ReAlloc(aCell, aSize2)!=NULL);
-
- test((TInt)pHeap->AllocLen(aCell)>=aSize2);
-
- TInt aTmpSize2 = Max(_ALIGN_UP(aSize2 + RHeap::EAllocCellSize, KAlign), KMinFreeSize);
-
- test((TInt)pHeap->AllocLen(aCell)<=aTmpSize2+KMinFreeSize);
- }
-
pHeap->Check();
pHeap->Reset();
// Allocate a block, fill with data, allocate another block or two then resize the original
@@ -738,6 +746,18 @@
RMyHeap* myHeap=(RMyHeap*)User::ChunkHeap(&myHeapName,0x100,0x2000);
const TInt KnormHeapGrowBy = 0x2000;
RHeap* normHeap=User::ChunkHeap(NULL,0x100,0x20000,KnormHeapGrowBy);
+ //
+ // Configure paged heap threshold 128 Kb (pagepower 17)
+ //
+ RHybridHeap::STestCommand conf;
+ conf.iCommand = RHybridHeap::EGetConfig;
+ if ( normHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone )
+ {
+ test.Printf(_L("New allocator detected, configuring paged threshold to 128 kb\r\n"));
+ conf.iCommand = RHybridHeap::ESetConfig;
+ conf.iConfig.iPagePower = 17;
+ test( normHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&conf ) == KErrNone);
+ }
TAny* ptrMy1=myHeap->Alloc(0x102);
test(ptrMy1!=NULL);
@@ -784,8 +804,8 @@
// Calc the amount, if any, the overall size of normHeap will have been shrunk by
// will depend on value of KHeapShrinkHysRatio.
// 1st calc current total size of the allocated cells
- TInt normAllocdSize = normHeap->AllocLen(ptrNorm1)+RHeap::EAllocCellSize +
- normHeap->AllocLen(ptrNorm2)+RHeap::EAllocCellSize;
+ TInt normAllocdSize = normHeap->AllocLen(ptrNorm1)+KHeadSize +
+ normHeap->AllocLen(ptrNorm2)+KHeadSize;
TInt normReduce = RHeapCalcReduce(oldNormHeapSize-normAllocdSize,KnormHeapGrowBy);
oldNormHeapSize -= normReduce;
test(r==oldNormHeapSize);
@@ -797,7 +817,7 @@
r=myHeap->Size();
// Calc the current total size of the allocated cells
- TInt myAllocdSize = myHeap->AllocLen(ptrMy1)+RHeap::EAllocCellSize;
+ TInt myAllocdSize = myHeap->AllocLen(ptrMy1)+KHeadSize;
TInt myReduce=RHeapCalcReduce(oldMyHeapSize-myAllocdSize,1);
oldMyHeapSize -= myReduce;
test(r==oldMyHeapSize);
@@ -864,7 +884,6 @@
test(last+space <= chunk.Base()+size);
// but that it is within the alignment requirement, as less than this
// would be short of the end
- test(last+space > chunk.Base()+size-RHeap::ECellAlignment);
}
else
{
@@ -1126,6 +1145,7 @@
test.Start(_L("Create chunk to"));
TPtrC autoHeap=_L("AutoHeap");
gHeapPtr=User::ChunkHeap(&autoHeap,0x1800,0x6000);
+
test(gHeapPtr!=NULL);
TInt biggest;
TInt avail=gHeapPtr->Available(biggest);
@@ -1160,13 +1180,133 @@
test(comp==0);
TInt biggest1;
TInt avail1=gHeapPtr->Available(biggest1);
- test(avail1==avail1);
+ test(avail==avail1);
test(biggest==biggest1);
test(gHeapPtr->Count()==0);
gHeapPtr->Close();
test.End();
}
+LOCAL_C TInt NormalChunk(RChunk& aChunk, TInt aInitialSize, TInt aMaxSize)
+ {
+ TChunkCreateInfo createInfo;
+ createInfo.SetNormal(aInitialSize, aMaxSize);
+ TInt r=aChunk.Create(createInfo);
+ return r;
+ }
+
+LOCAL_C TInt DisconnectedChunk(RChunk& aChunk, TInt aInitialBottom, TInt aInitialTop, TInt aMaxSize)
+ {
+ TChunkCreateInfo createInfo;
+ createInfo.SetDisconnected(aInitialBottom, aInitialTop, aMaxSize);
+ TInt r=aChunk.Create(createInfo);
+ return r;
+ }
+
+LOCAL_C TBool TestIsHybridHeap(RHeap* aHeap)
+ {
+ RHybridHeap::STestCommand cmd;
+ cmd.iCommand = RHybridHeap::EHeapMetaData;
+ aHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&cmd, 0);
+
+ RHybridHeap* hybridHeap = (RHybridHeap*) cmd.iData;
+ return (TestHybridHeap::IsHybrid(hybridHeap));
+ }
+
+LOCAL_C void TestHeapType()
+ {
+ TBool onlyDL = EFalse;
+ _LIT(KHeap, "NamedHeap");
+ // 1: Create a heap in a local chunk
+ RHeap* heap;
+ heap = UserHeap::ChunkHeap(NULL,0x100,0x2000);
+ TBool hybrid = TestIsHybridHeap(heap);
+ if (hybrid==0)
+ {
+ test.Printf(_L("Only DL allocator is in use \n"));
+ onlyDL = ETrue;;
+ }
+ else
+ test(hybrid==1);
+ heap->Close();
+
+ // 2: Create a heap in a global chunk
+ heap = UserHeap::ChunkHeap(&KHeap,0,0x1800,0x6000);
+ hybrid = TestIsHybridHeap(heap);
+ if(!onlyDL)
+ test(hybrid==1);
+ heap->Close();
+
+ // 3: Create a heap in an existing normal chunk
+ RChunk chunk;
+ TInt r = NormalChunk(chunk,0,0x1000);
+ heap = UserHeap::ChunkHeap(chunk,0);
+ hybrid = TestIsHybridHeap(heap);
+ test(hybrid==0);
+ heap->Close();
+
+ // 4: Create a heap in an existing disconnected chunk
+ // when offset = 0. Minimum heap size for a hybrid heap is 12KB
+ r = DisconnectedChunk(chunk,0,0,0x3000);
+ heap = UserHeap::ChunkHeap(chunk,0);
+ hybrid = TestIsHybridHeap(heap);
+ if(!onlyDL)
+ test(hybrid==1);
+ heap->Close();
+
+ // 5: Create a heap in an existing disconnected chunk
+ // when offset > 0
+ r = DisconnectedChunk(chunk,0,0x1800,0x6000);
+ heap = UserHeap::OffsetChunkHeap(chunk,0,0x2800);
+ hybrid = TestIsHybridHeap(heap);
+ test(hybrid==0);
+ heap->Close();
+
+ // 6: Create a fixed length heap at a normal chunk's base address
+ r = NormalChunk(chunk,0x1000,0x1000);
+ heap = UserHeap::FixedHeap(chunk.Base(), 0x1000);
+ hybrid = TestIsHybridHeap(heap);
+ test(hybrid==0);
+ heap->Close();
+ chunk.Close();
+
+ // 7: Create a fixed length heap at a disconnected chunk's base address
+ // when bottom = 0
+ r = DisconnectedChunk(chunk,0,0x2000,0x2000);
+ heap = UserHeap::FixedHeap(chunk.Base(), 0x2000);
+ hybrid = TestIsHybridHeap(heap);
+ test(hybrid==0);
+ heap->Close();
+ chunk.Close();
+
+ // 8: Create a fixed length heap at a disconnected chunk's base address
+ // when bottom > 0
+ r = DisconnectedChunk(chunk,0x6000,0x7000,0x13000);
+ heap = UserHeap::FixedHeap(chunk.Base()+ 0x6000, 0x1000);
+ hybrid = TestIsHybridHeap(heap);
+ test(hybrid==0);
+ heap->Close();
+ chunk.Close();
+
+ // 9: Create a fixed length heap for allocated buffer
+ heap = UserHeap::ChunkHeap(&KNullDesC(), 4096, (4096 * 1024));
+ test(heap != NULL);
+ TAny* buffer = heap->Alloc(1024 * 1024);
+ test(buffer != NULL);
+ TInt lth = heap->AllocLen(buffer);
+ test.Printf(_L("Fixed heap buffer: %x, length: %x \n"), buffer, lth);
+
+ RHeap* heapf = UserHeap::FixedHeap(buffer, (1024 * 1024));
+ test(heapf != NULL);
+ test.Printf(_L("Fixed heap: %x \n"), heapf);
+ hybrid = TestIsHybridHeap(heapf);
+ test(hybrid==0);
+
+ heapf->Close();
+ heap->Free(buffer);
+
+ heap->Close();
+ }
GLDEF_C TInt E32Main(void)
{
@@ -1178,6 +1318,7 @@
test.Start(_L("Test 1"));
UserHal::PageSizeInBytes(PageSize);
TestRHeap T;
+
T.Test1();
test.Next(_L("Test auto expand and compress"));
TestAuto();
@@ -1204,10 +1345,12 @@
test.Next(_L("Shared heap test 3"));
SharedHeapTest3();
sem.Close();
+ test.Next(_L("Test HeapType()"));
+ TestHeapType();
__KHEAP_CHECK(0);
__KHEAP_MARKEND;
-//
+
test.End();
return(0);
}