kerneltest/e32test/mmu/t_ramall.cpp
changeset 176 af6ec97d9189
parent 132 e4a7b1cbe40c
--- 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 <e32test.h>
 #include <e32uid.h>
+#include <hal.h>
 #include <e32hal.h>
 #include <dptest.h>
 #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);