os/kernelhwsrv/kerneltest/f32test/demandpaging/t_wdpstress.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-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 // f32test\demandpaging\t_wdpstress.cpp
    15 // Data Paging Stress Tests
    16 // Common command lines:
    17 // t_wdpstress lowmem
    18 // debug - switch on debugging information
    19 // silent - no output to the screen or serial port
    20 // single - run the tests in a single thread
    21 // multiple <numThreads> - run the tests in multiple threads where <numThreads> (max 50 simultaneous threads)
    22 // interleave - force thread interleaving
    23 // prio - each thread reschedules in between each function call, causes lots of context changes
    24 // media - perform media access during the tests, very stressful
    25 // lowmem - low memory tests
    26 // stack - perform autotest only with stack paging tests
    27 // chunk - perform autotest only with chunk paging tests 			
    28 // commit - perform autotest only with committing and decommitting paging tests 
    29 // ipc - perform autotest only with ipc pinning tests 			
    30 // all - perform autotest with all paging tests(ipc, stack, chunk and commit)
    31 // badserver - perform ipc pinning tests with dead server
    32 // iters <count> - the number of times to loop 
    33 // 
    34 //
    35 
    36 //! @SYMTestCaseID			KBASE-T_WDPSTRESS-xxx
    37 //! @SYMTestType			UT
    38 //! @SYMPREQ				PREQ1954
    39 //! @SYMTestCaseDesc		Writable Data Paging Stress Tests
    40 //! @SYMTestActions			
    41 //! @SYMTestExpectedResults All tests should pass.
    42 //! @SYMTestPriority        High
    43 //! @SYMTestStatus          Implemented
    44 //----------------------------------------------------------------------------------------------
    45 //
    46 #define __E32TEST_EXTENSION__
    47 #include <e32test.h>
    48 #include <e32ver.h>
    49 RTest test(_L("T_WDPSTRESS"));
    50 
    51 #include <e32rom.h>
    52 #include <u32hal.h>
    53 #include <f32file.h>
    54 #include <e32svr.h>
    55 #include <e32hal.h>
    56 #include <f32dbg.h>
    57 #include <e32msgqueue.h>
    58 #include <e32math.h>
    59 #include <dptest.h>
    60 #include <hal.h>
    61 #include "testdefs.h"
    62 
    63 #ifdef __X86__
    64 #define TEST_ON_UNPAGED
    65 #endif
    66 
    67 #include "t_pagestress.h"
    68 
    69 TBool   	TestDebug					= EFalse;
    70 TBool		TestSilent					= EFalse;
    71 TBool		TestExit					= EFalse;
    72 
    73 
    74 TInt		gPerformTestLoop			= 10;					// Number of times to perform test on a thread
    75 const TUint KMaxTestThreads				= 20;					// The maximum number of threads allowed to run simultaniously
    76 TInt		gNumTestThreads				= KMaxTestThreads;		// The number of threads to run simultaneously
    77 
    78 #define TEST_INTERLEAVE_PRIO			EPriorityMore
    79 
    80 TBool		TestWeAreTheTestBase		= EFalse;
    81 
    82 #define TEST_NONE		0x0
    83 #define TEST_IPC		0x1
    84 #define TEST_STACK		0x2
    85 #define TEST_CHUNK		0x4
    86 #define TEST_COMMIT		0x8
    87 #define TEST_ALL		(TEST_COMMIT | TEST_CHUNK | TEST_STACK | TEST_IPC)
    88 
    89 TUint32		gSetTests					= TEST_ALL;
    90 TUint32		gTestWhichTests				= gSetTests;
    91 TBuf<32>	gTestNameBuffer;
    92 TBool		gTestPrioChange				= EFalse;				
    93 TBool		gTestStopMedia				= EFalse;
    94 TBool		gTestMediaAccess			= EFalse;
    95 TBool		gTestInterleave				= EFalse;
    96 TBool		gTestBadServer				= EFalse;
    97 
    98 #define TEST_LM_NUM_FREE	0
    99 #define TEST_LM_BLOCKSIZE	1
   100 #define TEST_LM_BLOCKS_FREE	4
   101 
   102 RPageStressTestLdd Ldd;
   103 RSemaphore	TestMultiSem;
   104 RMsgQueue<TBuf <64> >	TestMsgQueue;
   105 
   106 TBool		gIsDemandPaged			= ETrue;
   107 TBool		gTestRunning				= EFalse;				// To control when to stop flushing
   108 TBool		gMaxChunksReached			= EFalse;				// On moving memory model, the number of chunks per process is capped
   109 
   110 TInt		gPageSize;											// The number of bytes per page
   111 TUint		gPageShift;
   112 TUint		gChunksAllocd				= 0;					// The total number of chunks that have been allocated
   113 TUint		gMaxChunks					= 0;					// The max amount of chunks after which KErrOverflow will be returned
   114 RHeap*		gThreadHeap					= NULL;					
   115 RHeap*		gStackHeap					= NULL;
   116 
   117 TInt		gTestType					= -1;					// The type of test that is to be performed
   118 
   119 #define TEST_NEXT(__args) \
   120 	if (!TestSilent)\
   121 		test.Next __args;
   122 
   123 #define RDBGD_PRINT(__args)\
   124 	if (TestDebug)\
   125 	RDebug::Printf __args ;\
   126 
   127 #define RDBGS_PRINT(__args)\
   128 	if (!TestSilent)\
   129 	RDebug::Printf __args ;\
   130 
   131 #define DEBUG_PRINT(__args)\
   132 if (!TestSilent)\
   133 	{\
   134 	if (aTestArguments.iMsgQueue && aTestArguments.iBuffer && aTestArguments.iTheSem)\
   135 		{\
   136 		aTestArguments.iBuffer->Zero();\
   137 		aTestArguments.iBuffer->Format __args ;\
   138 		aTestArguments.iTheSem->Wait();\
   139 		aTestArguments.iMsgQueue->SendBlocking(*aTestArguments.iBuffer);\
   140 		aTestArguments.iTheSem->Signal();\
   141 		}\
   142 	else\
   143 		{\
   144 		test.Printf __args ;\
   145 		}\
   146 	}
   147 
   148 #define RUNTEST(__test, __error)\
   149 	if (!TestSilent)\
   150 		test(__test == __error);\
   151 	else\
   152 		__test;
   153 
   154 #define RUNTEST1(__test)\
   155 	if (!TestSilent)\
   156 		test(__test);
   157 
   158 #define DEBUG_PRINT1(__args)\
   159 if (TestDebug)\
   160 	{\
   161 	DEBUG_PRINT(__args)\
   162 	}
   163 
   164 #define DOTEST(__operation, __condition)\
   165 	if (aLowMem) \
   166 		{\
   167 		__operation;\
   168 		while (!__condition)\
   169 			{\
   170 			Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
   171 			__operation;\
   172 			}\
   173 		RUNTEST1(__condition);\
   174 		}\
   175 	else\
   176 		{\
   177 		__operation;\
   178 		RUNTEST1(__condition);\
   179 		}
   180 
   181 #define DOTEST1(__operation, __condition)\
   182 	if (aTestArguments.iLowMem) \
   183 		{\
   184 		__operation;\
   185 		while (!__condition)\
   186 			{\
   187 			Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
   188 			__operation;\
   189 			}\
   190 		RUNTEST1(__condition);\
   191 		}\
   192 	else\
   193 		{\
   194 		__operation;\
   195 		RUNTEST1(__condition);\
   196 		}
   197 
   198 struct SThreadExitResults
   199 	{
   200 	TInt					iExitType;
   201 	TInt					iExitReason;
   202 	};
   203 SThreadExitResults* gResultsArray;
   204 const TInt KExitTypeReset = -1;
   205 
   206 struct SPerformTestArgs
   207 	{
   208 	TInt					iThreadIndex;
   209 	RMsgQueue<TBuf <64> >	*iMsgQueue; 
   210 	TBuf<64>				*iBuffer;
   211 	RSemaphore				*iTheSem;
   212 	TBool					iLowMem;
   213 	TInt					iTestType;
   214 	};
   215 
   216 
   217 TInt DoTest(TInt gTestType, TBool aLowMem = EFalse);
   218 enum
   219 	{
   220 	ETestSingle, 
   221 	ETestMultiple,
   222 	ETestMedia,
   223 	ETestLowMem,
   224 	ETestInterleave,
   225 	ETestCommit, 
   226 	ETestTypes,
   227 	// This is at the moment manual
   228 	ETestBadServer, 
   229 	ETestTypeEnd, 
   230 	};
   231 
   232 TInt FreeRam()
   233 	{
   234 	// wait for any async cleanup in the supervisor to finish first...
   235 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
   236 
   237 	TMemoryInfoV1Buf meminfo;
   238 	TInt r = UserHal::MemoryInfo(meminfo);
   239 	test_KErrNone(r);
   240 	return meminfo().iFreeRamInBytes;
   241 	}
   242 
   243 const TUint KStackSize = 20 * 4096;
   244 TUint stackLimit = 150;//*** NEED TO WORK OUT HOW MUCH STACK WE HAVE***
   245 
   246 /**
   247 Recursive function
   248 */
   249 void CallRecFunc(TUint aNum, TInt aThreadIndex)
   250 	{
   251 	RDBGD_PRINT(("ThreadId %d CallRecFunc, aNum = %d\n", aThreadIndex, aNum));
   252 	if (aNum >= stackLimit)
   253 		{// To avoid a stack overflow
   254 		return;
   255 		}
   256 	else
   257 		{
   258 		CallRecFunc(++aNum, aThreadIndex);
   259 		User::After(0);
   260 		}
   261 	RDBGD_PRINT(("ThreadId %d CRF(%d)Returning...", aThreadIndex, aNum));
   262 	return;
   263 	}
   264 
   265 /**
   266 Thread that calls a recursive function
   267 */
   268 TInt ThreadFunc(TAny* aThreadIndex)
   269 	{
   270 	for (TUint i=0; i<1; i++)
   271 		{
   272 		CallRecFunc(0, (TInt)aThreadIndex);
   273 		}
   274 	RDBGD_PRINT(("ThreadId %d ThreadFunc Returning...", (TInt)aThreadIndex));
   275 	return KErrNone;
   276 	}
   277 
   278 /**
   279 Thread continuously flushes the paging cache
   280 */
   281 TInt FlushFunc(TAny* /*aPtr*/)
   282 	{
   283 	RThread().SetPriority(EPriorityMore);
   284 	while(gTestRunning)
   285 		{
   286 		DPTest::FlushCache();	
   287 		User::After((Math::Random()&0xfff)*10);
   288 		}
   289 	return KErrNone;
   290 	}
   291 
   292 
   293 //
   294 // TestStackPaging
   295 //
   296 // Create a paged thread which calls a recursive function.
   297 // Calls to function will be placed on the stack, which is data paged
   298 //
   299 
   300 TInt TestStackPaging(SPerformTestArgs& aTestArguments)
   301 	{
   302 	RDBGD_PRINT(("Creating test thread"));
   303 	TBuf<16> runThreadName;
   304 	runThreadName = _L("");
   305 	TThreadCreateInfo threadCreateInfo(runThreadName, ThreadFunc, KStackSize, (TAny*) aTestArguments.iThreadIndex);
   306 	threadCreateInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
   307 	//threadCreateInfo.SetUseHeap(NULL);
   308 	threadCreateInfo.SetPaging(TThreadCreateInfo::EPaged);
   309 
   310 	RThread testThread;
   311 	TInt r;
   312 	for(;;)
   313 		{
   314 		r = testThread.Create(threadCreateInfo);
   315 		if(r != KErrNoMemory)
   316 			break;
   317 		if(!aTestArguments.iLowMem)
   318 			break;
   319 		if(Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE) != KErrNone)
   320 			break;
   321 		RDBGD_PRINT(("TestStackPaging released some RAM\n"));
   322 		}
   323 
   324 	RDBGD_PRINT(("TID(%d) TestStackPaging create r = %d freeRam = %d\n", aTestArguments.iThreadIndex, r, FreeRam()));
   325 	if (r != KErrNone)
   326 		return r;
   327 
   328 	TRequestStatus threadStatus;
   329 	testThread.Logon(threadStatus);
   330 	
   331 	RDBGD_PRINT(("resuming test thread"));
   332 	testThread.Resume();
   333 	
   334 	RDBGD_PRINT(("waiting for threadstatus"));
   335 	User::WaitForRequest(threadStatus);
   336 	
   337 	RDBGD_PRINT(("Killing threads\n"));
   338 	testThread.Close();
   339 
   340 	return KErrNone;
   341 	}
   342 
   343 //--------------------------Server Pinning stuff-----------------------------------------------------
   344 _LIT(KTestServer,"CTestServer");
   345 const TUint KSemServer = 0;
   346 
   347 class CTestServer : public CServer2
   348 	{
   349 public:
   350 	CTestServer(TInt aPriority);
   351 protected:
   352 	//override the pure virtual functions:
   353 	virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
   354 	};
   355 
   356 
   357 class CTestSession : public CSession2
   358 	{
   359 public:
   360 	enum TTestMode
   361 		{
   362 		EStop,
   363 		ERead,
   364 		EWrite,
   365 		EReadWrite,
   366 		};
   367 //Override pure virtual
   368 	IMPORT_C virtual void ServiceL(const RMessage2& aMessage);
   369 private:
   370 	TInt ReadWrite(const RMessage2& aMessage, TBool aRead, TBool aWrite);
   371 	TBool iClientDied;
   372 	};
   373 
   374 
   375 class CMyActiveScheduler : public CActiveScheduler
   376 	{
   377 public:
   378 	virtual void Error(TInt anError) const; //override pure virtual error function
   379 	};
   380 
   381 
   382 class RSession : public RSessionBase
   383 	{
   384 public:
   385 	TInt PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr)
   386 		{
   387 		return (SendReceive(aFunction, aPtr));
   388 		}
   389 	TInt PublicCreateSession(const TDesC& aServer,TInt aMessageSlots)
   390 		{
   391 		return (CreateSession(aServer,User::Version(),aMessageSlots));
   392 		}
   393 	};
   394 
   395 struct SServerArgs
   396 	{
   397 	TBool iBadServer;
   398 	RSemaphore iSemArray;
   399 	};
   400 
   401 SServerArgs gServerArgsArray[KMaxTestThreads];
   402 
   403 CTestServer::CTestServer(TInt aPriority)
   404 //
   405 // Constructor - sets name
   406 //
   407 	: CServer2(aPriority)
   408 	{}
   409 
   410 CSession2* CTestServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
   411 //
   412 // Virtual fn - checks version supported and creates a CTestSession
   413 //
   414 	{
   415 	TVersion version(KE32MajorVersionNumber,KE32MinorVersionNumber,KE32BuildVersionNumber);
   416 	if (User::QueryVersionSupported(version,aVersion)==EFalse)
   417 		User::Leave(KErrNotSupported);
   418 	CTestSession* newCTestSession = new CTestSession;
   419 	if (newCTestSession==NULL)
   420 		User::Panic(_L("NewSessionL failure"), KErrNoMemory);
   421 	return(newCTestSession);
   422 	}
   423 
   424 TInt CTestSession::ReadWrite(const RMessage2& aMessage, TBool aRead, TBool aWrite)
   425 	{
   426 	TInt r = KErrNone;
   427 	for (TUint argIndex = 0; argIndex < 4; argIndex++)
   428 		{
   429 		// Get the length of the descriptor and verify it is as expected.
   430 		TInt length = aMessage.GetDesLength(argIndex);
   431 		if (length < KErrNone)
   432 			{
   433 			RDebug::Printf("  Error getting descriptor length %d", length);
   434 			return length;
   435 			}
   436 
   437 		
   438 		if (aRead)
   439 			{
   440 			// Now read the descriptor
   441 			HBufC8* des = HBufC8::New(length);
   442 			if (!des)
   443 				return KErrNoMemory;
   444 			TPtr8 desPtr = des->Des();
   445 			r = aMessage.Read(argIndex, desPtr);
   446 			if (r != KErrNone)
   447 				{
   448 				delete des;
   449 				return r;
   450 				}
   451 			//TODO: Verify the descriptor
   452 			delete des;
   453 			}
   454 
   455 		if (aWrite)
   456 			{
   457 			// Now write to the maximum length of the descriptor.
   458 			TInt max = length;
   459 			HBufC8* argTmp = HBufC8::New(max);
   460 			if (!argTmp)
   461 				return KErrNoMemory;
   462 
   463 			TPtr8 argPtr = argTmp->Des();
   464 			argPtr.SetLength(max);
   465 			for (TInt i = 0; i < max; i++)
   466 				argPtr[i] = (TUint8)argIndex;
   467 			r = aMessage.Write(argIndex, argPtr);
   468 			delete argTmp;
   469 			if (r != KErrNone)
   470 				return r;
   471 			}
   472 		}
   473 
   474 	return KErrNone;
   475 	}
   476 
   477 
   478 void CTestSession::ServiceL(const RMessage2& aMessage)
   479 //
   480 // Virtual message-handler
   481 //
   482 	{
   483 	TInt r = KErrNone;
   484 	iClientDied = EFalse;
   485 	switch (aMessage.Function())
   486 		{
   487 		case EStop:
   488 			RDBGD_PRINT(("Stopping server"));
   489 			CActiveScheduler::Stop();
   490 			break;
   491 
   492 		case ERead:
   493 			r = ReadWrite(aMessage, ETrue, EFalse);
   494 			break;
   495 		case EWrite:
   496 			r = ReadWrite(aMessage, EFalse, ETrue);
   497 			break;
   498 		case EReadWrite:
   499 			r = ReadWrite(aMessage, ETrue, ETrue);
   500 			break;
   501 	
   502 		default:
   503 			r = KErrNotSupported;
   504 
   505 		}
   506  	aMessage.Complete(r);
   507 
   508 	// If descriptors aren't as expected then panic so the test will fail.
   509 	if (r != KErrNone)
   510 		User::Panic(_L("ServiceL failure"), r);
   511 	}
   512 
   513 // CTestSession funtions
   514 
   515 void CMyActiveScheduler::Error(TInt anError) const
   516 //
   517 // Virtual error handler
   518 //
   519 	{
   520 	User::Panic(_L("CMyActiveScheduer::Error"), anError);
   521 	}
   522 
   523 
   524 TInt ServerThread(TAny* aThreadIndex)
   525 //
   526 // Passed as the server thread in 2 tests - sets up and runs CTestServer
   527 //
   528 	{
   529 	RDBGD_PRINT(("ServerThread"));
   530 	TUint threadIndex = (TUint)aThreadIndex;
   531 
   532 	TBuf<16> serverName;
   533 	serverName = _L("ServerName_");
   534 	serverName.AppendNum(threadIndex);
   535 
   536 
   537 	CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
   538 	if (pScheduler == NULL)
   539 		{
   540 		gServerArgsArray[threadIndex].iBadServer = ETrue;
   541 		gServerArgsArray[threadIndex].iSemArray.Signal();
   542 		return KErrNoMemory;
   543 		}
   544 
   545 	CActiveScheduler::Install(pScheduler);
   546 
   547 	CTestServer* pServer = new CTestServer(0);
   548 	if (pServer == NULL)
   549 		{
   550 		gServerArgsArray[threadIndex].iBadServer = ETrue;
   551 		gServerArgsArray[threadIndex].iSemArray.Signal();
   552 		delete pScheduler;
   553 		return KErrNoMemory;
   554 		}
   555 
   556 	//Starting a CServer2 also Adds it to the ActiveScheduler
   557 	TInt r = pServer->Start(serverName);
   558 	if (r != KErrNone)
   559 		{
   560 		gServerArgsArray[threadIndex].iBadServer = ETrue;
   561 		gServerArgsArray[threadIndex].iSemArray.Signal();
   562 		delete pScheduler;
   563 		delete pServer;
   564 		return r;
   565 		}
   566 
   567 	RDBGD_PRINT(("Start ActiveScheduler and signal to client"));
   568 	RDBGD_PRINT(("There might be something going on beneath this window\n"));
   569 	gServerArgsArray[threadIndex].iSemArray.Signal();
   570 	CActiveScheduler::Start();
   571 
   572 	delete pScheduler;
   573 	delete pServer;
   574 
   575 	return KErrNone;
   576 	}
   577 
   578 TInt BadServerThread(TAny* /*aThreadIndex*/)
   579 //
   580 // Passed as the server thread in 2 tests - sets up and runs CTestServer
   581 //
   582 	{
   583 	RDBGD_PRINT(("BadServerThread"));
   584 	CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
   585 	if (pScheduler == NULL)
   586 		{
   587 		RDBGD_PRINT(("BST:Fail1"));
   588 		gServerArgsArray[KSemServer].iBadServer = ETrue;
   589 		gServerArgsArray[KSemServer].iSemArray.Signal();
   590 		return KErrNoMemory;
   591 		}
   592 
   593 	CActiveScheduler::Install(pScheduler);
   594 
   595 	CTestServer* pServer = new CTestServer(0);
   596 	if (pServer == NULL)
   597 		{
   598 		RDBGD_PRINT(("BST:Fail2"));
   599 		gServerArgsArray[KSemServer].iBadServer = ETrue;
   600 		gServerArgsArray[KSemServer].iSemArray.Signal();
   601 		delete pScheduler;
   602 		return KErrNoMemory;
   603 		}
   604 
   605 	//pServer->SetPinClientDescriptors(ETrue);
   606 
   607 
   608 	//Starting a CServer2 also Adds it to the ActiveScheduler
   609 	TInt r = pServer->Start(KTestServer);
   610 	if (r != KErrNone)
   611 		{
   612 		RDBGD_PRINT(("BST:Fail3"));
   613 		gServerArgsArray[KSemServer].iBadServer = ETrue;
   614 		gServerArgsArray[KSemServer].iSemArray.Signal();
   615 		delete pScheduler;
   616 		delete pServer;
   617 		return r;
   618 		}
   619 
   620 	RDBGD_PRINT(("Start ActiveScheduler and signal to client"));
   621 	RDBGD_PRINT(("There might be something going on beneath this window\n"));
   622 	gServerArgsArray[KSemServer].iSemArray.Signal();
   623 	CActiveScheduler::Start();
   624 
   625 	delete pScheduler;
   626 	delete pServer;
   627 	RDBGD_PRINT(("BST:Pass1"));
   628 	return KErrNone;
   629 	}
   630 
   631 TInt SendMessages(TUint aIters, TUint aSize, TDesC& aServerName, TInt aIndex, TBool aLowMem = EFalse)
   632 //
   633 // Passed as the first client thread - signals the server to do several tests
   634 //
   635 	{
   636 	HBufC8* argTmp1;
   637 	HBufC8* argTmp2;
   638 	HBufC8* argTmp3;
   639 	HBufC8* argTmp4;
   640 
   641 	DOTEST((argTmp1 = HBufC8::New(aSize)), (argTmp1 != NULL));
   642 	*argTmp1 = (const TUint8*)"argTmp1";
   643 	TPtr8 ptr1 = argTmp1->Des();
   644 
   645 	DOTEST((argTmp2 = HBufC8::New(aSize)), (argTmp2 != NULL));
   646 	*argTmp2 = (const TUint8*)"argTmp2";
   647 	TPtr8 ptr2 = argTmp2->Des();
   648 
   649 	DOTEST((argTmp3 = HBufC8::New(aSize)), (argTmp3 != NULL));
   650 	*argTmp3 = (const TUint8*)"argTmp3";
   651 	TPtr8 ptr3 = argTmp3->Des();
   652 
   653 	DOTEST((argTmp4 = HBufC8::New(aSize)), (argTmp1 != NULL));
   654 	*argTmp4 = (const TUint8*)"argTmp4";
   655 	TPtr8 ptr4 = argTmp4->Des();
   656 	
   657 	RSession session;
   658 	TInt r = KErrNone;
   659 	if(gTestBadServer)
   660 		{//Don't do bad server tests with lowmem
   661 		r = session.PublicCreateSession(aServerName,5);
   662 		}
   663 	else
   664 		{
   665 		DOTEST((r = session.PublicCreateSession(aServerName,5)), (r != KErrNoMemory));
   666 		}
   667 	if (r != KErrNone)
   668 		{
   669 		RDBGD_PRINT(("SendMessages[%d] failed to create session r = %d", aIndex, r));
   670 		return r;
   671 		}
   672 	
   673 	if(gTestBadServer)
   674 		{
   675 		RThread::Rendezvous(KErrNone);
   676 		RDBGD_PRINT(("Wait on sem %d", aIndex));
   677 		//gServerArgsArray[KSemCliSessStarted].iSemArray.Wait();
   678 		}
   679 	
   680 	RDBGD_PRINT(("ID (%d)ReadWrite" ,aIndex));
   681 	for (TUint i = 0; i < aIters; i++)
   682 		{
   683 		TUint mode = (i&0x3) + CTestSession::ERead;
   684 		switch(mode)
   685 			{
   686 			case CTestSession::ERead:
   687 				DOTEST((r = session.PublicSendReceive(CTestSession::ERead, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())), 
   688 						(r != KErrNoMemory));
   689 				if (r != KErrNone)
   690 					return r;
   691 				break;
   692 
   693 			case CTestSession::EWrite:
   694 				DOTEST((r = session.PublicSendReceive(CTestSession::EWrite, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())), 
   695 						(r != KErrNoMemory));
   696 				if (r != KErrNone)
   697 					return r;
   698 				break;
   699 			case CTestSession::EReadWrite:
   700 				DOTEST((r = session.PublicSendReceive(CTestSession::EReadWrite, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())), 
   701 						(r != KErrNoMemory));
   702 				if (r != KErrNone)
   703 					return r;
   704 				break;
   705 
   706 			}
   707 		}
   708 	RDBGD_PRINT(("ID(%d) Closing session", aIndex));
   709 	session.Close();
   710 	return r;
   711 	}
   712 
   713 TInt TestIPCPinning(SPerformTestArgs& aTestArguments)
   714 	{
   715 	TInt r = KErrNone;
   716 	// Create the server thread it needs to have a unpaged stack and heap.
   717 	TBuf<16> serverThreadName;
   718 	serverThreadName = _L("ServerThread_");
   719 	serverThreadName.AppendNum(aTestArguments.iThreadIndex);
   720 	TThreadCreateInfo serverInfo(serverThreadName, ServerThread, KDefaultStackSize, (TAny *) aTestArguments.iThreadIndex);
   721 	serverInfo.SetUseHeap(NULL);
   722 	
   723 	gServerArgsArray[aTestArguments.iThreadIndex].iBadServer = EFalse;
   724 
   725 	// Create the semaphores for the IPC pinning tests
   726 	DOTEST1((r = gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.CreateLocal(0)), (r != KErrNoMemory));
   727 	if (r != KErrNone)
   728 		{
   729 		RDBGD_PRINT(("Failed to create semaphonre[%d] r = %d", aTestArguments.iThreadIndex, r));
   730 		return r;
   731 		}
   732 
   733 	RThread serverThread;
   734 	TInt r1 = KErrNone;
   735 	DOTEST1((r1 = serverThread.Create(serverInfo)), (r1 != KErrNoMemory));
   736 	if (r1 != KErrNone)
   737 		{
   738 		RDBGD_PRINT(("Failed to create server thread[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
   739 		return r1;
   740 		}
   741 	TRequestStatus serverStat;
   742 	serverThread.Logon(serverStat);
   743 	serverThread.Resume();
   744 
   745 	// Wait for the server to start and then create a session to it.
   746 	TBuf<16> serverName;
   747 	serverName = _L("ServerName_");
   748 	serverName.AppendNum(aTestArguments.iThreadIndex);
   749 
   750 	gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.Wait();
   751 	
   752 	// First check that the server started successfully
   753 	if (gServerArgsArray[aTestArguments.iThreadIndex].iBadServer)
   754 		return KErrServerTerminated;
   755 
   756 	RSession session;
   757 	DOTEST1((r1 = session.PublicCreateSession(serverName,5)), (r1 != KErrNoMemory));
   758 	if (r1 != KErrNone)
   759 		{
   760 		RDBGD_PRINT(("Failed to create session[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
   761 		return r1;
   762 		}
   763 	
   764 	r1 = SendMessages(50, 10, serverName, aTestArguments.iThreadIndex, aTestArguments.iLowMem);
   765 	if (r1 != KErrNone)
   766 		{
   767 		RDBGD_PRINT(("SendMessages[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
   768 		return r1;
   769 		}
   770 	TInt r2 = KErrNone;
   771 	
   772 	// Signal to stop ActiveScheduler and wait for server to stop.
   773 	session.PublicSendReceive(CTestSession::EStop, TIpcArgs());
   774 	session.Close();
   775 
   776 	User::WaitForRequest(serverStat);
   777 	if (serverThread.ExitType() == EExitKill &&
   778 		serverThread.ExitReason() != KErrNone)	
   779 		{
   780 		r2 = serverThread.ExitReason();
   781 		}
   782 	if (serverThread.ExitType() != EExitKill)	
   783 		{
   784 		RDBGD_PRINT(("Server thread panic'd"));
   785 		r2 = KErrGeneral;
   786 		}
   787 
   788 	serverThread.Close();
   789 	gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.Close();
   790 		
   791 	if (r1 != KErrNone)
   792 		return r1;
   793 
   794 	return r2;
   795 	}
   796 
   797 TInt ClientThread(TAny* aClientThread)
   798 	{
   799 	TInt r = KErrNone;
   800 	
   801 	TBuf<16> serverName;
   802 	serverName = KTestServer;
   803 	RDBGD_PRINT(("CT(%d):Sending Messages" ,aClientThread));
   804 	r = SendMessages(500, 10, serverName, (TInt) aClientThread);
   805 	if (r != KErrNone)
   806 		{
   807 		RDBGD_PRINT(("SendMessages[%d] r = %d", (TInt) aClientThread, r));
   808 		return r;
   809 		}
   810 	return r;
   811 	}
   812 
   813 TInt TestIPCBadServer(SPerformTestArgs& aTestArguments)
   814 	{
   815 	TInt cliRet = KErrNone;
   816 	TInt serRet = KErrNone;
   817 
   818 	// Create the server thread it needs to have a unpaged stack and heap.
   819 	TBuf<16> serverThreadName;
   820 	serverThreadName = _L("BadServerThread");
   821 	TThreadCreateInfo serverInfo(serverThreadName, BadServerThread, KDefaultStackSize, NULL);
   822 	serverInfo.SetUseHeap(NULL);
   823 	
   824 	// Create the semaphores for the IPC pinning tests
   825 	DOTEST1((serRet = gServerArgsArray[KSemServer].iSemArray.CreateLocal(0)), (serRet != KErrNoMemory));
   826 	if (serRet != KErrNone)
   827 		{
   828 		RDBGD_PRINT(("Failed to create semaphonre[%d] serRet = %d", KSemServer, serRet));
   829 		return serRet;
   830 		}
   831 
   832 	RThread serverThread;
   833 	DOTEST1((serRet = serverThread.Create(serverInfo)), (serRet != KErrNoMemory));
   834 	if (serRet != KErrNone)
   835 		{
   836 		RDBGD_PRINT(("Failed to create server thread serRet = %d", serRet));
   837 		return serRet;
   838 		}
   839 	TRequestStatus serverStat;
   840 	serverThread.Logon(serverStat);
   841 	serverThread.Resume();
   842 
   843 	// Wait for the server to start and then create a session to it.
   844 	gServerArgsArray[KSemServer].iSemArray.Wait();
   845 	
   846 	// First check that the server started successfully
   847 	if (gServerArgsArray[KSemServer].iBadServer)
   848 		return KErrServerTerminated;
   849 
   850 
   851 	//create client threads
   852 	const TUint KNumClientThreads = 50;	
   853 	RThread clientThreads[KNumClientThreads];
   854 	TRequestStatus clientStarted[KNumClientThreads];
   855 	TRequestStatus clientStats[KNumClientThreads];
   856 
   857 	// Create the client threads
   858 	TBuf<16> clientThreadName;
   859 	TUint i;
   860 	for (i = 0; i < KNumClientThreads; i++)
   861 		{
   862 		clientThreadName = _L("clientThread_");
   863 		clientThreadName.AppendNum(i);
   864 		TThreadCreateInfo clientInfo(clientThreadName, ClientThread, KDefaultStackSize, (TAny*)i);
   865 		clientInfo.SetPaging(TThreadCreateInfo::EPaged);
   866 		clientInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
   867 		cliRet = clientThreads[i].Create(clientInfo);
   868 		if (cliRet != KErrNone)
   869 			{
   870 			RDBGD_PRINT(("Failed to create client thread [%d] cliRet = %d", i, cliRet));
   871 			return cliRet;
   872 			}
   873 		clientThreads[i].Rendezvous(clientStarted[i]);	
   874 		clientThreads[i].Logon(clientStats[i]);
   875 		clientThreads[i].Resume();
   876 		}
   877 	
   878 	// Wait for creation of the client thread sessions
   879 	for (i = 0; i < KNumClientThreads; i++)
   880 		{
   881 		User::WaitForRequest(clientStarted[i]);
   882 		if (clientStarted[i].Int() != KErrNone)
   883 			return clientStarted[i].Int();
   884 		}
   885 	
   886 
   887 	// Once the messages are being sent, create a session to the
   888 	// same server and signal to stop ActiveScheduler
   889 	RSession session;
   890 	serRet = session.PublicCreateSession(KTestServer,5);
   891 	if (serRet != KErrNone)
   892 		{
   893 		RDBGD_PRINT(("Failed to create session serRet = %d", serRet));
   894 		return serRet;
   895 		}
   896 	session.PublicSendReceive(CTestSession::EStop, TIpcArgs());
   897 	session.Close();
   898 
   899 	// Wait for the client thread to end.
   900 	cliRet = KErrNone;
   901 	for (i = 0; i < KNumClientThreads; i++)
   902 		{
   903 		User::WaitForRequest(clientStats[i]);
   904 		RDBGD_PRINT(("Thread complete clientStats[%d] = %d", i, clientStats[i].Int()));
   905 		if (clientStats[i].Int() != KErrNone && 
   906 			clientStats[i].Int() != KErrServerTerminated)
   907 			{
   908 			cliRet = clientStats[i].Int();
   909 			}
   910 		}
   911 
   912 	// Check that the server ended correctly
   913 	serRet = KErrNone;
   914 	User::WaitForRequest(serverStat);
   915 	if (serverThread.ExitType() == EExitKill &&
   916 		serverThread.ExitReason() != KErrNone)	
   917 		{
   918 		serRet = serverThread.ExitReason();
   919 		}
   920 	if (serverThread.ExitType() != EExitKill)	
   921 		{
   922 		RDBGD_PRINT(("Server thread panic'd"));
   923 		serRet = KErrGeneral;
   924 		}
   925 
   926 	// Close all the server thread and client threads
   927 	for (i = 0; i < KNumClientThreads; i++)
   928 		{
   929 		clientThreads[i].Close();
   930 		}
   931 	serverThread.Close();
   932 		
   933 	if (cliRet != KErrNone)
   934 		return cliRet;
   935 
   936 	return serRet;
   937 	}
   938 
   939 
   940 //
   941 // RemoveChunkAlloc
   942 //
   943 // Remove ALL chunks allocated
   944 //
   945 // @param aChunkArray The array that stores a reference to the chunks created.
   946 // @param aChunkArraySize The size of aChunkArray.
   947 //
   948 void RemoveChunkAlloc(RChunk*& aChunkArray, TUint aChunkArraySize)
   949 	{
   950 	if (aChunkArray == NULL)
   951 		{// The chunk array has already been deleted.
   952 		return;
   953 		}
   954 
   955 	for (TUint i = 0; i < aChunkArraySize; i++)
   956 		{
   957 		if (aChunkArray[i].Handle() != NULL)
   958 			{
   959 			aChunkArray[i].Close();
   960 			gChunksAllocd --;
   961 			if (gChunksAllocd < gMaxChunks)
   962 				gMaxChunksReached = EFalse;
   963 			}
   964 		}
   965 	delete[] aChunkArray;
   966 	aChunkArray = NULL;
   967 	}	
   968 
   969 TInt WriteToChunk(RChunk* aChunkArray, TUint aChunkArraySize)
   970 	{
   971 	for (TUint j = 0; j < aChunkArraySize; j++) 
   972 		{
   973 		if (aChunkArray[j].Handle() != NULL)
   974 			{
   975 			TUint32* base = (TUint32*)aChunkArray[j].Base();
   976 			TUint32* end = (TUint32*)(aChunkArray[j].Base() + aChunkArray[j].Size());
   977 			for (TUint32 k = 0; base < end; k++)
   978 				{
   979 				*base++ = k; // write index to the chunk
   980 				}
   981 			}		
   982 		}
   983 	return KErrNone;
   984 	}
   985 
   986 TUint32 ReadByte(volatile TUint32* aPtr)
   987 	{
   988 	return *aPtr;
   989 	}
   990 
   991 TInt ReadChunk(RChunk* aChunkArray, TUint aChunkArraySize)
   992 	{
   993 	for (TUint j=0; j < aChunkArraySize; j++) //Read all open chunks
   994 		{
   995 		if (aChunkArray[j].Handle() != NULL)
   996 			{
   997 			TUint32* base = (TUint32*)aChunkArray[j].Base();
   998 			TUint32* end = (TUint32*)(aChunkArray[j].Base() + aChunkArray[j].Size());
   999 			for (TUint32 k = 0; base < end; k++)
  1000 				{
  1001 				TUint value = ReadByte((volatile TUint32*)base++);
  1002 				if (value != k)
  1003 					{
  1004 					RDBGS_PRINT(("Read value incorrect expected 0x%x got 0x%x", k, value));
  1005 					return KErrGeneral;
  1006 					}
  1007 				}
  1008 			}		
  1009 		}
  1010 	return KErrNone;
  1011 	}
  1012 
  1013 
  1014 TInt CreateChunks(SPerformTestArgs& aTestArguments, RChunk*& aChunkArray, TUint aChunkArraySize)
  1015 	{
  1016 	TInt r = KErrNone;
  1017 
  1018 	TUint chunkSize = 1 << gPageShift;
  1019 
  1020 	// Allocate as many chunks as is specified, either with the default chunk size or a specified chunk size
  1021 	if (aChunkArray == NULL)
  1022 		{
  1023 		DOTEST1((aChunkArray = new RChunk[aChunkArraySize]), (aChunkArray != NULL));
  1024 		if (aChunkArray == NULL)
  1025 			return KErrNoMemory;
  1026 		}
  1027 	
  1028 	TChunkCreateInfo createInfo;
  1029 	createInfo.SetNormal(chunkSize, chunkSize);
  1030 	createInfo.SetPaging(TChunkCreateInfo::EPaged);
  1031 
  1032 
  1033 	// Create chunks for each RChunk with a NULL handle.
  1034 	for (TUint i = 0; i < aChunkArraySize; i++)
  1035 		{
  1036 		DOTEST1((r = aChunkArray[i].Create(createInfo)), (r != KErrNoMemory));
  1037 		if (r != KErrNone)
  1038 			{
  1039 			if (r == KErrOverflow)
  1040 				{
  1041 				gMaxChunks = gChunksAllocd;
  1042 				RDBGD_PRINT(("Max Chunks Allowed = %d", gMaxChunks));
  1043 				gMaxChunksReached = ETrue;
  1044 				}
  1045 			return r;
  1046 			}
  1047 		gChunksAllocd++;
  1048 		RDBGD_PRINT(("TID(%d) aChunkArray[%d], r = %d", aTestArguments.iThreadIndex, i, r));
  1049 		}
  1050 	RDBGD_PRINT(("TID(%d) created chunks r = %d", aTestArguments.iThreadIndex, r));
  1051 	
  1052 	return KErrNone;
  1053 	}
  1054 //
  1055 // TestChunkPaging
  1056 //
  1057 // Create a number of chunks and write to them
  1058 // read the chunk back to ensure the values are correct
  1059 //
  1060 
  1061 TInt TestChunkPaging(SPerformTestArgs& aTestArguments)
  1062 	{
  1063 	TInt r = KErrNone;
  1064 	const TUint KNumChunks = 10;
  1065 	
  1066 	
  1067 	if(gMaxChunksReached)
  1068 		{// We cant create any more chunks as the max number has been reached
  1069 		return KErrNone;
  1070 		}
  1071 
  1072 	RChunk* chunkArray = NULL;	
  1073 	r = CreateChunks(aTestArguments, chunkArray, KNumChunks);
  1074 	if (r != KErrNone)
  1075 		{
  1076 		if (r == KErrOverflow)
  1077 			{
  1078 			RDBGD_PRINT(("Max number of chunks reached"));
  1079 			RemoveChunkAlloc(chunkArray, KNumChunks);
  1080 			return KErrNone;
  1081 			}
  1082 		RDBGD_PRINT(("TID(%d) CreateChunks r = %d", aTestArguments.iThreadIndex, r));
  1083 		return r;
  1084 		}
  1085 
  1086 	r = WriteToChunk(chunkArray, KNumChunks);
  1087 	if (r != KErrNone)
  1088 		{
  1089 		RemoveChunkAlloc(chunkArray, KNumChunks);
  1090 		RDBGD_PRINT(("TID(%d) WriteToChunk r = %d", aTestArguments.iThreadIndex, r));
  1091 		return r;
  1092 		}
  1093 
  1094 	r = ReadChunk(chunkArray, KNumChunks);
  1095 	if (r != KErrNone)
  1096 		{
  1097 		RemoveChunkAlloc(chunkArray, KNumChunks);
  1098 		RDBGD_PRINT(("TID(%d) ReadChunk r = %d", aTestArguments.iThreadIndex, r));
  1099 		return r;
  1100 		} 
  1101 	RemoveChunkAlloc(chunkArray, KNumChunks);
  1102 	return KErrNone;
  1103 	}
  1104 
  1105 
  1106 //
  1107 // TestChunkCommit
  1108 //
  1109 // Create a chunk
  1110 // commit a page at a time, write to that page and then decommit the page
  1111 //
  1112 
  1113 TInt TestChunkCommit(SPerformTestArgs& aTestArguments)
  1114 	{
  1115 	TInt r = KErrNone;
  1116 	RChunk testChunk;
  1117 
  1118 	TUint chunkSize = 70 << gPageShift;
  1119 
  1120 	TChunkCreateInfo createInfo;
  1121 	createInfo.SetDisconnected(0, 0, chunkSize);
  1122 	createInfo.SetPaging(TChunkCreateInfo::EPaged);
  1123 	DOTEST1((r = testChunk.Create(createInfo)), (r != KErrNoMemory));
  1124 	if (r != KErrNone)
  1125 		{
  1126 		return r;
  1127 		}
  1128 	TUint offset = 0;
  1129 	while(offset < chunkSize)
  1130 		{
  1131 		// Commit a page
  1132 		DOTEST1((r = testChunk.Commit(offset,gPageSize)), (r != KErrNoMemory));
  1133 		if (r != KErrNone)
  1134 			{
  1135 			return r;
  1136 			}
  1137 
  1138 		// Write to the page
  1139 		TUint8* pageStart = testChunk.Base() + offset;
  1140 		*pageStart = 0xed;
  1141 
  1142 
  1143 		// Decommit the page
  1144 		r = testChunk.Decommit(offset, gPageSize);
  1145 		if (r != KErrNone)
  1146 			{
  1147 			return r;
  1148 			}
  1149 		
  1150 		offset += gPageSize;
  1151 		}
  1152 	
  1153 
  1154 	testChunk.Close();
  1155 	return r;
  1156 	}
  1157 
  1158 //
  1159 // PerformTestThread
  1160 //
  1161 // This is the function that actually does the work.
  1162 // It is complicated a little because test.Printf can only be called from the first thread that calls it 
  1163 // so if we are using multiple threads we need to use a message queue to pass the debug info from the
  1164 // child threads back to the parent for the parent to then call printf.
  1165 //
  1166 //
  1167 
  1168 LOCAL_C TInt PerformTestThread(SPerformTestArgs& aTestArguments)
  1169 	{
  1170 	TInt r = KErrNone;
  1171 	TUint start = User::TickCount();
  1172 
  1173 	DEBUG_PRINT1((_L("%S : thread Starting %d\n"), &gTestNameBuffer, aTestArguments.iThreadIndex));
  1174 	// now select how we do the test...
  1175 	TInt	iterIndex = 0;
  1176 
  1177 
  1178 	if (TEST_ALL == (gTestWhichTests & TEST_ALL))
  1179 		{
  1180 		#define LOCAL_ORDER_INDEX1	6
  1181 		#define LOCAL_ORDER_INDEX2	4
  1182 		TInt	order[LOCAL_ORDER_INDEX1][LOCAL_ORDER_INDEX2] = {	{TEST_STACK, TEST_CHUNK,TEST_COMMIT, TEST_IPC},
  1183 																	{TEST_STACK, TEST_COMMIT,  TEST_CHUNK, TEST_IPC},
  1184 																	{TEST_CHUNK,TEST_STACK, TEST_COMMIT, TEST_IPC},
  1185 																	{TEST_CHUNK,TEST_COMMIT,  TEST_STACK, TEST_IPC},
  1186 																	{TEST_COMMIT,  TEST_STACK, TEST_CHUNK, TEST_IPC},
  1187 																	{TEST_COMMIT,  TEST_CHUNK,TEST_STACK, TEST_IPC}};
  1188 		TInt	whichOrder = 0;
  1189 		iterIndex = 0;
  1190 		for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
  1191 			{
  1192 			DEBUG_PRINT1((_L("iterIndex = %d\n"), iterIndex));
  1193 			TInt    selOrder = ((aTestArguments.iThreadIndex + 1) * (iterIndex + 1)) % LOCAL_ORDER_INDEX1;
  1194 			for (whichOrder = 0; whichOrder < LOCAL_ORDER_INDEX2; whichOrder ++)
  1195 				{
  1196 				DEBUG_PRINT1((_L("whichOrder = %d\n"), whichOrder));
  1197 				switch (order[selOrder][whichOrder])
  1198 					{
  1199 					case TEST_STACK:
  1200 					DEBUG_PRINT1((_L("%S : %d Iter %d Stack\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1201 					r = TestStackPaging(aTestArguments);
  1202 					DEBUG_PRINT1((_L("ThreadId %d Finished TestStackPaging() r = %d\n"), aTestArguments.iThreadIndex, r));
  1203 					if (r != KErrNone)
  1204 						return r;
  1205 					break;
  1206 
  1207 					case TEST_CHUNK:
  1208 					DEBUG_PRINT1((_L("%S : %d Iter %d Chunk\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1209 					r = TestChunkPaging(aTestArguments);
  1210 					DEBUG_PRINT1((_L("ThreadId %d Finished TestChunkPaging() r = %d\n"), aTestArguments.iThreadIndex, r));
  1211 					if (r != KErrNone)
  1212 						return r;
  1213 					break;
  1214 
  1215 					case TEST_COMMIT:
  1216 					DEBUG_PRINT1((_L("%S : %d Iter %d Commit\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1217 					r = TestChunkCommit(aTestArguments);
  1218 					DEBUG_PRINT1((_L("ThreadId %d Finished TestChunkCommit() r = %d\n"), aTestArguments.iThreadIndex, r));
  1219 					if (r != KErrNone)
  1220 						return r;
  1221 					break;
  1222 
  1223 					case TEST_IPC:
  1224 					
  1225 					if (gTestBadServer)
  1226 						{
  1227 						DEBUG_PRINT1((_L("%S : %d Iter %d IPC-BadServer\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1228 						r = TestIPCBadServer(aTestArguments);
  1229 						DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCBadServer() r = %d\n"), aTestArguments.iThreadIndex, r));
  1230 						}
  1231 					else
  1232 						{
  1233 						DEBUG_PRINT1((_L("%S : %d Iter %d IPC\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1234 						// Limit the IPC pinning stuff to 2 loops else will take a long time to run
  1235 						if (gNumTestThreads > 1 && gPerformTestLoop > 2)
  1236 							break;
  1237 						r = TestIPCPinning(aTestArguments);
  1238 						DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCPinning() r = %d\n"), aTestArguments.iThreadIndex, r));
  1239 						if (r != KErrNone)
  1240 							return r;
  1241 						}
  1242 					break;
  1243 					
  1244 					default: // this is really an error.
  1245 					break;
  1246 					}
  1247 				iterIndex++;
  1248 				}
  1249 			}
  1250 		}
  1251 	else
  1252 		{
  1253 		if (gTestWhichTests & TEST_STACK)
  1254 			{
  1255 			for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
  1256 				{
  1257 				DEBUG_PRINT1((_L("%S : %d Iter %d Stack\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1258 				r = TestStackPaging(aTestArguments);
  1259 				DEBUG_PRINT1((_L("ThreadId %d Finished TestStackPaging() r = %d\n"), aTestArguments.iThreadIndex, r));
  1260 				if (r != KErrNone)
  1261 						return r;
  1262 				}
  1263 			}
  1264 			
  1265 		if (gTestWhichTests & TEST_CHUNK)
  1266 			{
  1267 			for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
  1268 				{
  1269 				DEBUG_PRINT1((_L("%S : %d Iter %d Chunk\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1270 				r = TestChunkPaging(aTestArguments);
  1271 				DEBUG_PRINT1((_L("ThreadId %d Finished TestChunkPaging() r = %d\n"), aTestArguments.iThreadIndex, r));
  1272 				if (r != KErrNone)
  1273 						return r;
  1274 				}
  1275 			}
  1276 
  1277 		if (gTestWhichTests & TEST_COMMIT)
  1278 			{
  1279 			for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
  1280 				{
  1281 				DEBUG_PRINT1((_L("%S : %d Iter %d Commit\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1282 				r = TestChunkCommit(aTestArguments);
  1283 				DEBUG_PRINT1((_L("ThreadId %d Finished TestChunkCommit() r = %d\n"), aTestArguments.iThreadIndex, r));
  1284 				if (r != KErrNone)
  1285 					return r;
  1286 				}
  1287 			}
  1288 
  1289 		if (gTestWhichTests & TEST_IPC)
  1290 			{
  1291 			// In multiple thread case limit IPC test to 2 loops else will take a long time
  1292 			TInt loops = (gPerformTestLoop <= 2 && gNumTestThreads) ? gPerformTestLoop : 2;
  1293 			for (iterIndex = 0; iterIndex < loops; iterIndex ++)
  1294 				{
  1295 				if (gTestBadServer)
  1296 					{
  1297 					r = TestIPCBadServer(aTestArguments);
  1298 					DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCBadServer() r = %d\n"), aTestArguments.iThreadIndex, r));
  1299 					}
  1300 				else
  1301 					{
  1302 					DEBUG_PRINT1((_L("%S : %d Iter %d IPC\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, iterIndex));
  1303 					r = TestIPCPinning(aTestArguments);
  1304 					DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCPinning() r = %d\n"), aTestArguments.iThreadIndex, r));
  1305 					if (r != KErrNone)
  1306 						return r;
  1307 					}
  1308 				}
  1309 			}
  1310 		}
  1311 	
  1312 	DEBUG_PRINT1((_L("%S : thread Exiting %d (tickcount %u)\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, (User::TickCount() - start)));
  1313 	return r;
  1314 	}
  1315 
  1316 
  1317 //
  1318 // MultipleTestThread
  1319 //
  1320 // Thread function, one created for each thread in a multiple thread test.
  1321 //
  1322 
  1323 LOCAL_C TInt MultipleTestThread(TAny* aTestArgs)
  1324 	{
  1325 	TInt r = KErrNone;
  1326 	TBuf<64>					localBuffer;
  1327 
  1328 	if (gTestInterleave)	
  1329 		{
  1330 		RThread				thisThread;
  1331 		thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
  1332 		}
  1333 	
  1334 	SPerformTestArgs& testArgs = *(SPerformTestArgs*)aTestArgs;
  1335 	testArgs.iBuffer = &localBuffer;
  1336 	
  1337 	RDBGD_PRINT(("Performing test thread ThreadID(%d)\n", testArgs.iThreadIndex));
  1338 	r = PerformTestThread(testArgs);
  1339 	
  1340 	return r;
  1341 	}
  1342 
  1343 
  1344 
  1345 //
  1346 // FindMMCDriveNumber
  1347 // 
  1348 // Find the first read write drive.
  1349 //
  1350 
  1351 TInt FindMMCDriveNumber(RFs& aFs)
  1352 	{
  1353 	TDriveInfo driveInfo;
  1354 	for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
  1355 		{
  1356 		TInt r = aFs.Drive(driveInfo, drvNum);
  1357 		if (r >= 0)
  1358 			{
  1359 			if (driveInfo.iType == EMediaHardDisk)
  1360 				return (drvNum);
  1361 			}
  1362 		}
  1363 	return -1; 
  1364 	}
  1365 
  1366 //
  1367 // PerformRomAndFileSystemAccess
  1368 // 
  1369 // Access the rom and dump it out to one of the writeable partitions...
  1370 // really just to make the media server a little busy during the test.
  1371 //
  1372 
  1373 TInt PerformRomAndFileSystemAccessThread(SPerformTestArgs& aTestArguments)
  1374 	{
  1375 	TUint maxBytes = KMaxTUint;
  1376 	TInt startTime = User::TickCount();
  1377 
  1378 	RFs fs;
  1379 	RFile file;
  1380 	if (KErrNone != fs.Connect())
  1381 		{
  1382 		DEBUG_PRINT(_L("PerformRomAndFileSystemAccessThread : Can't connect to the FS\n"));
  1383 		return KErrGeneral;
  1384 		}
  1385 
  1386 	// get info about the ROM...
  1387 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
  1388 	TUint8* start;
  1389 	TUint8* end;
  1390 	if(romHeader->iPageableRomStart)
  1391 		{
  1392 		start = (TUint8*)romHeader + romHeader->iPageableRomStart;
  1393 		end = start + romHeader->iPageableRomSize;
  1394 		}
  1395 	else
  1396 		{
  1397 		start = (TUint8*)romHeader;
  1398 		end = start + romHeader->iUncompressedSize;
  1399 		}
  1400 	if (end <= start)
  1401 		return KErrGeneral;
  1402 
  1403 	// read all ROM pages in a random order...and write out to file in ROFs, 
  1404 	TUint size = end - start - gPageSize;
  1405 	if(size > maxBytes)
  1406 		size = maxBytes;
  1407 
  1408 	TUint32 random = 1;
  1409 	TPtrC8 rom;
  1410 	TUint8 *theAddr;
  1411 
  1412 	//TInt		drvNum = TestBootedFromMmc ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
  1413 	TInt drvNum = FindMMCDriveNumber(fs);
  1414 	TBuf<32>	filename = _L("d:\\Pageldrtst.tmp");
  1415 	if (drvNum >= 0)
  1416 		{
  1417 		filename[0] = (TUint16)('a' + drvNum);
  1418 		DEBUG_PRINT1((_L("%S : Filename %S\n"), &gTestNameBuffer, &filename));
  1419 		}
  1420 	else
  1421 		DEBUG_PRINT((_L("PerformRomAndFileSystemAccessThread : error getting drive num\n")));
  1422 
  1423 	for(TInt i = (size >> gPageShift); i > 0; --i)
  1424 		{
  1425 		DEBUG_PRINT1((_L("%S : Opening the file\n"), &gTestNameBuffer));
  1426 		if (KErrNone != file.Replace(fs, filename, EFileWrite))
  1427 			{
  1428 			DEBUG_PRINT1((_L("%S : Opening the file Failed!\n"), &gTestNameBuffer));
  1429 			}
  1430 
  1431 		random = random * 69069 + 1;
  1432 		theAddr = (TUint8*)(start+((TInt64(random)*TInt64(size))>>32));
  1433 		if (theAddr + gPageSize > end)
  1434 			{
  1435 			DEBUG_PRINT1((_L("%S : address is past the end 0x%x / 0x%x\n"), &gTestNameBuffer, (TInt)theAddr, (TInt)end));
  1436 			}
  1437 		rom.Set(theAddr,gPageSize);
  1438 		DEBUG_PRINT1((_L("%S : Writing the file\n"), &gTestNameBuffer));
  1439 		TInt ret = file.Write(rom);
  1440 		if (ret != KErrNone)
  1441 			{
  1442 			DEBUG_PRINT1((_L("%S : Write returned error %d\n"), &gTestNameBuffer, ret));
  1443 			}
  1444 		DEBUG_PRINT1((_L("%S : Closing the file\n"), &gTestNameBuffer));
  1445 		file.Close();
  1446 
  1447 		DEBUG_PRINT1((_L("%S : Deleting the file\n"), &gTestNameBuffer));
  1448 		ret = fs.Delete(filename);
  1449 		if (KErrNone != ret)
  1450 			{
  1451 			DEBUG_PRINT1((_L("%S : Delete returned error %d\n"), &gTestNameBuffer, ret));
  1452 			}
  1453 		if (gTestStopMedia)
  1454 			break;
  1455 		}
  1456 	fs.Close();
  1457 	DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
  1458 	return KErrNone;
  1459 	}
  1460 
  1461 
  1462 //
  1463 // PerformRomAndFileSystemAccess
  1464 //
  1465 // Thread function, kicks off the file system access.
  1466 //
  1467 
  1468 LOCAL_C TInt PerformRomAndFileSystemAccess(TAny* aTestArgs)
  1469 	{
  1470 	TBuf<64>					localBuffer;
  1471 	
  1472 	SPerformTestArgs& testArgs = *(SPerformTestArgs*)aTestArgs;
  1473 	testArgs.iBuffer = &localBuffer;
  1474 	
  1475 	PerformRomAndFileSystemAccessThread(testArgs);
  1476 	
  1477 	return KErrNone;
  1478 	}
  1479 
  1480 
  1481 
  1482 
  1483 //
  1484 // StartFlushing
  1485 //
  1486 // Create a thread that will continuously flush the paging cache
  1487 //
  1488 void StartFlushing(TRequestStatus &aStatus, RThread &aFlushThread, TBool aLowMem = EFalse)
  1489 	{
  1490 	TInt ret;
  1491 	gTestRunning = ETrue;
  1492 
  1493 	TThreadCreateInfo flushThreadInfo(_L("FlushThread"), FlushFunc, KDefaultStackSize,NULL);
  1494 	flushThreadInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
  1495 	
  1496 	if (!aLowMem)
  1497 		{
  1498 		test_KErrNone(aFlushThread.Create(flushThreadInfo));
  1499 		}
  1500 	else
  1501 		{
  1502 		DOTEST((ret = aFlushThread.Create(flushThreadInfo)), (ret != KErrNoMemory));
  1503 		test_KErrNone(ret);
  1504 		}
  1505 	
  1506 	
  1507 	aFlushThread.Logon(aStatus);
  1508 	
  1509 	aFlushThread.Resume();
  1510 	}
  1511 
  1512 //
  1513 // FinishFlushing
  1514 //
  1515 // Close the thread flushing the paging cache
  1516 //
  1517 void FinishFlushing(TRequestStatus &aStatus, RThread &aFlushThread)
  1518 	{
  1519 	gTestRunning = EFalse;
  1520 	User::WaitForRequest(aStatus);
  1521 	// TO DO: Check Exit tyoe
  1522 	CLOSE_AND_WAIT(aFlushThread);
  1523 	}
  1524 
  1525 
  1526 //
  1527 // ResetResults
  1528 // 
  1529 // Clear the previous results from the results array
  1530 //
  1531 TInt ResetResults()
  1532 	{
  1533 	for (TUint i = 0; i < KMaxTestThreads; i++)
  1534 		{
  1535 		gResultsArray[i].iExitType = KExitTypeReset;
  1536 		gResultsArray[i].iExitReason = KErrNone;
  1537 		}
  1538 	return KErrNone;
  1539 	}
  1540 
  1541 
  1542 //
  1543 // CheckResults
  1544 //
  1545 // Check that the results are as expected
  1546 //
  1547 TInt CheckResults()
  1548 	{
  1549 	TUint i;
  1550 	for (i = 0; i < KMaxTestThreads; i++)
  1551 		{
  1552 		if (gResultsArray[i].iExitType == KExitTypeReset)
  1553 			continue;
  1554 		RDBGD_PRINT(("%S : Thread %d ExitType(%d) ExitReason(%d)...\n", 
  1555 					&gTestNameBuffer, i, gResultsArray[i].iExitType, gResultsArray[i].iExitReason));
  1556 		}
  1557 	
  1558 	for (i = 0; i < KMaxTestThreads; i++)
  1559 		{
  1560 		if (gResultsArray[i].iExitType == KExitTypeReset)
  1561 			continue;
  1562 		
  1563 		if (gResultsArray[i].iExitType != EExitKill)
  1564 			{
  1565 			RDBGS_PRINT(("Thread %d ExitType(%d) Expected(%d)\n", i, gResultsArray[i].iExitType, EExitKill));
  1566 			return KErrGeneral;
  1567 			}
  1568 		
  1569 		// Allow for No Memory as we can run out of memory due to high number of threads and
  1570 		// Overflow as the number of chunks that can be created on moving memory model is capped
  1571 		if (gResultsArray[i].iExitReason != KErrNone &&
  1572 			gResultsArray[i].iExitReason != KErrNoMemory &&
  1573 			gResultsArray[i].iExitReason != KErrOverflow)
  1574 			{
  1575 			RDBGS_PRINT(("Thread %d ExitReason(%d) Expected either %d, %d or %d\n", 
  1576 							i, gResultsArray[i].iExitReason, KErrNone, KErrNoMemory, KErrOverflow));
  1577 			return KErrGeneral;
  1578 			}
  1579 		}
  1580 	return KErrNone;
  1581 	}
  1582 
  1583 
  1584 //
  1585 // PrintOptions
  1586 //
  1587 // Print out the options of the test
  1588 //
  1589 void PrintOptions()
  1590 	{
  1591 	SVMCacheInfo  tempPages;
  1592 	if (gIsDemandPaged)
  1593 		{
  1594 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
  1595 		test.Printf(_L("PerformAutoTest : Start cache info: iMinSize 0x%x iMaxSize 0x%x iCurrentSize 0x%x iMaxFreeSize 0x%x\n"),
  1596 					 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize);
  1597 		}
  1598 	
  1599 	test.Printf(_L("Loops (%d), Threads (%d), Tests: "), gPerformTestLoop, gNumTestThreads);
  1600 	if (TEST_ALL == (gTestWhichTests & TEST_ALL))
  1601 		{
  1602 		test.Printf(_L("All, "));
  1603 		}
  1604 	else if (gTestWhichTests & TEST_STACK)
  1605 		{
  1606 		test.Printf(_L("Stack, "));
  1607 		}
  1608 	else if (gTestWhichTests & TEST_CHUNK)
  1609 		{
  1610 		test.Printf(_L("Chunk, "));
  1611 		}
  1612 	else if (gTestWhichTests & TEST_COMMIT)
  1613 		{
  1614 		test.Printf(_L("Commit, "));
  1615 		}
  1616 	else if (gTestWhichTests & TEST_IPC)
  1617 		{
  1618 		test.Printf(_L("IPC Pinning, "));
  1619 		}
  1620 	else
  1621 		{
  1622 		test.Printf(_L("?, "));
  1623 		}
  1624 	test.Printf(_L("\nOptions: "));
  1625 
  1626 	if(gTestInterleave)
  1627 		test.Printf(_L("Interleave "));
  1628 	if(gTestPrioChange)
  1629 		test.Printf(_L("Priority "));
  1630 	if(gTestMediaAccess)
  1631 		test.Printf(_L("Media"));
  1632 	if(gTestBadServer)
  1633 		test.Printf(_L("BadServer"));
  1634 	test.Printf(_L("\n"));
  1635 	}
  1636 
  1637 // DoMultipleTest
  1638 // 
  1639 // Perform the multiple thread test, spawning a number of threads.
  1640 // It is complicated a little because test.Printf can only be called from the first thread that calls it 
  1641 // so if we are using multiple threads we need to use a message queue to pass the debug info from the
  1642 // child threads back to the parent for the parent to then call printf.
  1643 //
  1644 TInt DoMultipleTest(TBool aLowMem = EFalse)
  1645 	{
  1646 	SVMCacheInfo  tempPages;
  1647 	memset(&tempPages, 0, sizeof(tempPages));
  1648 
  1649 	if (gIsDemandPaged)
  1650 		{
  1651 		// get the old cache info
  1652 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
  1653 		// set the cache to our test value
  1654 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)tempPages.iMinSize,(TAny*)(tempPages.iMaxSize * gNumTestThreads));
  1655 		}
  1656 	
  1657 	if (!TestSilent)
  1658 		PrintOptions();
  1659 
  1660 	TUint startTime = User::TickCount();
  1661 	TInt			 index;
  1662 	TInt ret = KErrNone;
  1663 	TBuf<16> multiThreadName;
  1664 	TBuf<16> rerunThreadName;
  1665 	
  1666 	ResetResults();
  1667 	
  1668 	TRequestStatus flushStatus;
  1669 	RThread flushThread;
  1670 	StartFlushing(flushStatus, flushThread, aLowMem);
  1671 
  1672 	DOTEST((gThreadHeap = User::ChunkHeap(NULL, 0x1000, 0x1000)), (gThreadHeap != NULL));
  1673 	test_NotNull(gThreadHeap);
  1674 	
  1675 	DOTEST((gStackHeap = User::ChunkHeap(NULL, 0x1000, 0x1000)), (gStackHeap != NULL));
  1676 	test_NotNull(gStackHeap);
  1677 
  1678 	TThreadCreateInfo	*pThreadCreateInfo = (TThreadCreateInfo *)User::AllocZ(sizeof(TThreadCreateInfo) * gNumTestThreads);
  1679 	RThread				*pTheThreads  = (RThread *)User::AllocZ(sizeof(RThread) * gNumTestThreads);
  1680 	TInt				*pThreadInUse = (TInt *)User::AllocZ(sizeof(TInt) * gNumTestThreads);
  1681 
  1682 	TRequestStatus	mediaStatus;
  1683 	RThread			mediaThread;
  1684 	
  1685 	
  1686 	DOTEST((ret = TestMsgQueue.CreateLocal(gNumTestThreads * 10, EOwnerProcess)),
  1687 	       (KErrNone == ret));
  1688 
  1689 	DOTEST((ret = TestMultiSem.CreateLocal(1)),
  1690 	       (KErrNone == ret));
  1691 
  1692 	// make sure we have a priority higher than that of the threads we spawn...
  1693 	RThread thisThread;
  1694 	TThreadPriority savedThreadPriority = thisThread.Priority();
  1695 	const TThreadPriority KMainThreadPriority = EPriorityMuchMore;
  1696 	__ASSERT_COMPILE(KMainThreadPriority>TEST_INTERLEAVE_PRIO);
  1697 	thisThread.SetPriority(KMainThreadPriority);
  1698 
  1699 	SPerformTestArgs mediaArgs;
  1700 	mediaArgs.iMsgQueue = &TestMsgQueue; 
  1701 	mediaArgs.iTheSem = &TestMultiSem;
  1702 	mediaArgs.iLowMem = aLowMem;
  1703 	
  1704 	if (gTestMediaAccess)
  1705 		{
  1706 		TThreadCreateInfo mediaInfo(_L(""),PerformRomAndFileSystemAccess,KDefaultStackSize,(TAny*)&mediaArgs);
  1707 		mediaInfo.SetUseHeap(NULL);
  1708 		mediaInfo.SetPaging(TThreadCreateInfo::EPaged);
  1709 		gTestStopMedia = EFalse;
  1710 		ret = mediaThread.Create(mediaInfo);
  1711 		if (ret != KErrNone)
  1712 			return ret;
  1713 		mediaThread.Logon(mediaStatus);
  1714 		RUNTEST1(mediaStatus == KRequestPending);
  1715 		mediaThread.Resume();
  1716 		}
  1717 
  1718 	TThreadCreateInfo** infoPtrs = new TThreadCreateInfo*[gNumTestThreads]; 
  1719 	if (infoPtrs == NULL)
  1720 		return KErrNoMemory;
  1721 	
  1722 	SPerformTestArgs *testArgs = new SPerformTestArgs[gNumTestThreads];
  1723 	if (testArgs == NULL)
  1724 		return KErrNoMemory;
  1725 
  1726 	Mem::FillZ(testArgs, gNumTestThreads * sizeof(SPerformTestArgs));
  1727 
  1728 	for (index = 0; index < gNumTestThreads; index++)
  1729 		{
  1730 		RDBGD_PRINT(("%S : Starting thread.%d!\n", &gTestNameBuffer, index));
  1731 		multiThreadName = _L("TestThread_");
  1732 		multiThreadName.AppendNum(index);
  1733 
  1734 		testArgs[index].iThreadIndex = index;
  1735 		testArgs[index].iMsgQueue = &TestMsgQueue; 
  1736 		testArgs[index].iTheSem = &TestMultiSem;
  1737 		testArgs[index].iLowMem = aLowMem;
  1738 
  1739 		RDBGD_PRINT(("Creating thread.%d!\n", index));
  1740 		infoPtrs[index] = new TThreadCreateInfo(multiThreadName, MultipleTestThread, KDefaultStackSize, (TAny*)&testArgs[index]);
  1741 		if (infoPtrs[index] == NULL)
  1742 			continue;
  1743 		infoPtrs[index]->SetCreateHeap(KMinHeapSize, KMinHeapSize);
  1744 		infoPtrs[index]->SetPaging(TThreadCreateInfo::EPaged);
  1745 		//infoPtrs[index]->SetUseHeap(gThreadHeap);
  1746 		DOTEST((ret = pTheThreads[index].Create(*infoPtrs[index])), (ret != KErrNoMemory));
  1747 		if (ret != KErrNone)
  1748 			continue;
  1749 		pTheThreads[index].Resume();
  1750 		pThreadInUse[index] = 1;
  1751 		}
  1752 	
  1753 	// now process any messages sent from the child threads.
  1754 	TBool		anyUsed = ETrue;
  1755 	TBuf<64>	localBuffer;
  1756 	while(anyUsed)
  1757 		{
  1758 		anyUsed = EFalse;
  1759 		// check the message queue and call printf if we get a message.
  1760 		while (KErrNone == TestMsgQueue.Receive(localBuffer))
  1761 			{
  1762 			if (!TestSilent)
  1763 				test.Printf(localBuffer);
  1764 			}
  1765 
  1766 		// walk through the thread list to check which are still alive.
  1767 		for (index = 0; index < gNumTestThreads; index++)
  1768 			{
  1769 			if (pThreadInUse[index])
  1770 				{
  1771 				if (pTheThreads[index].ExitType() != EExitPending)
  1772 					{
  1773 					if (aLowMem &&
  1774 						pTheThreads[index].ExitType() == EExitKill &&
  1775 						pTheThreads[index].ExitReason() == KErrNoMemory &&
  1776 						Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE) == KErrNone)
  1777 						{// If thread was killed with no memory in a low mem scenario
  1778 						// then release some RAM and restart the thread again
  1779 						anyUsed = ETrue;
  1780 						RDBGD_PRINT(("Thread index %d EExitKill KErrNoMemory\n", index));
  1781 						CLOSE_AND_WAIT(pTheThreads[index]);
  1782 
  1783 						RDBGD_PRINT(("Re-running Thread index %d\n", index));
  1784 						rerunThreadName = _L("RRTestThread_");
  1785 						rerunThreadName.AppendNum(index);
  1786 						
  1787 						delete infoPtrs[index];				
  1788 						infoPtrs[index] = new TThreadCreateInfo(rerunThreadName, MultipleTestThread, KDefaultStackSize, (TAny*)&testArgs[index]);
  1789 						if (infoPtrs[index] == NULL)
  1790 							continue;
  1791 						infoPtrs[index]->SetCreateHeap(KMinHeapSize, KMinHeapSize);
  1792 						infoPtrs[index]->SetPaging(TThreadCreateInfo::EPaged);
  1793 						//infoPtrs[index]->SetUseHeap(gThreadHeap);
  1794 						ret = pTheThreads[index].Create(*infoPtrs[index]);
  1795 						if (ret != KErrNone)
  1796 							continue;
  1797 						pTheThreads[index].Resume();
  1798 						pThreadInUse[index] = 1;
  1799 						continue;
  1800 						}
  1801 					if (pTheThreads[index].ExitType() == EExitPanic)
  1802 						{
  1803 						RDBGD_PRINT(("%S : Thread Panic'd  %d...\n", &gTestNameBuffer, index));	
  1804 						}
  1805 					
  1806 					//Store the results but let all the threads finish
  1807 					gResultsArray[index].iExitType = pTheThreads[index].ExitType();
  1808 					gResultsArray[index].iExitReason = pTheThreads[index].ExitReason();
  1809 					
  1810 					pThreadInUse[index] = EFalse;
  1811 					pTheThreads[index].Close();
  1812 					}
  1813 				else
  1814 					{
  1815 					anyUsed = ETrue;
  1816 					}
  1817 				}
  1818 			}
  1819 
  1820 		User::AfterHighRes(50000);
  1821 		}
  1822 
  1823 	if (gTestMediaAccess)
  1824 		{
  1825 		gTestStopMedia = ETrue;
  1826 		RDBGD_PRINT(("%S : Waiting for media thread to exit...\n", &gTestNameBuffer));	
  1827 		User::WaitForRequest(mediaStatus);
  1828 		mediaThread.Close();
  1829 		}
  1830 
  1831 	TestMsgQueue.Close();
  1832 	TestMultiSem.Close();
  1833 
  1834 	// cleanup the resources and exit.
  1835 	User::Free(pTheThreads);
  1836 	User::Free(pThreadInUse);
  1837 	User::Free(pThreadCreateInfo);
  1838 	delete infoPtrs;
  1839 	delete testArgs;
  1840 
  1841 
  1842 	FinishFlushing(flushStatus, flushThread);
  1843 	gThreadHeap->Close();
  1844 	gStackHeap->Close();
  1845 	thisThread.SetPriority(savedThreadPriority);
  1846 	ret = CheckResults();
  1847 	RDBGS_PRINT(("Test Complete (%u ticks)\n", User::TickCount() - startTime));
  1848 	
  1849 	if (gIsDemandPaged)
  1850 		{
  1851 		// put the cache back to the the original values.
  1852 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)tempPages.iMinSize,(TAny*)tempPages.iMaxSize);
  1853 		}
  1854 	return ret;
  1855 	}
  1856 
  1857 
  1858 //
  1859 // DoSingleTest
  1860 // 
  1861 // Perform the single thread test,.
  1862 //
  1863 
  1864 LOCAL_C TInt DoSingleTest(TBool aLowMem = EFalse)
  1865 	{
  1866 	TUint origThreadCount = gNumTestThreads;
  1867 	gNumTestThreads = 1;
  1868 	TInt r = DoMultipleTest(aLowMem);
  1869 	gNumTestThreads = origThreadCount;
  1870 	return r;
  1871 	}
  1872 
  1873 
  1874 
  1875 //
  1876 // ParseCommandLine 
  1877 //
  1878 // read the arguments passed from the command line and set global variables to 
  1879 // control the tests.
  1880 //
  1881 
  1882 TBool ParseCommandLine()
  1883 	{
  1884 	TBuf<256> args;
  1885 	User::CommandLine(args);
  1886 	TLex	lex(args);
  1887 	TBool	retVal = ETrue;
  1888 	
  1889 	// initially test for arguments, the parse them, if not apply some sensible defaults.
  1890 	TBool	foundArgs = EFalse;	
  1891 	
  1892 	FOREVER
  1893 		{
  1894 		TPtrC  token=lex.NextToken();
  1895 		if(token.Length()!=0)
  1896 			{
  1897 			if ((token == _L("help")) || (token == _L("-h")) || (token == _L("-?")))
  1898 				{
  1899 				RDBGS_PRINT(("\nUsage:  %S n", &gTestNameBuffer));
  1900 				RDBGS_PRINT(("\ndebug: Prints out tracing in the test"));
  1901 				RDBGS_PRINT(("\n[single | multiple <numThreads>] : Specify to run in a single thread or multiple threads and how many"));
  1902 				RDBGS_PRINT(("\n[ipc | stack | chunk| commit| all | badserver] : which type of test to run "));
  1903 				RDBGS_PRINT(("\n-> ipc: IPC Pinning tests"));
  1904 				RDBGS_PRINT(("\n-> stack: Stack paging tests"));
  1905 				RDBGS_PRINT(("\n-> chunk: Chunk paging tests"));
  1906 				RDBGS_PRINT(("\n-> commit: Chunk committing tests"));
  1907 				RDBGS_PRINT(("\n-> all: All the above tests"));
  1908 				RDBGS_PRINT(("\n-> badserver: IPC Pinning tests with a dead server"));
  1909 				RDBGS_PRINT(("\n[iters <iters>] : Number of loops each test should perform"));
  1910 				RDBGS_PRINT(("\n[media] : Perform multiple test with media activity in the background"));
  1911 				RDBGS_PRINT(("\n[lowmem] : Perform testing in low memory situations "));
  1912 				RDBGS_PRINT(("\n[interleave]: Perform test with thread interleaving\n\n"));
  1913 				test.Getch();
  1914 				TestExit = ETrue;
  1915 				break;
  1916 				}
  1917 			else if (token == _L("debug"))
  1918 				{
  1919 				if (!TestSilent)
  1920 					{
  1921 					TestDebug = ETrue;
  1922 					gTestPrioChange = ETrue;
  1923 					}
  1924 				}
  1925 			else if (token == _L("silent"))
  1926 				{
  1927 				TestSilent = ETrue;
  1928 				TestDebug = EFalse;
  1929 				}
  1930 			else if (token == _L("single"))
  1931 				{
  1932 				gTestType = ETestSingle;
  1933 				}
  1934 			else if (token == _L("multiple"))
  1935 				{
  1936 				TPtrC val=lex.NextToken();
  1937 				TLex lexv(val);
  1938 				TInt value;
  1939 
  1940 				if (lexv.Val(value) == KErrNone)
  1941 					{
  1942 					if ((value <= 0) || (value > (TInt)KMaxTestThreads))
  1943 						{
  1944 						gNumTestThreads = KMaxTestThreads;
  1945 						}
  1946 					else
  1947 						{
  1948 						gNumTestThreads = value;
  1949 						}
  1950 					}
  1951 				else
  1952 					{
  1953 					RDBGS_PRINT(("Bad value for thread count '%S' was ignored.\n", &val));
  1954 					}
  1955 				gTestType = ETestMultiple;
  1956 				}
  1957 			else if (token == _L("prio"))
  1958 				{
  1959 				gTestPrioChange = !gTestPrioChange;
  1960 				}
  1961 			else if (token == _L("lowmem"))
  1962 				{
  1963 				gTestType = ETestLowMem;
  1964 				}
  1965 			else if (token == _L("media"))
  1966 				{
  1967 				gTestType = ETestMedia;
  1968 				}
  1969 			else if (token == _L("stack"))
  1970 				{
  1971 				gSetTests = TEST_STACK;
  1972 				}
  1973 			else if (token == _L("chunk"))
  1974 				{
  1975 				gSetTests = TEST_CHUNK;
  1976 				}
  1977 			else if (token == _L("commit"))
  1978 				{
  1979 				gTestType = ETestCommit;
  1980 				gSetTests = TEST_COMMIT;
  1981 				}
  1982 			else if (token == _L("ipc"))
  1983 				{
  1984 				gSetTests = TEST_IPC;
  1985 				}
  1986 			else if (token == _L("badserver"))
  1987 				{
  1988 				gTestType = ETestBadServer;
  1989 				}
  1990 			else if (token == _L("all"))
  1991 				{
  1992 				gSetTests = TEST_ALL;
  1993 				}
  1994 			else  if (token == _L("iters"))
  1995 				{
  1996 				TPtrC val=lex.NextToken();
  1997 				TLex lexv(val);
  1998 				TInt value;
  1999 
  2000 				if (lexv.Val(value) == KErrNone)
  2001 					{
  2002 					gPerformTestLoop = value;
  2003 					}
  2004 				else
  2005 					{
  2006 					RDBGS_PRINT(("Bad value for loop count '%S' was ignored.\n", &val));
  2007 					retVal = EFalse;
  2008 					break;
  2009 					}
  2010 				}
  2011 			else  if (token == _L("interleave"))
  2012 				{
  2013 				gTestType = ETestInterleave;
  2014 				}
  2015 			else
  2016 				{
  2017 				if ((foundArgs == EFalse) && (token.Length() == 1))
  2018 					{
  2019 					// Single letter argument...only run on 'd'
  2020 					if (token.CompareF(_L("d")) == 0)
  2021 						{
  2022 						break;
  2023 						}
  2024 					else
  2025 						{
  2026 						if (!TestSilent)
  2027 							{
  2028 							test.Title();
  2029 							test.Start(_L("Skipping non drive 'd' - Test Exiting."));
  2030 							test.End();
  2031 							}
  2032 						foundArgs = ETrue;
  2033 						TestExit = ETrue;
  2034 						break;
  2035 						}
  2036 					}
  2037 				RDBGS_PRINT(("Unknown argument '%S' was ignored.\n", &token));
  2038 				break;
  2039 				}
  2040 			foundArgs = ETrue;
  2041 			}
  2042 		else
  2043 			{
  2044 			break;
  2045 			}
  2046 		}
  2047 	if (!foundArgs)
  2048 		{
  2049 		retVal = EFalse;
  2050 		}
  2051 	return retVal;
  2052 	}
  2053 
  2054 //
  2055 // AreWeTheTestBase
  2056 //
  2057 // Test whether we are the root of the tests.
  2058 //
  2059 
  2060 void AreWeTheTestBase(void)
  2061 	{
  2062 	if (!TestSilent)
  2063 		{
  2064 		TFileName  filename(RProcess().FileName());
  2065 
  2066 		TParse	myParse;
  2067 		myParse.Set(filename, NULL, NULL);
  2068 		gTestNameBuffer.Zero();
  2069 		gTestNameBuffer.Append(myParse.Name());
  2070 		gTestNameBuffer.Append(_L(".exe"));
  2071 
  2072 		TestWeAreTheTestBase = !gTestNameBuffer.Compare(_L("t_wdpstress.exe"));
  2073 
  2074 		}
  2075 	else
  2076 		{
  2077 		gTestNameBuffer.Zero();
  2078 		gTestNameBuffer.Append(_L("t_wdpstress.exe"));
  2079 		}
  2080 	}
  2081 
  2082 //
  2083 // PerformAutoTest
  2084 //
  2085 // Perform the autotest
  2086 //
  2087 TInt PerformAutoTest()
  2088 	{
  2089 	TInt r = KErrNone;
  2090 
  2091 	// Run all the different types of test
  2092 	for (TUint testType = 0; testType < ETestTypes; testType++)
  2093 		{
  2094 		r = DoTest(testType);
  2095 		if (r != KErrNone)
  2096 			return r;
  2097 		}
  2098 
  2099 	return r;
  2100 	}
  2101 
  2102 //
  2103 // DoLowMemTest
  2104 //
  2105 // Low Memory Test
  2106 //
  2107 
  2108 TInt DoLowMemTest()
  2109 	{
  2110 	TInt r = User::LoadLogicalDevice(KPageStressTestLddName);
  2111 	RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
  2112 	RUNTEST(Ldd.Open(),KErrNone);
  2113 	
  2114 	SVMCacheInfo  tempPages;
  2115 	memset(&tempPages, 0, sizeof(tempPages));
  2116 
  2117 	if (gIsDemandPaged)
  2118 		{
  2119 		// get the old cache info
  2120 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
  2121 		TInt	minSize = 8 << gPageShift;
  2122 		TInt	maxSize = 256 << gPageShift;
  2123 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
  2124 		}
  2125 
  2126 
  2127 	// First load some pages onto the page cache 
  2128 	gPerformTestLoop = 1;
  2129 	r = DoTest(ETestSingle);
  2130 	test_KErrNone(r);
  2131 
  2132 
  2133 	Ldd.DoConsumeRamSetup(TEST_LM_NUM_FREE, TEST_LM_BLOCKSIZE);
  2134 	TEST_NEXT((_L("Single thread with Low memory.")));
  2135 	gNumTestThreads	= KMaxTestThreads / 2;
  2136 	gPerformTestLoop = 20;
  2137 
  2138 	r = DoTest(ETestSingle, ETrue);
  2139 	Ldd.DoConsumeRamFinish();
  2140 	test_KErrNone(r);
  2141 
  2142 	TEST_NEXT((_L("Multiple thread with Low memory.")));
  2143 	// First load some pages onto the page cache 
  2144 	gPerformTestLoop = 1;
  2145 	r = DoTest(ETestSingle);
  2146 	test_KErrNone(r);
  2147 
  2148 	Ldd.DoConsumeRamSetup(TEST_LM_NUM_FREE, TEST_LM_BLOCKSIZE);
  2149 	
  2150 	gPerformTestLoop = 10;
  2151 	gNumTestThreads	= KMaxTestThreads / 2;
  2152 	r = DoTest(ETestMultiple, ETrue);
  2153 	Ldd.DoConsumeRamFinish();
  2154 	test_KErrNone(r);
  2155 
  2156 	TEST_NEXT((_L("Multiple thread with Low memory, with starting free ram.")));
  2157 	// First load some pages onto the page cache 
  2158 	gPerformTestLoop = 1;
  2159 	r = DoTest(ETestSingle);
  2160 	test_KErrNone(r);
  2161 
  2162 	Ldd.DoConsumeRamSetup(32, TEST_LM_BLOCKSIZE);
  2163 	
  2164 	gPerformTestLoop = 10;
  2165 	gNumTestThreads	= KMaxTestThreads / 2;
  2166 	r = DoTest(ETestMultiple, ETrue);
  2167 	Ldd.DoConsumeRamFinish();
  2168 	test_KErrNone(r);
  2169 
  2170 	TEST_NEXT((_L("Close test driver")));
  2171 	Ldd.Close();
  2172 	RUNTEST(User::FreeLogicalDevice(KPageStressTestLddName), KErrNone);
  2173 	if (gIsDemandPaged)
  2174 		{
  2175 		TInt minSize = tempPages.iMinSize;
  2176 		TInt maxSize = tempPages.iMaxSize;
  2177 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
  2178 		}
  2179 
  2180 	return r;
  2181 	}
  2182 
  2183 void RestoreDefaults()
  2184 	{
  2185 	gPerformTestLoop			= 10;					
  2186 	gNumTestThreads				= KMaxTestThreads;	
  2187 
  2188 	gTestInterleave				= EFalse;
  2189 	
  2190 	gTestWhichTests				= gSetTests;
  2191 	gTestPrioChange				= EFalse;
  2192 	gTestStopMedia				= EFalse;
  2193 	gTestMediaAccess			= EFalse;
  2194 	}
  2195 
  2196 
  2197 
  2198 TInt DoTest(TInt gTestType, TBool aLowMem)
  2199 	{
  2200 	TInt r = KErrNone;
  2201 	
  2202 	switch(gTestType)
  2203 		{
  2204 		case ETestSingle:
  2205 			TEST_NEXT((_L("Single thread")));
  2206 			r = DoSingleTest(aLowMem);
  2207 			break;
  2208 
  2209 		case ETestMultiple:
  2210 			TEST_NEXT((_L("Multiple thread")));
  2211 			
  2212 			r = DoMultipleTest(aLowMem);
  2213 			break;
  2214 
  2215 		case ETestLowMem:
  2216 			TEST_NEXT((_L("Low Memory Tests")));
  2217 			r = DoLowMemTest();
  2218 			break;
  2219 
  2220 		case ETestMedia:
  2221 			TEST_NEXT((_L("Background Media Activity Tests")));
  2222 			gTestMediaAccess = ETrue;
  2223 			gPerformTestLoop = 2;					
  2224 			gNumTestThreads	= KMaxTestThreads / 2;	
  2225 			r = DoMultipleTest(aLowMem);
  2226 			break;
  2227 
  2228 		case ETestCommit:
  2229 			TEST_NEXT((_L("Committing and Decommitting Tests")));	
  2230 			gTestWhichTests = TEST_COMMIT;
  2231 			r = DoSingleTest(aLowMem);
  2232 			break;
  2233 
  2234 		case ETestInterleave:
  2235 			TEST_NEXT((_L("Testing multiple with thread interleaving")));
  2236 			gTestInterleave = ETrue;
  2237 			r = DoMultipleTest(aLowMem);
  2238 			break;
  2239 
  2240 		case ETestBadServer:
  2241 			TEST_NEXT((_L("Testing multiple with thread interleaving")));
  2242 			gTestBadServer = ETrue;
  2243 			gTestWhichTests = TEST_IPC;
  2244 			r = DoSingleTest(aLowMem);
  2245 			break;
  2246 
  2247 
  2248 		}
  2249 	RestoreDefaults();
  2250 	return r;
  2251 	}
  2252 //
  2253 // E32Main
  2254 //
  2255 // Main entry point.
  2256 //
  2257 
  2258 TInt E32Main()
  2259 	{
  2260 #ifndef TEST_ON_UNPAGED
  2261 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
  2262 	if(!romHeader->iPageableRomStart)
  2263 		{
  2264 		gIsDemandPaged = EFalse;
  2265 		}
  2266 #endif
  2267 	TUint start = User::TickCount();
  2268 	
  2269 	gResultsArray = (SThreadExitResults *)User::AllocZ(sizeof(SThreadExitResults) * KMaxTestThreads);
  2270 	if (gResultsArray == NULL)
  2271 		return KErrNoMemory;
  2272 
  2273 	AreWeTheTestBase();
  2274 	RestoreDefaults();
  2275 
  2276 	TBool parseResult = ParseCommandLine();
  2277 
  2278 	if (TestExit)
  2279 		{
  2280 		return KErrNone;
  2281 		}
  2282 
  2283 	// Retrieve the page size and use it to detemine the page shift (assumes 32-bit system).
  2284 	TInt r = HAL::Get(HAL::EMemoryPageSize, gPageSize);
  2285 	if (r != KErrNone)
  2286 		{
  2287 		RDBGS_PRINT(("Cannot obtain the page size\n"));
  2288 		return r;
  2289 		}
  2290 	else
  2291 		{
  2292 		RDBGS_PRINT(("page size = %d\n", gPageSize));
  2293 		}
  2294 
  2295 
  2296 	TUint32 pageMask = gPageSize;
  2297 	TUint i = 0;
  2298 	for (; i < 32; i++)
  2299 		{
  2300 		if (pageMask & 1)
  2301 			{
  2302 			if (pageMask & ~1u)
  2303 				{
  2304 				test.Printf(_L("ERROR - page size not a power of 2"));
  2305 				return KErrNotSupported;
  2306 				}
  2307 			gPageShift = i;
  2308 			break;
  2309 			}
  2310 		pageMask >>= 1;
  2311 		}
  2312 
  2313 	TInt  minSize = 8 << gPageShift;
  2314 	TInt  maxSize = 64 << gPageShift; 
  2315 	SVMCacheInfo  tempPages;
  2316 	memset(&tempPages, 0, sizeof(tempPages));
  2317 	if (gIsDemandPaged)
  2318 		{
  2319 		// get the old cache info
  2320 		UserSvr::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0);
  2321 		// set the cache to our test value
  2322 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
  2323 		}
  2324 
  2325 
  2326 	if (!TestSilent)
  2327 		{
  2328 		test.Title();
  2329 		test.Start(_L("Writable Data Paging stress tests..."));
  2330 		test.Printf(_L("%S\n"), &gTestNameBuffer);
  2331 		}
  2332 
  2333 	if (parseResult)
  2334 		{
  2335 		if (!TestSilent)
  2336 			{
  2337 			extern TInt *CheckLdmiaInstr(void);
  2338 			test.Printf(_L("%S : CheckLdmiaInstr\n"), &gTestNameBuffer);
  2339 			TInt   *theAddr = CheckLdmiaInstr();
  2340 			test.Printf(_L("%S : CheckLdmiaInstr complete 0x%x...\n"), &gTestNameBuffer, (TInt)theAddr);
  2341 			}
  2342 		
  2343 		if (gTestType < 0 || gTestType >= ETestTypeEnd)
  2344 			{
  2345 			r = PerformAutoTest();
  2346 			test_KErrNone(r);
  2347 			}
  2348 		else
  2349 			{
  2350 			r = DoTest(gTestType);
  2351 			test_KErrNone(r);
  2352 			}
  2353 		}
  2354 	else
  2355 		{
  2356 		r = PerformAutoTest();
  2357 		test_KErrNone(r);
  2358 		}
  2359 
  2360 	if (gIsDemandPaged)
  2361 		{
  2362 		minSize = tempPages.iMinSize;
  2363 		maxSize = tempPages.iMaxSize;
  2364 		// put the cache back to the the original values.
  2365 		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
  2366 		}
  2367 
  2368 	if (!TestSilent)
  2369 		{
  2370 		test.Printf(_L("%S : Complete (%u ticks)\n"), &gTestNameBuffer, User::TickCount() - start);	
  2371 		test.End();
  2372 		}
  2373 
  2374 	User::Free(gResultsArray);
  2375 	gResultsArray = NULL;
  2376 	
  2377 	return 0;
  2378 	}
  2379 
  2380