kerneltest/e32test/heap/t_heapstress.cpp
changeset 109 b3a1d9898418
child 293 0659d0e1a03c
equal deleted inserted replaced
102:ef2a444a7410 109:b3a1d9898418
       
     1 // Copyright (c) 2002-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_heaphybridstress.cpp
       
    15 // Overview:
       
    16 // Tests RHybridHeap class: stress test
       
    17 // API Information:
       
    18 // RHybridHeap/RHeap
       
    19 // Details:
       
    20 // - Stress test heap implementation that allocates, frees
       
    21 //   and reallocates cells in random patterns, and checks the heap.
       
    22 // - Allocated/reallocated buffer content is verified, when buffer is freed/reallocated.
       
    23 // - Stress test with a single thread
       
    24 // - Stress test with two threads that run concurrently.
       
    25 // - Tests configured for slab, doug lea, paged and hybrid allocators
       
    26 // Platforms/Drives/Compatibility:
       
    27 // All
       
    28 // Assumptions/Requirement/Pre-requisites:
       
    29 // Failures and causes:
       
    30 // Base Port information:
       
    31 // 
       
    32 //
       
    33 
       
    34 #include <e32test.h>
       
    35 #include <e32hal.h>
       
    36 #include <e32def.h>
       
    37 #include <e32def_private.h>
       
    38 #include "dla.h"
       
    39 #include "slab.h"
       
    40 #include "page_alloc.h"
       
    41 #include "heap_hybrid.h"
       
    42 
       
    43 // Needed for KHeapShrinkHysRatio which is now ROM 'patchdata'
       
    44 #include "TestRHeapShrink.h"
       
    45 
       
    46 //-------------------------------------------
       
    47 
       
    48 //#define TSTDBG_PRINTMETA(a) a
       
    49 #define TSTDBG_PRINTMETA(a)
       
    50 
       
    51 //-------------------------------------------
       
    52 
       
    53 
       
    54 #ifdef __EABI__
       
    55        IMPORT_D extern const TInt KHeapMinCellSize;
       
    56 #else
       
    57        const TInt KHeapMinCellSize = 0;
       
    58 #endif
       
    59 
       
    60 RTest test(_L("T_HEAPSTRESS"));
       
    61 
       
    62 #define TEST_ALIGN(p,a)     test((TLinAddr(p)&((a)-1))==0)
       
    63 
       
    64 
       
    65 #define TST_HEAP_MAX_LTH 0x4000000 // 64M
       
    66 #define MAX_CELL_COUNT 0x100000 // 0x100 0x1000 0x10000 0x100000
       
    67 #define MAX_THREAD_COUNT 2
       
    68 LOCAL_D TUint8* HeapStressCell[MAX_THREAD_COUNT][MAX_CELL_COUNT];
       
    69 LOCAL_D TInt HeapStressLen[MAX_THREAD_COUNT][MAX_CELL_COUNT];
       
    70 
       
    71 enum TTestHybridHeapFunc {ETstOnlySlab, ETstOnlyDl, ETstOnlyPaged, ETstHybrid};
       
    72 enum TTestType {ETestE32Test, ETestForeverOne, ETestForeverAll};
       
    73 
       
    74 LOCAL_D TTimeIntervalMicroSeconds32 TickPeriod;
       
    75 
       
    76 //--------- config parameters - begin
       
    77 LOCAL_D TTestType TestType;
       
    78 LOCAL_D TInt TestTimeAsSeconds;
       
    79 LOCAL_D TBool TestForeverMultiThreadTest;
       
    80 LOCAL_D TTestHybridHeapFunc TestHybridHeapFunc;
       
    81 LOCAL_D TInt CurrMaxCellCount;
       
    82 LOCAL_D TInt HeapMaxLength;
       
    83 //--------- config parameters - end
       
    84 
       
    85 LOCAL_D TBool DlOnly;
       
    86 
       
    87 LOCAL_D TInt SlabThreshold;
       
    88 LOCAL_D TInt PageThreshold;
       
    89 
       
    90 
       
    91 struct TMetaData
       
    92     {
       
    93     TBool           iDLOnly;
       
    94     RFastLock*      iLock;
       
    95     TInt            iChunkSize;
       
    96     TInt            iSlabThreshold;
       
    97     TInt            iPageThreshold;
       
    98     TInt            iSlabInitThreshold;
       
    99     TUint32         iSlabConfigBits;
       
   100     slab*           iPartialPage;
       
   101     slab*           iFullSlab;
       
   102     page*           iSparePage;
       
   103     TUint8*         iMemBase;
       
   104     TUint8          iSizeMap[(MAXSLABSIZE>>2)+1];
       
   105     slabset         iSlabAlloc[MAXSLABSIZE>>2];
       
   106     slab**          iSlabAllocRealRootAddress[MAXSLABSIZE>>2];
       
   107     };
       
   108 
       
   109 class TestHybridHeap
       
   110     {
       
   111 public:
       
   112     static void GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta);
       
   113     };
       
   114 
       
   115 void TestHybridHeap::GetHeapMetaData(RHeap& aHeap, TMetaData& aMeta)
       
   116 {
       
   117     RHybridHeap::STestCommand cmd;
       
   118     cmd.iCommand = RHybridHeap::EHeapMetaData;
       
   119     TInt ret = aHeap.DebugFunction(RHeap::EHybridHeap, &cmd, 0);
       
   120     test(ret == KErrNone);
       
   121     
       
   122     RHybridHeap* hybridHeap = (RHybridHeap*)cmd.iData;
       
   123     
       
   124     aMeta.iDLOnly              = hybridHeap->iDLOnly;
       
   125     aMeta.iLock                = &hybridHeap->iLock;
       
   126     aMeta.iChunkSize           = hybridHeap->iChunkSize;
       
   127     aMeta.iSlabThreshold       = hybridHeap->iSlabThreshold;
       
   128     aMeta.iPageThreshold       = hybridHeap->iPageThreshold;
       
   129     aMeta.iSlabInitThreshold   = hybridHeap->iSlabInitThreshold;
       
   130     aMeta.iSlabConfigBits      = hybridHeap->iSlabConfigBits;
       
   131     aMeta.iPartialPage         = hybridHeap->iPartialPage;
       
   132     aMeta.iFullSlab            = hybridHeap->iFullSlab;
       
   133     aMeta.iSparePage           = hybridHeap->iSparePage;
       
   134     aMeta.iMemBase             = hybridHeap->iMemBase;
       
   135 
       
   136     TInt i;
       
   137     TInt count;
       
   138     count = sizeof(aMeta.iSizeMap)/sizeof(unsigned char);
       
   139     for (i=0; i<count; ++i)
       
   140         {
       
   141         aMeta.iSizeMap[i] = hybridHeap->iSizeMap[i];
       
   142         }
       
   143     count = sizeof(aMeta.iSlabAlloc)/sizeof(slabset);
       
   144     for (i=0; i<count; ++i)
       
   145         {
       
   146         aMeta.iSlabAlloc[i].iPartial = hybridHeap->iSlabAlloc[i].iPartial;
       
   147         aMeta.iSlabAllocRealRootAddress[i] = &hybridHeap->iSlabAlloc[i].iPartial;
       
   148         }
       
   149 }
       
   150 
       
   151 LOCAL_C void GetMeta(RHeap& aHeap, TMetaData& aMeta)
       
   152 {
       
   153     TestHybridHeap::GetHeapMetaData(aHeap, aMeta);
       
   154 }
       
   155 
       
   156 
       
   157 TSTDBG_PRINTMETA(
       
   158 LOCAL_C void PrintMeta(const char* aText, TMetaData& aMeta)
       
   159 {
       
   160     RDebug::Printf("=========== HeapMetaData (local) - begin: %s", aText);
       
   161 
       
   162     RDebug::Printf("iDLOnly: 0x%08x", aMeta.iDLOnly);
       
   163     RDebug::Printf("iChunkSize: 0x%08x", aMeta.iChunkSize);
       
   164     RDebug::Printf("iSlabThreshold: 0x%08x / %d", aMeta.iSlabThreshold, aMeta.iSlabThreshold);
       
   165     RDebug::Printf("iPageThreshold: 0x%08x / %d", aMeta.iPageThreshold, aMeta.iPageThreshold);
       
   166     RDebug::Printf("iSlabInitThreshold: 0x%08x / %d", aMeta.iSlabInitThreshold, aMeta.iSlabInitThreshold);
       
   167     RDebug::Printf("iSlabConfigBits: 0x%08x", aMeta.iSlabConfigBits);
       
   168     RDebug::Printf("iPartialPage: 0x%08x", aMeta.iPartialPage);
       
   169     RDebug::Printf("iFullSlab: 0x%08x", aMeta.iFullSlab);
       
   170     RDebug::Printf("iSparePage: 0x%08x", aMeta.iSparePage);
       
   171     RDebug::Printf("iMemBase: 0x%08x", aMeta.iMemBase);
       
   172 
       
   173     TInt i;
       
   174     TInt count;
       
   175     count = sizeof(aMeta.iSizeMap)/sizeof(unsigned char);
       
   176     for (i=0; i<count; ++i)
       
   177         {
       
   178         RDebug::Printf("iSizeMap[%d]: %d", i, aMeta.iSizeMap[i]);
       
   179         }
       
   180     count = sizeof(aMeta.iSlabAlloc)/sizeof(slabset);
       
   181     for (i=0; i<count; ++i)
       
   182         {
       
   183         RDebug::Printf("iSlabAlloc[%d].iPartial: 0x%08x", i, aMeta.iSlabAlloc[i].iPartial);
       
   184         }
       
   185     for (i=0; i<count; ++i)
       
   186         {
       
   187         RDebug::Printf("iSlabAllocRealRootAddress[%d]: 0x%08x", i, aMeta.iSlabAllocRealRootAddress[i]);
       
   188         }
       
   189     RDebug::Printf("=========== HeapMetaData (local) - end");
       
   190 }
       
   191 )
       
   192 
       
   193 LOCAL_C void ConfHeap(RHeap* aHeap)
       
   194 {
       
   195     RHybridHeap::STestCommand cmd;
       
   196 
       
   197     if (TestHybridHeapFunc == ETstOnlySlab)
       
   198         {
       
   199         cmd.iCommand = RHybridHeap::ESetConfig;
       
   200         cmd.iConfig.iSlabBits = 0xabe;
       
   201         cmd.iConfig.iDelayedSlabThreshold = 0;            // 0 -> use slab at once from the beginning
       
   202         cmd.iConfig.iPagePower = 0;                       // 0 -> no page allocator
       
   203         }
       
   204     else if (TestHybridHeapFunc == ETstOnlyDl)
       
   205         {
       
   206         cmd.iCommand = RHybridHeap::ESetConfig;
       
   207         cmd.iConfig.iSlabBits = 0xabe;
       
   208         cmd.iConfig.iDelayedSlabThreshold = 0x40000000;   // 1G -> slab never used
       
   209         cmd.iConfig.iPagePower = 0;                       // 0 -> no page allocator
       
   210         }
       
   211     else if (TestHybridHeapFunc == ETstOnlyPaged)
       
   212         {
       
   213         cmd.iCommand = RHybridHeap::ESetConfig;
       
   214         cmd.iConfig.iSlabBits = 0xabe;
       
   215         cmd.iConfig.iDelayedSlabThreshold = 0x40000000;   // 1G -> slab never used
       
   216         cmd.iConfig.iPagePower = 14;                      // min page 14 -> 16K
       
   217         }
       
   218     else if (TestHybridHeapFunc == ETstHybrid)
       
   219         {
       
   220         cmd.iCommand = RHybridHeap::ESetConfig;
       
   221         cmd.iConfig.iSlabBits = 0xabe;
       
   222         cmd.iConfig.iDelayedSlabThreshold = 0;            // 0 -> use slab at once from the beginning
       
   223         cmd.iConfig.iPagePower = 14;                      // min page 14 -> 16K
       
   224         }
       
   225     else
       
   226         {
       
   227         test(0);
       
   228         }
       
   229     
       
   230     TInt ret = aHeap->DebugFunction(RHeap::EHybridHeap, &cmd, 0);
       
   231     test(ret == KErrNone);
       
   232 }
       
   233 
       
   234 LOCAL_C TInt MinPagedAllocLength(void)
       
   235 {
       
   236     return (1 << PageThreshold);
       
   237 }
       
   238 
       
   239 LOCAL_C TUint32 RandomPagedLength(TUint32 aRandom)
       
   240 {
       
   241     TUint32 ret;
       
   242     ret = aRandom;
       
   243     ret <<= PageThreshold;
       
   244     if (TestHybridHeapFunc == ETstOnlyPaged)
       
   245         {
       
   246         //ret &= 0xfffff; // below 1M
       
   247         ret &= 0x7ffff; // below 512K
       
   248         }
       
   249     else
       
   250         {
       
   251         ret &= 0x1ffff; // below 128K
       
   252         }
       
   253     if (ret == 0)
       
   254         {
       
   255         ret = MinPagedAllocLength();
       
   256         }
       
   257     return ret;
       
   258 }
       
   259 
       
   260 #if 0            
       
   261 LOCAL_C TUint TicksAsMilliSeconds(TUint aTicks)
       
   262 {
       
   263     TUint time = TUint((TUint64)aTicks*(TUint64)TickPeriod.Int()/(TUint64)1000);
       
   264     return time;
       
   265 }
       
   266 #endif
       
   267 
       
   268 LOCAL_C TBool IsDlOnly(void)
       
   269 {
       
   270     TestHybridHeapFunc = ETstHybrid;
       
   271     
       
   272     RHeap* heap;
       
   273     heap = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x4000, 0x1000, 4);
       
   274     test(heap != NULL);
       
   275 
       
   276     ConfHeap(heap);
       
   277     
       
   278     TMetaData metaData;
       
   279     GetMeta(*heap, metaData);
       
   280     
       
   281     heap->Close();
       
   282     return metaData.iDLOnly;
       
   283 }
       
   284 
       
   285 LOCAL_C RHeap* CreateTestHeap(TInt aAlign)
       
   286 {
       
   287     if (HeapMaxLength > TST_HEAP_MAX_LTH)
       
   288         {
       
   289         HeapMaxLength = TST_HEAP_MAX_LTH;
       
   290         }
       
   291     
       
   292     if (CurrMaxCellCount > MAX_CELL_COUNT)
       
   293         {
       
   294         CurrMaxCellCount = MAX_CELL_COUNT;
       
   295         }
       
   296     
       
   297     RHeap* heap;
       
   298     heap = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, HeapMaxLength, 0x1000, aAlign);
       
   299     test(heap != NULL);
       
   300 
       
   301     ConfHeap(heap);
       
   302     
       
   303     TMetaData metaData;
       
   304     GetMeta(*heap, metaData);
       
   305     
       
   306     if (TestHybridHeapFunc == ETstOnlySlab)
       
   307         {
       
   308         SlabThreshold = metaData.iSlabThreshold;
       
   309         test(SlabThreshold != 0);
       
   310         }
       
   311     else if (TestHybridHeapFunc == ETstOnlyDl)
       
   312         {
       
   313         }
       
   314     else if (TestHybridHeapFunc == ETstOnlyPaged)
       
   315         {
       
   316         PageThreshold = metaData.iPageThreshold;
       
   317         test(PageThreshold >= 14);
       
   318         }
       
   319     else if (TestHybridHeapFunc == ETstHybrid)
       
   320         {
       
   321         }
       
   322     else
       
   323         {
       
   324         test(0);
       
   325         }
       
   326 
       
   327     return heap;
       
   328 }
       
   329 
       
   330 //-------------------------------------------------------------------
       
   331 
       
   332 struct STestCell
       
   333     {
       
   334     enum {EMagic = 0xb8aa3b29};
       
   335 
       
   336     TUint32 iLength;
       
   337     TUint32 iData[1];
       
   338 
       
   339     void Set(TInt aLength);
       
   340     void Verify(TInt aLength);
       
   341     void Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength);
       
   342     };
       
   343 
       
   344 void STestCell::Set(TInt aLength)
       
   345     {
       
   346     TInt i;
       
   347     TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic;
       
   348     if (aLength < (TInt) sizeof(iLength))
       
   349         {
       
   350         return;
       
   351         }
       
   352     iLength = x;
       
   353     aLength /= sizeof(TUint32);
       
   354     for (i=0; i<aLength-1; ++i)
       
   355         {
       
   356         x *= 69069;
       
   357         x += 41;
       
   358         iData[i] = x;
       
   359         }
       
   360     }
       
   361 
       
   362 void STestCell::Verify(TInt aLength)
       
   363     {
       
   364     Verify(this, aLength, aLength);
       
   365     }
       
   366 
       
   367 void STestCell::Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength)
       
   368     {
       
   369     TInt i;
       
   370     TUint32 x = (TUint32)aInitPtr ^ (TUint32)aInitLength ^ (TUint32)EMagic;
       
   371     if (aLength < (TInt) sizeof(iLength))
       
   372         {
       
   373         return;
       
   374         }
       
   375     test(iLength == x);
       
   376     aLength /= sizeof(TUint32);
       
   377     for (i=0; i<aLength-1; ++i)
       
   378         {
       
   379         x *= 69069;
       
   380         x += 41;
       
   381         test(iData[i] == x);
       
   382         }
       
   383     }
       
   384 
       
   385 class RTestHeap : public RHeap
       
   386     {
       
   387 public:
       
   388     TInt CheckAllocatedCell(const TAny* aCell) const;
       
   389     void FullCheckAllocatedCell(const TAny* aCell) const;
       
   390     TAny* TestAlloc(TInt aSize);
       
   391     void TestFree(TAny* aPtr);
       
   392     TAny* TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
       
   393     void FullCheck();
       
   394     static void WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
       
   395     };
       
   396 
       
   397 TInt RTestHeap::CheckAllocatedCell(const TAny* aCell) const
       
   398     {
       
   399     TInt len = AllocLen(aCell);
       
   400     return len;
       
   401     }
       
   402 
       
   403 void RTestHeap::FullCheckAllocatedCell(const TAny* aCell) const
       
   404     {
       
   405     ((STestCell*)aCell)->Verify(CheckAllocatedCell(aCell));
       
   406     }
       
   407 
       
   408 TAny* RTestHeap::TestAlloc(TInt aSize)
       
   409     {
       
   410     TAny* p = Alloc(aSize);
       
   411     if (p)
       
   412         {
       
   413         TInt len = CheckAllocatedCell(p);
       
   414         test(len>=aSize);       
       
   415         ((STestCell*)p)->Set(len);
       
   416         }
       
   417     return p;
       
   418     }
       
   419 
       
   420 void RTestHeap::TestFree(TAny* aPtr)
       
   421     {
       
   422     if (aPtr)
       
   423         {
       
   424         FullCheckAllocatedCell(aPtr);
       
   425         }
       
   426     Free(aPtr);
       
   427     }
       
   428 
       
   429 TAny* RTestHeap::TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode)
       
   430     {
       
   431     TInt old_len = aPtr ? CheckAllocatedCell(aPtr) : 0;
       
   432     if (aPtr)
       
   433         ((STestCell*)aPtr)->Verify(old_len);
       
   434     TAny* p = ReAlloc(aPtr, aSize, aMode);
       
   435     if (!p)
       
   436         {
       
   437         ((STestCell*)aPtr)->Verify(old_len);
       
   438         return p;
       
   439         }
       
   440     TInt new_len = CheckAllocatedCell(p);
       
   441     test(new_len>=aSize);       
       
   442     if (p == aPtr)
       
   443         {
       
   444         ((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len));
       
   445         if (new_len != old_len)
       
   446             ((STestCell*)p)->Set(new_len);
       
   447         return p;
       
   448         }
       
   449     test(!(aMode & ENeverMove));
       
   450     test((new_len > old_len) || (aMode & EAllowMoveOnShrink));
       
   451     if (old_len)
       
   452         ((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, aSize));
       
   453     ((STestCell*)p)->Set(new_len);
       
   454     return p;
       
   455     }
       
   456 
       
   457 struct SHeapCellInfo
       
   458     {
       
   459     RTestHeap* iHeap;
       
   460     TInt iTotalAlloc;
       
   461     TInt iTotalAllocSize;
       
   462     TInt iTotalFree;
       
   463     TUint8* iNextCell;
       
   464     };
       
   465 
       
   466 void RTestHeap::WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen)
       
   467     {
       
   468     (void)aCell;
       
   469     ::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr;
       
   470     switch(aType)
       
   471         {
       
   472         case EGoodAllocatedCell:
       
   473             {
       
   474             TInt len = aLen;
       
   475             info.iTotalAllocSize += len;
       
   476             STestCell* pT = (STestCell*)aCell;
       
   477             ++info.iTotalAlloc;
       
   478             pT->Verify(len);
       
   479             break;
       
   480             }
       
   481         case EGoodFreeCell:
       
   482             {
       
   483             ++info.iTotalFree;
       
   484             break;
       
   485             }
       
   486         default:
       
   487             test.Printf(_L("TYPE=%d ??\n"),aType);
       
   488             test(0);
       
   489             break;
       
   490         }
       
   491     }
       
   492 
       
   493 void RTestHeap::FullCheck()
       
   494     {
       
   495     ::SHeapCellInfo info;
       
   496     Mem::FillZ(&info, sizeof(info));
       
   497     info.iHeap = this;
       
   498     DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info);
       
   499     TInt count = AllocSize(iTotalAllocSize);
       
   500     test(info.iTotalAlloc == count);
       
   501     test(info.iTotalAllocSize == iTotalAllocSize);
       
   502     }
       
   503 
       
   504 
       
   505 struct STestStress
       
   506     {
       
   507     RThread iThread;
       
   508     volatile TBool iStop;
       
   509     TInt iAllocs;
       
   510     TInt iFailedAllocs;
       
   511     TInt iFrees;
       
   512     TInt iReAllocs;
       
   513     TInt iFailedReAllocs;
       
   514     TInt iChecks;
       
   515     TUint32 iSeed;
       
   516     RAllocator* iAllocator;
       
   517     TInt iThreadIndex;
       
   518 
       
   519     TUint32 Random();
       
   520     };
       
   521 
       
   522 TUint32 FirstSeed(TInt aThreadIndex)
       
   523     {
       
   524     static TUint32 seed0 = 0xb504f334;
       
   525     static TUint32 seed1 = 0xddb3d743;
       
   526     static TBool first = ETrue;
       
   527 
       
   528     TUint32 ret;
       
   529 
       
   530     if (aThreadIndex == 0)
       
   531         {
       
   532         ret = seed0;
       
   533         }
       
   534     else
       
   535         {
       
   536         ret = seed1;
       
   537         }
       
   538     
       
   539     if (first)
       
   540         {
       
   541         first = EFalse;
       
   542         }
       
   543     
       
   544     if (aThreadIndex == 0)
       
   545         {
       
   546         seed0 *= 69069;
       
   547         seed0 += 41;
       
   548         }
       
   549     else
       
   550         {
       
   551         seed1 *= 69069;
       
   552         seed1 += 41;
       
   553         }
       
   554 
       
   555     test.Printf(_L("FirstSeed: 0x%08x\n"), ret);
       
   556     return ret;
       
   557     }
       
   558 
       
   559 TUint32 STestStress::Random()
       
   560     {
       
   561     iSeed *= 69069;
       
   562     iSeed += 41;
       
   563     return iSeed;
       
   564     }
       
   565 
       
   566 TInt RandomLength(TUint32 aRandom)
       
   567     {
       
   568     TUint32 ret = 0;
       
   569     
       
   570     if (TestHybridHeapFunc == ETstOnlySlab)
       
   571         {
       
   572         test(SlabThreshold != 0);
       
   573         ret = aRandom;
       
   574         TInt realSlabThreshold = SlabThreshold;
       
   575 #ifdef _DEBUG
       
   576         realSlabThreshold -= RHeap::EDebugHdrSize;
       
   577 #endif
       
   578         ret %= realSlabThreshold;
       
   579         }
       
   580     else if (TestHybridHeapFunc == ETstOnlyDl)
       
   581         {
       
   582         TUint8 x = (TUint8)aRandom;
       
   583         if (x & 0x80)
       
   584             {
       
   585             ret = x & 0x7f;
       
   586             }
       
   587         else
       
   588             {
       
   589             ret = (x & 0x7f) << 7;
       
   590             }
       
   591         }
       
   592     else if (TestHybridHeapFunc == ETstOnlyPaged)
       
   593         {
       
   594         ret = RandomPagedLength(aRandom);
       
   595         }
       
   596     else if (TestHybridHeapFunc == ETstHybrid)
       
   597         {
       
   598         TUint8 x = (TUint8)aRandom;
       
   599         if (x & 0x80)
       
   600             {
       
   601             ret = x & 0x7f;
       
   602             }
       
   603         else
       
   604             {
       
   605             if (x & 0x10)
       
   606                 {
       
   607                 ret = (x & 0x7f) << 7;
       
   608                 }
       
   609             else
       
   610                 {
       
   611                 ret = RandomPagedLength(aRandom);
       
   612                 }
       
   613             }
       
   614         }
       
   615     else
       
   616         {
       
   617         test(0);
       
   618         }
       
   619 
       
   620     return (TInt)ret;
       
   621     }
       
   622 
       
   623 TInt HeapStress(TAny* aPtr)
       
   624     {
       
   625     STestStress& stress = *(STestStress*)aPtr;
       
   626     RTestHeap* heap = (RTestHeap*)&User::Allocator();
       
   627     TUint8** cell;
       
   628     TInt* len;
       
   629 
       
   630     if (stress.iThreadIndex >= MAX_THREAD_COUNT)
       
   631         {
       
   632         test(0);
       
   633         }
       
   634     cell = &HeapStressCell[stress.iThreadIndex][0];
       
   635     len = &HeapStressLen[stress.iThreadIndex][0];
       
   636 
       
   637     Mem::FillZ(cell, sizeof(*cell)*CurrMaxCellCount);
       
   638     Mem::FillZ(len, sizeof(*len)*CurrMaxCellCount);
       
   639 
       
   640     RThread::Rendezvous(KErrNone);
       
   641     while (!stress.iStop)
       
   642         {
       
   643         // allocate all cells
       
   644         TInt i;
       
   645         for (i=0; i<CurrMaxCellCount; ++i)
       
   646             {
       
   647             if (!cell[i])
       
   648                 {
       
   649                 ++stress.iAllocs;
       
   650                 cell[i] = (TUint8*)heap->TestAlloc(RandomLength(stress.Random()));
       
   651                 if (cell[i])
       
   652                     len[i] = heap->AllocLen(cell[i]);
       
   653                 else
       
   654                     ++stress.iFailedAllocs;
       
   655                 }
       
   656             }
       
   657 
       
   658         // free some cells
       
   659         TInt n = (CurrMaxCellCount/4) + (stress.Random() & (CurrMaxCellCount/2-1));
       
   660         while (--n)
       
   661             {
       
   662             i = stress.Random() & (CurrMaxCellCount-1);
       
   663             if (cell[i])
       
   664                 {
       
   665                 test(heap->AllocLen(cell[i]) == len[i]);
       
   666                 heap->TestFree(cell[i]);
       
   667                 cell[i] = NULL;
       
   668                 len[i] = 0;
       
   669                 ++stress.iFrees;
       
   670                 }
       
   671             }
       
   672 
       
   673         // realloc some cells
       
   674         n = (CurrMaxCellCount/4) + (stress.Random() & (CurrMaxCellCount/2-1));
       
   675         while (--n)
       
   676             {
       
   677             TUint32 rn = stress.Random();
       
   678             i = (rn >> 8) & (CurrMaxCellCount-1);
       
   679             TInt new_len = RandomLength(rn);
       
   680             if (cell[i])
       
   681                 {
       
   682                 test(heap->AllocLen(cell[i]) == len[i]);
       
   683                 ++stress.iReAllocs;
       
   684                 TUint8* p = (TUint8*)heap->TestReAlloc(cell[i], new_len, rn >> 16);
       
   685                 if (p)
       
   686                     {
       
   687                     cell[i] = p;
       
   688                     len[i] = heap->AllocLen(p);
       
   689                     }
       
   690                 else
       
   691                     {
       
   692                     ++stress.iFailedReAllocs;
       
   693                     }
       
   694                 }
       
   695             }
       
   696                 
       
   697         // check the heap
       
   698         heap->Check();
       
   699         ++stress.iChecks;
       
   700         }
       
   701     
       
   702     return 0;
       
   703     }
       
   704 
       
   705 void PrintSummary(STestStress& aStress)
       
   706     {
       
   707     test.Printf(_L("Total Allocs    : %11d\n"), aStress.iAllocs);
       
   708     test.Printf(_L("Failed Allocs   : %11d\n"), aStress.iFailedAllocs);
       
   709     test.Printf(_L("Total Frees     : %11d\n"), aStress.iFrees);
       
   710     test.Printf(_L("Total ReAllocs  : %11d\n"), aStress.iReAllocs);
       
   711     test.Printf(_L("Failed ReAllocs : %11d\n"), aStress.iFailedReAllocs);
       
   712     test.Printf(_L("Heap checks     : %11d\n"), aStress.iChecks);
       
   713     }
       
   714     
       
   715 void CreateStressThread(STestStress& aStress)
       
   716     {
       
   717     RThread& thread = aStress.iThread;
       
   718     TInt err = thread.Create(KNullDesC(), &HeapStress, 0x2000, aStress.iAllocator, &aStress);
       
   719     test(err==KErrNone);
       
   720     thread.SetPriority(EPriorityLess);
       
   721     TRequestStatus status;
       
   722     thread.Rendezvous(status);
       
   723     test(status == KRequestPending);
       
   724     thread.Resume();
       
   725     User::WaitForRequest(status);
       
   726     test(status == KErrNone);
       
   727     test(thread.ExitType() == EExitPending);
       
   728     thread.SetPriority(EPriorityMuchLess);
       
   729     }
       
   730 
       
   731 void StopStressThread(STestStress& aStress)
       
   732     {
       
   733     RThread& thread = aStress.iThread;
       
   734     TRequestStatus status;
       
   735     thread.Logon(status);
       
   736     aStress.iStop = ETrue;
       
   737     User::WaitForRequest(status);
       
   738     const TDesC& exitCat = thread.ExitCategory();
       
   739     TInt exitReason = thread.ExitReason();
       
   740     TInt exitType = thread.ExitType();
       
   741     test.Printf(_L("Exit type %d,%d,%S\n"), exitType, exitReason, &exitCat);
       
   742     test(exitType == EExitKill);
       
   743     test(exitReason == KErrNone);
       
   744     test(status == KErrNone);
       
   745     PrintSummary(aStress);
       
   746     }
       
   747 
       
   748 void WaitForKey(STestStress* aStress1, STestStress* aStress2)
       
   749 {
       
   750     TRequestStatus keyStatus;
       
   751     CConsoleBase* console = test.Console();
       
   752     console->Read(keyStatus);
       
   753     
       
   754     for (;;)
       
   755         {
       
   756         User::WaitForRequest(keyStatus);
       
   757         if (keyStatus != KRequestPending)
       
   758             {
       
   759             test(keyStatus == KErrNone);
       
   760             if (console->KeyCode() == EKeyEscape)
       
   761                 {
       
   762                 test.Printf(_L("Forever test aborted by user\n"));
       
   763                 break;
       
   764                 }
       
   765             else if (console->KeyCode() == EKeySpace)
       
   766                 {
       
   767                 if (aStress1 != NULL)
       
   768                     {
       
   769                     PrintSummary(*aStress1);
       
   770                     }
       
   771                 if (aStress2 != NULL)
       
   772                     {
       
   773                     PrintSummary(*aStress2);
       
   774                     }
       
   775                 }
       
   776             }
       
   777         console->Read(keyStatus);
       
   778         }
       
   779 }
       
   780 
       
   781 TBool WaitForTimeoutOrKey(STestStress* aStress1, STestStress* aStress2)
       
   782 {
       
   783     TBool abortedByUser = EFalse;
       
   784     RTimer timer;
       
   785     TRequestStatus timerStatus;
       
   786     TInt err = timer.CreateLocal();
       
   787     test(err == KErrNone);
       
   788     timer.After(timerStatus, TestTimeAsSeconds*1000000);
       
   789     
       
   790     TRequestStatus keyStatus;
       
   791     CConsoleBase* console = test.Console();
       
   792     console->Read(keyStatus);
       
   793     
       
   794     for (;;)
       
   795         {
       
   796         User::WaitForRequest(keyStatus, timerStatus);
       
   797         if (keyStatus != KRequestPending)
       
   798             {
       
   799             test(keyStatus == KErrNone);
       
   800             if (console->KeyCode() == EKeyEscape)
       
   801                 {
       
   802                 abortedByUser = ETrue;
       
   803                 timer.Cancel();
       
   804                 test.Printf(_L("Forever test aborted by user\n"));
       
   805                 break;
       
   806                 }
       
   807             else if (console->KeyCode() == EKeySpace)
       
   808                 {
       
   809                 if (aStress1 != NULL)
       
   810                     {
       
   811                     PrintSummary(*aStress1);
       
   812                     }
       
   813                 if (aStress2 != NULL)
       
   814                     {
       
   815                     PrintSummary(*aStress2);
       
   816                     }
       
   817                 }
       
   818             console->Read(keyStatus);
       
   819             }
       
   820         if (timerStatus != KRequestPending)
       
   821             {
       
   822             if (timerStatus != KErrNone)
       
   823                 {
       
   824                 test(0);
       
   825                 }
       
   826             console->ReadCancel();
       
   827             break;
       
   828             }
       
   829         }
       
   830     timer.Close();
       
   831     return abortedByUser;
       
   832 }
       
   833     
       
   834 TBool DoStressTest1(RAllocator* aAllocator)
       
   835     {
       
   836     TBool abortedByUser = EFalse;
       
   837     
       
   838     RTestHeap* heap = (RTestHeap*)aAllocator;
       
   839     //test.Printf(_L("Test Stress 1: max=0x%x\n"),  heap->MaxLength());
       
   840     
       
   841     STestStress stress;
       
   842     Mem::FillZ(&stress, sizeof(STestStress));
       
   843     stress.iAllocator = aAllocator;
       
   844     stress.iThreadIndex = 0;
       
   845     if (TestType == ETestForeverAll)
       
   846         {
       
   847         stress.iSeed = FirstSeed(stress.iThreadIndex);
       
   848         }
       
   849     else
       
   850         {
       
   851         stress.iSeed = 0xb504f334;;
       
   852         }
       
   853     
       
   854     CreateStressThread(stress);
       
   855     
       
   856     if (TestType == ETestE32Test)
       
   857         {
       
   858         User::After(TestTimeAsSeconds*1000000);
       
   859         }
       
   860     else if (TestType == ETestForeverAll)
       
   861         {
       
   862         abortedByUser = WaitForTimeoutOrKey(&stress, NULL);
       
   863         }
       
   864     else if (TestType == ETestForeverOne)
       
   865         {
       
   866         WaitForKey(&stress, NULL);
       
   867         abortedByUser = ETrue;
       
   868         }
       
   869     else
       
   870         {
       
   871         test(0);
       
   872         }
       
   873     
       
   874     StopStressThread(stress);
       
   875     CLOSE_AND_WAIT(stress.iThread);
       
   876     heap->FullCheck();
       
   877     return abortedByUser;
       
   878     }
       
   879 
       
   880 TBool DoStressTest2(RAllocator* aAllocator)
       
   881     {
       
   882     TBool abortedByUser = EFalse;
       
   883     
       
   884     RTestHeap* heap = (RTestHeap*)aAllocator;
       
   885     //test.Printf(_L("Test Stress 2: max=0x%x\n"),  heap->MaxLength());    
       
   886     
       
   887     STestStress stress1;
       
   888     Mem::FillZ(&stress1, sizeof(STestStress));
       
   889     stress1.iAllocator = aAllocator;
       
   890     stress1.iThreadIndex = 0;
       
   891     
       
   892     STestStress stress2;
       
   893     Mem::FillZ(&stress2, sizeof(STestStress));
       
   894     stress2.iAllocator = aAllocator;
       
   895     stress2.iThreadIndex = 1;
       
   896     
       
   897     if (TestType == ETestForeverAll)
       
   898         {
       
   899         stress1.iSeed = FirstSeed(stress1.iThreadIndex);
       
   900         stress2.iSeed = FirstSeed(stress2.iThreadIndex);
       
   901         }
       
   902     else
       
   903         {
       
   904         stress1.iSeed = 0xb504f334;
       
   905         stress2.iSeed = 0xddb3d743;
       
   906         }
       
   907     CreateStressThread(stress1);
       
   908     CreateStressThread(stress2);
       
   909 
       
   910     if (TestType == ETestE32Test)
       
   911         {
       
   912         User::After(2*TestTimeAsSeconds*1000000);
       
   913         }
       
   914     else if (TestType == ETestForeverAll)
       
   915         {
       
   916         abortedByUser = WaitForTimeoutOrKey(&stress1, &stress2);
       
   917         }
       
   918     else if (TestType == ETestForeverOne)
       
   919         {
       
   920         WaitForKey(&stress1, &stress2);
       
   921         abortedByUser = ETrue;
       
   922         }
       
   923     else
       
   924         {
       
   925         test(0);
       
   926         }
       
   927     
       
   928     StopStressThread(stress1);
       
   929     StopStressThread(stress2);
       
   930     CLOSE_AND_WAIT(stress1.iThread);
       
   931     CLOSE_AND_WAIT(stress2.iThread);
       
   932     heap->FullCheck();
       
   933     return abortedByUser;
       
   934     }
       
   935 
       
   936 TBool StressTests(void)
       
   937     {
       
   938     TBool abortedByUser = EFalse;
       
   939     RHeap* heap = 0;
       
   940     
       
   941     for (;;)
       
   942         {
       
   943         if (TestType == ETestE32Test ||
       
   944             TestType == ETestForeverAll)
       
   945             {
       
   946             heap = CreateTestHeap(4);
       
   947             test(heap != NULL);
       
   948             test.Next(_L("one thread, align 4"));
       
   949             abortedByUser = DoStressTest1(heap);
       
   950             if (abortedByUser)
       
   951                 {
       
   952                 break;
       
   953                 }
       
   954             heap->Close();
       
   955             
       
   956             heap = CreateTestHeap(4);
       
   957             test.Next(_L("two threads, align 4"));
       
   958             abortedByUser = DoStressTest2(heap);
       
   959             if (abortedByUser)
       
   960                 {
       
   961                 break;
       
   962                 }
       
   963             heap->Close();
       
   964                 
       
   965             heap = CreateTestHeap(8);
       
   966             test(heap != NULL);
       
   967             test.Next(_L("one thread, align 8"));
       
   968             abortedByUser = DoStressTest1(heap);
       
   969             if (abortedByUser)
       
   970                 {
       
   971                 break;
       
   972                 }
       
   973             heap->Close();
       
   974 
       
   975             heap = CreateTestHeap(8);
       
   976             test.Next(_L("two threads, align 8"));
       
   977             abortedByUser = DoStressTest2(heap);
       
   978             }
       
   979         else if (TestType == ETestForeverOne)
       
   980             {
       
   981             heap = CreateTestHeap(4);
       
   982             test(heap != NULL);
       
   983             if (TestForeverMultiThreadTest)
       
   984                 {
       
   985                 test.Next(_L("two threads, align 4"));
       
   986                 abortedByUser = DoStressTest2(heap);
       
   987                 }
       
   988             else
       
   989                 {
       
   990                 test.Next(_L("one thread, align 4"));
       
   991                 abortedByUser = DoStressTest1(heap);
       
   992                 }
       
   993             }
       
   994         else
       
   995             {
       
   996             test(0);
       
   997             }
       
   998         break;
       
   999         }
       
  1000     heap->Close();
       
  1001     
       
  1002     return abortedByUser;
       
  1003     }           
       
  1004 
       
  1005         
       
  1006 void ForeverOneTest(void)
       
  1007     {
       
  1008     //--------- config parameters - begin
       
  1009     TestForeverMultiThreadTest = ETrue; // EFalse
       
  1010     TestHybridHeapFunc = ETstOnlySlab; // ETstOnlySlab // ETstOnlyDl // ETstOnlyPaged // ETstHybrid
       
  1011     //--------- config parameters - end
       
  1012 
       
  1013     if (TestHybridHeapFunc == ETstOnlySlab && !DlOnly)
       
  1014         {
       
  1015         // slab tests
       
  1016 #ifdef __WINS__
       
  1017         test.Next(_L("slab test 48M"));
       
  1018         CurrMaxCellCount = 0x100000; //0x10000; 0x100000
       
  1019         HeapMaxLength = 0x3000000; // 48M
       
  1020 #else
       
  1021         test.Next(_L("slab test 3M"));
       
  1022         CurrMaxCellCount = 0x10000; //0x10000; 0x100000
       
  1023         HeapMaxLength = 0x300000; // 3M
       
  1024 #endif          
       
  1025         StressTests();
       
  1026         }
       
  1027     else if (TestHybridHeapFunc == ETstOnlyDl)
       
  1028         {
       
  1029         // DL tests
       
  1030         test.Next(_L("DL test 32M"));
       
  1031         CurrMaxCellCount = 0x1000; //0x10000;
       
  1032         HeapMaxLength = 0x2000000; // 32M
       
  1033         StressTests();
       
  1034         }
       
  1035     else if (TestHybridHeapFunc == ETstOnlyPaged && !DlOnly)
       
  1036         {
       
  1037         // paged tests
       
  1038         test.Next(_L("paged test 64M"));
       
  1039         CurrMaxCellCount = 0x100; //0x10000;
       
  1040         HeapMaxLength = 0x4000000; // 64M
       
  1041         StressTests();
       
  1042         }
       
  1043     else if (TestHybridHeapFunc == ETstHybrid && !DlOnly)
       
  1044         {
       
  1045         // hybrid tests
       
  1046         test.Next(_L("hybrid test 64M"));
       
  1047         CurrMaxCellCount = 0x1000; //0x10000;
       
  1048         HeapMaxLength = 0x4000000; // 64M
       
  1049         StressTests();
       
  1050         }
       
  1051     else
       
  1052         {
       
  1053         test(0);
       
  1054         }
       
  1055     }
       
  1056     
       
  1057 void ForeverAllTests(void)
       
  1058     {
       
  1059     //--------- config parameters - begin
       
  1060     TInt basicTimeAsSeconds = 30; //10;
       
  1061     //--------- config parameters - end
       
  1062 
       
  1063     for (;;)
       
  1064         {
       
  1065         if (!DlOnly)
       
  1066             {
       
  1067             // slab tests
       
  1068             TestHybridHeapFunc = ETstOnlySlab;
       
  1069             TestTimeAsSeconds = basicTimeAsSeconds * 3;
       
  1070 #ifdef __WINS__
       
  1071             test.Next(_L("slab test 48M"));
       
  1072             CurrMaxCellCount = 0x100000; //0x10000; 0x100000
       
  1073             HeapMaxLength = 0x3000000; // 48M
       
  1074 #else
       
  1075             test.Next(_L("slab test 3M"));
       
  1076             CurrMaxCellCount = 0x10000; //0x10000; 0x100000
       
  1077             HeapMaxLength = 0x300000; // 3M
       
  1078 #endif          
       
  1079             if (StressTests())
       
  1080                 {
       
  1081                 break;
       
  1082                 }
       
  1083             }
       
  1084         
       
  1085         // DL tests
       
  1086         TestHybridHeapFunc = ETstOnlyDl;
       
  1087         TestTimeAsSeconds = basicTimeAsSeconds;
       
  1088         
       
  1089         test.Next(_L("DL test 32M"));
       
  1090         CurrMaxCellCount = 0x1000; //0x10000;
       
  1091         HeapMaxLength = 0x2000000; // 32M
       
  1092         if (StressTests())
       
  1093             {
       
  1094             break;
       
  1095             }
       
  1096         
       
  1097         test.Next(_L("DL test 16M"));
       
  1098         CurrMaxCellCount = 0x1000; //0x10000;
       
  1099         HeapMaxLength = 0x1000000; // 16M
       
  1100         if (StressTests())
       
  1101             {
       
  1102             break;
       
  1103             }
       
  1104         
       
  1105         if (!DlOnly)
       
  1106             {
       
  1107             // paged tests
       
  1108             TestHybridHeapFunc = ETstOnlyPaged;
       
  1109             TestTimeAsSeconds = basicTimeAsSeconds;
       
  1110             
       
  1111             test.Next(_L("paged test 64M"));
       
  1112             CurrMaxCellCount = 0x100; //0x10000;
       
  1113             HeapMaxLength = 0x4000000; // 64M
       
  1114             if (StressTests())
       
  1115                 {
       
  1116                 break;
       
  1117                 }
       
  1118             }
       
  1119         
       
  1120         if (!DlOnly)
       
  1121             {
       
  1122             // hybrid tests
       
  1123             TestHybridHeapFunc = ETstHybrid;
       
  1124             TestTimeAsSeconds = basicTimeAsSeconds * 2;
       
  1125             
       
  1126             test.Next(_L("hybrid test 64M"));
       
  1127             CurrMaxCellCount = 0x1000; //0x10000;
       
  1128             HeapMaxLength = 0x4000000; // 64M
       
  1129             if (StressTests())
       
  1130                 {
       
  1131                 break;
       
  1132                 }
       
  1133             }
       
  1134         }
       
  1135     }
       
  1136     
       
  1137 void TestUsedInE32Tests(void)
       
  1138     {
       
  1139     //--------- config parameters - begin
       
  1140     TInt basicTimeAsSeconds = 10;
       
  1141     //--------- config parameters - end
       
  1142 
       
  1143     if (!DlOnly)
       
  1144         {
       
  1145         // slab tests
       
  1146         TestHybridHeapFunc = ETstOnlySlab;
       
  1147         TestTimeAsSeconds = basicTimeAsSeconds * 3;
       
  1148 #ifdef __WINS__
       
  1149         test.Next(_L("slab test 48M"));
       
  1150         CurrMaxCellCount = 0x100000; //0x10000; 0x100000
       
  1151         HeapMaxLength = 0x3000000; // 48M
       
  1152 #else
       
  1153         test.Next(_L("slab test 3M"));
       
  1154         CurrMaxCellCount = 0x10000; //0x10000; 0x100000
       
  1155         HeapMaxLength = 0x300000; // 3M
       
  1156 #endif          
       
  1157         StressTests();
       
  1158         }
       
  1159     
       
  1160     // DL tests
       
  1161     TestHybridHeapFunc = ETstOnlyDl;
       
  1162     TestTimeAsSeconds = basicTimeAsSeconds;
       
  1163     
       
  1164     test.Next(_L("DL test 32M"));
       
  1165     CurrMaxCellCount = 0x1000; //0x10000;
       
  1166     HeapMaxLength = 0x2000000; // 32M
       
  1167     StressTests();
       
  1168     
       
  1169     test.Next(_L("DL test 16M"));
       
  1170     CurrMaxCellCount = 0x1000; //0x10000;
       
  1171     HeapMaxLength = 0x1000000; // 16M
       
  1172     StressTests();
       
  1173     
       
  1174     if (!DlOnly)
       
  1175         {
       
  1176         // paged tests
       
  1177         TestHybridHeapFunc = ETstOnlyPaged;
       
  1178         TestTimeAsSeconds = basicTimeAsSeconds;
       
  1179         
       
  1180         test.Next(_L("paged test 64M"));
       
  1181         CurrMaxCellCount = 0x100; //0x10000;
       
  1182         HeapMaxLength = 0x4000000; // 64M
       
  1183         StressTests();
       
  1184         }
       
  1185 
       
  1186     if (!DlOnly)
       
  1187         {
       
  1188         // hybrid tests
       
  1189         TestHybridHeapFunc = ETstHybrid;
       
  1190         TestTimeAsSeconds = basicTimeAsSeconds * 2;
       
  1191         
       
  1192         test.Next(_L("hybrid test 64M"));
       
  1193         CurrMaxCellCount = 0x1000; //0x10000;
       
  1194         HeapMaxLength = 0x4000000; // 64M
       
  1195         StressTests();
       
  1196         }
       
  1197     }
       
  1198     
       
  1199 TInt E32Main()
       
  1200     {
       
  1201     test.Title();
       
  1202     __KHEAP_MARK;
       
  1203     test.Start(_L("Testing heaps"));
       
  1204 
       
  1205     TInt err = UserHal::TickPeriod(TickPeriod);
       
  1206     test(err == KErrNone);
       
  1207 
       
  1208     DlOnly = IsDlOnly();
       
  1209     
       
  1210     TestType = ETestE32Test; //ETestE32Test // ETestForeverOne // ETestForeverAll
       
  1211     // see other config parameters: TestUsedInE32Tests()/ForeverOneTest()/ForeverAllTests()
       
  1212    
       
  1213     if (TestType == ETestE32Test)
       
  1214         {
       
  1215         TestUsedInE32Tests();
       
  1216         }
       
  1217     else if (TestType == ETestForeverOne)
       
  1218         {
       
  1219         ForeverOneTest();
       
  1220         }
       
  1221     else if (TestType == ETestForeverAll)
       
  1222         {
       
  1223         ForeverAllTests();
       
  1224         }
       
  1225     else
       
  1226         {
       
  1227         test(0);
       
  1228         }
       
  1229     
       
  1230     test.End();
       
  1231     __KHEAP_MARKEND;
       
  1232     return 0;
       
  1233     }