diff -r 5af6c74cd793 -r af6ec97d9189 kerneltest/e32test/mmu/t_ramall.cpp --- a/kerneltest/e32test/mmu/t_ramall.cpp Wed Jun 23 11:59:44 2010 +0100 +++ b/kerneltest/e32test/mmu/t_ramall.cpp Wed Jun 23 12:52:28 2010 +0100 @@ -19,11 +19,13 @@ #include #include +#include #include #include #include "d_shadow.h" #include "mmudetect.h" #include "freeram.h" +#include "d_gobble.h" LOCAL_D RTest test(_L("T_RAMALL")); @@ -32,7 +34,7 @@ TInt PageSize; TInt PageShift; RShadow Shadow; -TInt InitFreeRam; +TInt TotalRam; RChunk Chunk; TUint ChunkCommitEnd; RThread TouchThread; @@ -46,6 +48,30 @@ TUint OrigMinCacheSize; TUint OrigMaxCacheSize; +// +// Random number generation +// + +TUint32 RandomSeed; + +TUint32 Random() + { + RandomSeed = RandomSeed*69069+1; + return RandomSeed; + } + +TUint32 Random(TUint32 aRange) + { + return (TUint32)((TUint64(Random())*TUint64(aRange))>>32); + } + +void RandomInit(TUint32 aSeed) + { + RandomSeed = aSeed+(aSeed<<8)+(aSeed<<16)+(aSeed<<24); + Random(); + Random(); + } + TInt AllocPhysicalRam(TUint32& aAddr, TInt aSize, TInt aAlign) { return Shadow.AllocPhysicalRam(aAddr,aSize,aAlign); @@ -143,7 +169,7 @@ TInt FillPhysicalRam(TAny* aArgs) { - SPhysAllocData& allocData = *((SPhysAllocData*)aArgs); + SPhysAllocData allocData = *((SPhysAllocData*)aArgs); TUint maxAllocs = FreeRam() / allocData.iSize; TUint32* physAddrs = new TUint32[maxAllocs + 1]; if (!physAddrs) @@ -165,10 +191,11 @@ RDebug::Printf("Error alignment phys addr 0x%08x", *(pa - 1)); break; } - if (allocData.iCheckFreeRam && freeRam - allocData.iSize != (TUint)FreeRam()) + TUint newFreeRam = FreeRam(); + if (allocData.iCheckFreeRam && freeRam - allocData.iSize != newFreeRam) { r = KErrGeneral; - RDebug::Printf("Error in free ram 0x%08x orig 0x%08x", FreeRam(), freeRam); + RDebug::Printf("Error in free ram 0x%08x orig 0x%08x", newFreeRam, freeRam); break; } } @@ -187,10 +214,11 @@ r = KErrOverflow; RDebug::Printf("Error able to allocate too many pages"); } - if (allocData.iCheckFreeRam && initialFreeRam != (TUint)FreeRam()) + TUint finalFreeRam = FreeRam(); + if (allocData.iCheckFreeRam && initialFreeRam != finalFreeRam) { r = KErrGeneral; - RDebug::Printf("Error in free ram 0x%08x initial 0x%08x", FreeRam(), initialFreeRam); + RDebug::Printf("Error in free ram 0x%08x initial 0x%08x", finalFreeRam, initialFreeRam); } delete[] physAddrs; if (r != KErrNone && r != KErrNoMemory) @@ -219,16 +247,18 @@ TUint i = 0; for (; i < aNumThreads; i++) {// Need enough heap to store addr of every possible allocation + 1. - TUint requiredHeapMax = Max(PageSize, ((InitFreeRam / aSize) / sizeof(TUint32)) + sizeof(TUint32)); + TUint requiredHeapMax = Max(PageSize, ((TotalRam / aSize) * sizeof(TUint32)) + sizeof(TUint32)); TInt r = threads[i].Create(KNullDesC, FillPhysicalRam, KDefaultStackSize, PageSize, requiredHeapMax, (TAny*)&allocData); - test_KErrNone(r); + if (r != KErrNone) + break; threads[i].Logon(status[i]); } - for (i = 0; i < aNumThreads; i++) + TUint totalThreads = i; + for (i = 0; i < totalThreads; i++) { threads[i].Resume(); } - for (i = 0; i < aNumThreads; i++) + for (i = 0; i < totalThreads; i++) { User::WaitForRequest(status[i]); test_Equal(EExitKill, threads[i].ExitType()); @@ -249,25 +279,33 @@ TInt TouchMemory(TAny*) { + RThread::Rendezvous(KErrNone); // Signal that this thread has started running. + RandomInit(TouchData.iSize); while (!TouchDataStop) { TUint8* p = Chunk.Base(); TUint8* pEnd = p + ChunkCommitEnd; TUint8* fragPEnd = p + TouchData.iFrequency; - for (TUint8* fragP = p + TouchData.iSize; fragPEnd < pEnd;) + for (TUint8* fragP = p + TouchData.iSize; fragPEnd < pEnd && !TouchDataStop;) { TUint8* data = fragP; - for (; data < fragPEnd; data += PageSize) + for (; data < fragPEnd && !TouchDataStop; data += PageSize) { *data = (TUint8)(data - fragP); + TUint random = Random(); + if (random & 0x8484) + User::After(random & 0xFFFF); } - for (data = fragP; data < fragPEnd; data += PageSize) + for (data = fragP; data < fragPEnd && !TouchDataStop; data += PageSize) { if (*data != (TUint8)(data - fragP)) { RDebug::Printf("Error unexpected data 0x%x read from 0x%08x", *data, data); return KErrGeneral; } + TUint random = Random(); + if (random & 0x8484) + User::After(random & 0xFFFF); } fragP = fragPEnd + TouchData.iSize; fragPEnd += TouchData.iFrequency; @@ -302,17 +340,14 @@ { test_KErrNone(Chunk.Decommit(offset, FragData.iSize)); } - if (!FragData.iFragThread) - test_Equal(FreeRam(), freeBlocks * FragData.iSize); if (FragData.iDiscard && CacheSizeAdjustable && !FragThreadStop) { TUint minCacheSize = FreeRam(); TUint maxCacheSize = minCacheSize; - TUint currentCacheSize; - test_KErrNone(DPTest::CacheSize(OrigMinCacheSize, OrigMaxCacheSize, currentCacheSize)); - test_KErrNone(DPTest::SetCacheSize(minCacheSize, maxCacheSize)); - test_KErrNone(DPTest::SetCacheSize(OrigMinCacheSize, maxCacheSize)); + DPTest::SetCacheSize(minCacheSize, maxCacheSize); + if (OrigMinCacheSize <= maxCacheSize) + DPTest::SetCacheSize(OrigMinCacheSize, maxCacheSize); } } @@ -320,13 +355,14 @@ void UnfragmentMemoryFunc() { if (FragData.iDiscard && CacheSizeAdjustable) - test_KErrNone(DPTest::SetCacheSize(OrigMinCacheSize, OrigMaxCacheSize)); + DPTest::SetCacheSize(OrigMinCacheSize, OrigMaxCacheSize); Chunk.Decommit(0, Chunk.MaxSize()); } TInt FragmentMemoryThreadFunc(TAny*) { + RThread::Rendezvous(KErrNone); // Signal that this thread has started running. while (!FragThreadStop) { FragmentMemoryFunc(); @@ -346,17 +382,22 @@ FragData.iFragThread = aFragThread; TChunkCreateInfo chunkInfo; - chunkInfo.SetDisconnected(0, 0, FreeRam()); + chunkInfo.SetDisconnected(0, 0, TotalRam); chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged); + chunkInfo.SetClearByte(0x19); test_KErrNone(Chunk.Create(chunkInfo)); if (aFragThread) { - TInt r = FragThread.Create(KNullDesC, FragmentMemoryThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); + TInt r = FragThread.Create(_L("FragThread"), FragmentMemoryThreadFunc, KDefaultStackSize, PageSize, PageSize, NULL); test_KErrNone(r); FragThread.Logon(FragStatus); FragThreadStop = EFalse; + TRequestStatus threadInitialised; + FragThread.Rendezvous(threadInitialised); FragThread.Resume(); + User::WaitForRequest(threadInitialised); + test_KErrNone(threadInitialised.Int()); } else { @@ -366,11 +407,15 @@ { TouchData.iSize = aSize; TouchData.iFrequency = aFrequency; - TInt r = TouchThread.Create(KNullDesC, TouchMemory, KDefaultStackSize, PageSize, PageSize, NULL); + TInt r = TouchThread.Create(_L("TouchThread"), TouchMemory, KDefaultStackSize, PageSize, PageSize, NULL); test_KErrNone(r); TouchThread.Logon(TouchStatus); TouchDataStop = EFalse; + TRequestStatus threadInitialised; + TouchThread.Rendezvous(threadInitialised); TouchThread.Resume(); + User::WaitForRequest(threadInitialised); + test_KErrNone(threadInitialised.Int()); } } @@ -396,6 +441,8 @@ } else UnfragmentMemoryFunc(); + if (CacheSizeAdjustable) + test_KErrNone(DPTest::SetCacheSize(OrigMinCacheSize, OrigMaxCacheSize)); CLOSE_AND_WAIT(Chunk); } @@ -407,11 +454,12 @@ FragmentMemory(aFragSize, aFragFreq, aDiscard, aTouchMemory, EFalse); SPhysAllocData allocData; // Only check free all ram could be allocated in manual tests as fixed pages may be fragmented. - allocData.iCheckMaxAllocs = (ManualTest && !aTouchMemory && !aAllocAlign)? ETrue : EFalse; + allocData.iCheckMaxAllocs = (ManualTest && !aTouchMemory && !aAllocAlign); allocData.iCheckFreeRam = ETrue; allocData.iSize = aAllocSize; allocData.iAlign = aAllocAlign; - FillPhysicalRam(&allocData); + TInt r = FillPhysicalRam(&allocData); + test_Value(r, r >= 0); UnfragmentMemory(aDiscard, aTouchMemory, EFalse); } @@ -492,14 +540,17 @@ ManualTest = cmdLine.Find(KManual) != KErrNotFound; } - // Turn off lazy dll unloading so the free ram checking isn't affected. + // Turn off lazy dll unloading and ensure any supervisor clean up has completed + // so the free ram checking isn't affected. RLoader l; test(l.Connect()==KErrNone); test(l.CancelLazyDllUnload()==KErrNone); l.Close(); + UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); - InitFreeRam=FreeRam(); - test.Printf(_L("Free RAM=%08x, Page size=%x, Page shift=%d\n"),InitFreeRam,PageSize,PageShift); + test_KErrNone(HAL::Get(HAL::EMemoryRAM, TotalRam)); + + test.Printf(_L("Free RAM=%08x, Page size=%x, Page shift=%d\n"),FreeRam(),PageSize,PageShift); test.Next(_L("Open test LDD")); r=Shadow.Open(); @@ -513,6 +564,18 @@ if (memodel >= EMemModelTypeFlexible) { + // To stop these tests taking too long leave only 8MB of RAM free. + const TUint KFreePages = 2048; + test.Next(_L("Load gobbler LDD")); + TInt r = User::LoadLogicalDevice(KGobblerLddFileName); + test_Value(r, r == KErrNone || r == KErrAlreadyExists); + RGobbler gobbler; + r = gobbler.Open(); + test_KErrNone(r); + TUint32 taken = gobbler.GobbleRAM(KFreePages * PageSize); + test.Printf(_L("Gobbled: %dK\n"), taken/1024); + test.Printf(_L("Free RAM 0x%08X bytes\n"),FreeRam()); + test.Next(_L("TestFragmentedAllocation")); TestFragmentedAllocation(); @@ -555,9 +618,15 @@ FragmentMemory(PageSize * 32, PageSize * 64, ETrue, EFalse, ETrue); TestMultipleContiguousAllocations(20, PageSize * 1024, PageShift + 10); UnfragmentMemory(ETrue, EFalse, ETrue); + + gobbler.Close(); + r = User::FreeLogicalDevice(KGobblerLddFileName); + test_KErrNone(r); } Shadow.Close(); + r = User::FreeLogicalDevice(KLddFileName); + test_KErrNone(r); test.Printf(_L("Free RAM=%08x at end of test\n"),FreeRam()); test.End(); return(KErrNone);