First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32test\demandpaging\t_wdpstress.cpp
15 // Data Paging Stress Tests
16 // Common command lines:
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
36 //! @SYMTestCaseID KBASE-T_WDPSTRESS-xxx
39 //! @SYMTestCaseDesc Writable Data Paging Stress Tests
41 //! @SYMTestExpectedResults All tests should pass.
42 //! @SYMTestPriority High
43 //! @SYMTestStatus Implemented
44 //----------------------------------------------------------------------------------------------
46 #define __E32TEST_EXTENSION__
49 RTest test(_L("T_WDPSTRESS"));
57 #include <e32msgqueue.h>
64 #define TEST_ON_UNPAGED
67 #include "t_pagestress.h"
69 TBool TestDebug = EFalse;
70 TBool TestSilent = EFalse;
71 TBool TestExit = EFalse;
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
78 #define TEST_INTERLEAVE_PRIO EPriorityMore
80 TBool TestWeAreTheTestBase = EFalse;
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)
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;
98 #define TEST_LM_NUM_FREE 0
99 #define TEST_LM_BLOCKSIZE 1
100 #define TEST_LM_BLOCKS_FREE 4
102 RPageStressTestLdd Ldd;
103 RSemaphore TestMultiSem;
104 RMsgQueue<TBuf <64> > TestMsgQueue;
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
110 TInt gPageSize; // The number of bytes per page
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;
117 TInt gTestType = -1; // The type of test that is to be performed
119 #define TEST_NEXT(__args) \
123 #define RDBGD_PRINT(__args)\
125 RDebug::Printf __args ;\
127 #define RDBGS_PRINT(__args)\
129 RDebug::Printf __args ;\
131 #define DEBUG_PRINT(__args)\
134 if (aTestArguments.iMsgQueue && aTestArguments.iBuffer && aTestArguments.iTheSem)\
136 aTestArguments.iBuffer->Zero();\
137 aTestArguments.iBuffer->Format __args ;\
138 aTestArguments.iTheSem->Wait();\
139 aTestArguments.iMsgQueue->SendBlocking(*aTestArguments.iBuffer);\
140 aTestArguments.iTheSem->Signal();\
144 test.Printf __args ;\
148 #define RUNTEST(__test, __error)\
150 test(__test == __error);\
154 #define RUNTEST1(__test)\
158 #define DEBUG_PRINT1(__args)\
164 #define DOTEST(__operation, __condition)\
168 while (!__condition)\
170 Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
173 RUNTEST1(__condition);\
178 RUNTEST1(__condition);\
181 #define DOTEST1(__operation, __condition)\
182 if (aTestArguments.iLowMem) \
185 while (!__condition)\
187 Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE);\
190 RUNTEST1(__condition);\
195 RUNTEST1(__condition);\
198 struct SThreadExitResults
203 SThreadExitResults* gResultsArray;
204 const TInt KExitTypeReset = -1;
206 struct SPerformTestArgs
209 RMsgQueue<TBuf <64> > *iMsgQueue;
217 TInt DoTest(TInt gTestType, TBool aLowMem = EFalse);
227 // This is at the moment manual
234 // wait for any async cleanup in the supervisor to finish first...
235 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
237 TMemoryInfoV1Buf meminfo;
238 TInt r = UserHal::MemoryInfo(meminfo);
240 return meminfo().iFreeRamInBytes;
243 const TUint KStackSize = 20 * 4096;
244 TUint stackLimit = 150;//*** NEED TO WORK OUT HOW MUCH STACK WE HAVE***
249 void CallRecFunc(TUint aNum, TInt aThreadIndex)
251 RDBGD_PRINT(("ThreadId %d CallRecFunc, aNum = %d\n", aThreadIndex, aNum));
252 if (aNum >= stackLimit)
253 {// To avoid a stack overflow
258 CallRecFunc(++aNum, aThreadIndex);
261 RDBGD_PRINT(("ThreadId %d CRF(%d)Returning...", aThreadIndex, aNum));
266 Thread that calls a recursive function
268 TInt ThreadFunc(TAny* aThreadIndex)
270 for (TUint i=0; i<1; i++)
272 CallRecFunc(0, (TInt)aThreadIndex);
274 RDBGD_PRINT(("ThreadId %d ThreadFunc Returning...", (TInt)aThreadIndex));
279 Thread continuously flushes the paging cache
281 TInt FlushFunc(TAny* /*aPtr*/)
283 RThread().SetPriority(EPriorityMore);
286 DPTest::FlushCache();
287 User::After((Math::Random()&0xfff)*10);
296 // Create a paged thread which calls a recursive function.
297 // Calls to function will be placed on the stack, which is data paged
300 TInt TestStackPaging(SPerformTestArgs& aTestArguments)
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);
314 r = testThread.Create(threadCreateInfo);
315 if(r != KErrNoMemory)
317 if(!aTestArguments.iLowMem)
319 if(Ldd.DoReleaseSomeRam(TEST_LM_BLOCKS_FREE) != KErrNone)
321 RDBGD_PRINT(("TestStackPaging released some RAM\n"));
324 RDBGD_PRINT(("TID(%d) TestStackPaging create r = %d freeRam = %d\n", aTestArguments.iThreadIndex, r, FreeRam()));
328 TRequestStatus threadStatus;
329 testThread.Logon(threadStatus);
331 RDBGD_PRINT(("resuming test thread"));
334 RDBGD_PRINT(("waiting for threadstatus"));
335 User::WaitForRequest(threadStatus);
337 RDBGD_PRINT(("Killing threads\n"));
343 //--------------------------Server Pinning stuff-----------------------------------------------------
344 _LIT(KTestServer,"CTestServer");
345 const TUint KSemServer = 0;
347 class CTestServer : public CServer2
350 CTestServer(TInt aPriority);
352 //override the pure virtual functions:
353 virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
357 class CTestSession : public CSession2
367 //Override pure virtual
368 IMPORT_C virtual void ServiceL(const RMessage2& aMessage);
370 TInt ReadWrite(const RMessage2& aMessage, TBool aRead, TBool aWrite);
375 class CMyActiveScheduler : public CActiveScheduler
378 virtual void Error(TInt anError) const; //override pure virtual error function
382 class RSession : public RSessionBase
385 TInt PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr)
387 return (SendReceive(aFunction, aPtr));
389 TInt PublicCreateSession(const TDesC& aServer,TInt aMessageSlots)
391 return (CreateSession(aServer,User::Version(),aMessageSlots));
398 RSemaphore iSemArray;
401 SServerArgs gServerArgsArray[KMaxTestThreads];
403 CTestServer::CTestServer(TInt aPriority)
405 // Constructor - sets name
407 : CServer2(aPriority)
410 CSession2* CTestServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
412 // Virtual fn - checks version supported and creates a CTestSession
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);
424 TInt CTestSession::ReadWrite(const RMessage2& aMessage, TBool aRead, TBool aWrite)
427 for (TUint argIndex = 0; argIndex < 4; argIndex++)
429 // Get the length of the descriptor and verify it is as expected.
430 TInt length = aMessage.GetDesLength(argIndex);
431 if (length < KErrNone)
433 RDebug::Printf(" Error getting descriptor length %d", length);
440 // Now read the descriptor
441 HBufC8* des = HBufC8::New(length);
444 TPtr8 desPtr = des->Des();
445 r = aMessage.Read(argIndex, desPtr);
451 //TODO: Verify the descriptor
457 // Now write to the maximum length of the descriptor.
459 HBufC8* argTmp = HBufC8::New(max);
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);
478 void CTestSession::ServiceL(const RMessage2& aMessage)
480 // Virtual message-handler
484 iClientDied = EFalse;
485 switch (aMessage.Function())
488 RDBGD_PRINT(("Stopping server"));
489 CActiveScheduler::Stop();
493 r = ReadWrite(aMessage, ETrue, EFalse);
496 r = ReadWrite(aMessage, EFalse, ETrue);
499 r = ReadWrite(aMessage, ETrue, ETrue);
503 r = KErrNotSupported;
506 aMessage.Complete(r);
508 // If descriptors aren't as expected then panic so the test will fail.
510 User::Panic(_L("ServiceL failure"), r);
513 // CTestSession funtions
515 void CMyActiveScheduler::Error(TInt anError) const
517 // Virtual error handler
520 User::Panic(_L("CMyActiveScheduer::Error"), anError);
524 TInt ServerThread(TAny* aThreadIndex)
526 // Passed as the server thread in 2 tests - sets up and runs CTestServer
529 RDBGD_PRINT(("ServerThread"));
530 TUint threadIndex = (TUint)aThreadIndex;
533 serverName = _L("ServerName_");
534 serverName.AppendNum(threadIndex);
537 CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
538 if (pScheduler == NULL)
540 gServerArgsArray[threadIndex].iBadServer = ETrue;
541 gServerArgsArray[threadIndex].iSemArray.Signal();
545 CActiveScheduler::Install(pScheduler);
547 CTestServer* pServer = new CTestServer(0);
550 gServerArgsArray[threadIndex].iBadServer = ETrue;
551 gServerArgsArray[threadIndex].iSemArray.Signal();
556 //Starting a CServer2 also Adds it to the ActiveScheduler
557 TInt r = pServer->Start(serverName);
560 gServerArgsArray[threadIndex].iBadServer = ETrue;
561 gServerArgsArray[threadIndex].iSemArray.Signal();
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();
578 TInt BadServerThread(TAny* /*aThreadIndex*/)
580 // Passed as the server thread in 2 tests - sets up and runs CTestServer
583 RDBGD_PRINT(("BadServerThread"));
584 CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
585 if (pScheduler == NULL)
587 RDBGD_PRINT(("BST:Fail1"));
588 gServerArgsArray[KSemServer].iBadServer = ETrue;
589 gServerArgsArray[KSemServer].iSemArray.Signal();
593 CActiveScheduler::Install(pScheduler);
595 CTestServer* pServer = new CTestServer(0);
598 RDBGD_PRINT(("BST:Fail2"));
599 gServerArgsArray[KSemServer].iBadServer = ETrue;
600 gServerArgsArray[KSemServer].iSemArray.Signal();
605 //pServer->SetPinClientDescriptors(ETrue);
608 //Starting a CServer2 also Adds it to the ActiveScheduler
609 TInt r = pServer->Start(KTestServer);
612 RDBGD_PRINT(("BST:Fail3"));
613 gServerArgsArray[KSemServer].iBadServer = ETrue;
614 gServerArgsArray[KSemServer].iSemArray.Signal();
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();
627 RDBGD_PRINT(("BST:Pass1"));
631 TInt SendMessages(TUint aIters, TUint aSize, TDesC& aServerName, TInt aIndex, TBool aLowMem = EFalse)
633 // Passed as the first client thread - signals the server to do several tests
641 DOTEST((argTmp1 = HBufC8::New(aSize)), (argTmp1 != NULL));
642 *argTmp1 = (const TUint8*)"argTmp1";
643 TPtr8 ptr1 = argTmp1->Des();
645 DOTEST((argTmp2 = HBufC8::New(aSize)), (argTmp2 != NULL));
646 *argTmp2 = (const TUint8*)"argTmp2";
647 TPtr8 ptr2 = argTmp2->Des();
649 DOTEST((argTmp3 = HBufC8::New(aSize)), (argTmp3 != NULL));
650 *argTmp3 = (const TUint8*)"argTmp3";
651 TPtr8 ptr3 = argTmp3->Des();
653 DOTEST((argTmp4 = HBufC8::New(aSize)), (argTmp1 != NULL));
654 *argTmp4 = (const TUint8*)"argTmp4";
655 TPtr8 ptr4 = argTmp4->Des();
660 {//Don't do bad server tests with lowmem
661 r = session.PublicCreateSession(aServerName,5);
665 DOTEST((r = session.PublicCreateSession(aServerName,5)), (r != KErrNoMemory));
669 RDBGD_PRINT(("SendMessages[%d] failed to create session r = %d", aIndex, r));
675 RThread::Rendezvous(KErrNone);
676 RDBGD_PRINT(("Wait on sem %d", aIndex));
677 //gServerArgsArray[KSemCliSessStarted].iSemArray.Wait();
680 RDBGD_PRINT(("ID (%d)ReadWrite" ,aIndex));
681 for (TUint i = 0; i < aIters; i++)
683 TUint mode = (i&0x3) + CTestSession::ERead;
686 case CTestSession::ERead:
687 DOTEST((r = session.PublicSendReceive(CTestSession::ERead, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())),
688 (r != KErrNoMemory));
693 case CTestSession::EWrite:
694 DOTEST((r = session.PublicSendReceive(CTestSession::EWrite, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())),
695 (r != KErrNoMemory));
699 case CTestSession::EReadWrite:
700 DOTEST((r = session.PublicSendReceive(CTestSession::EReadWrite, TIpcArgs(&ptr1, &ptr2, &ptr3, &ptr4).PinArgs())),
701 (r != KErrNoMemory));
708 RDBGD_PRINT(("ID(%d) Closing session", aIndex));
713 TInt TestIPCPinning(SPerformTestArgs& aTestArguments)
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);
723 gServerArgsArray[aTestArguments.iThreadIndex].iBadServer = EFalse;
725 // Create the semaphores for the IPC pinning tests
726 DOTEST1((r = gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.CreateLocal(0)), (r != KErrNoMemory));
729 RDBGD_PRINT(("Failed to create semaphonre[%d] r = %d", aTestArguments.iThreadIndex, r));
733 RThread serverThread;
735 DOTEST1((r1 = serverThread.Create(serverInfo)), (r1 != KErrNoMemory));
738 RDBGD_PRINT(("Failed to create server thread[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
741 TRequestStatus serverStat;
742 serverThread.Logon(serverStat);
743 serverThread.Resume();
745 // Wait for the server to start and then create a session to it.
747 serverName = _L("ServerName_");
748 serverName.AppendNum(aTestArguments.iThreadIndex);
750 gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.Wait();
752 // First check that the server started successfully
753 if (gServerArgsArray[aTestArguments.iThreadIndex].iBadServer)
754 return KErrServerTerminated;
757 DOTEST1((r1 = session.PublicCreateSession(serverName,5)), (r1 != KErrNoMemory));
760 RDBGD_PRINT(("Failed to create session[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
764 r1 = SendMessages(50, 10, serverName, aTestArguments.iThreadIndex, aTestArguments.iLowMem);
767 RDBGD_PRINT(("SendMessages[%d] r1 = %d", aTestArguments.iThreadIndex, r1));
772 // Signal to stop ActiveScheduler and wait for server to stop.
773 session.PublicSendReceive(CTestSession::EStop, TIpcArgs());
776 User::WaitForRequest(serverStat);
777 if (serverThread.ExitType() == EExitKill &&
778 serverThread.ExitReason() != KErrNone)
780 r2 = serverThread.ExitReason();
782 if (serverThread.ExitType() != EExitKill)
784 RDBGD_PRINT(("Server thread panic'd"));
788 serverThread.Close();
789 gServerArgsArray[aTestArguments.iThreadIndex].iSemArray.Close();
797 TInt ClientThread(TAny* aClientThread)
802 serverName = KTestServer;
803 RDBGD_PRINT(("CT(%d):Sending Messages" ,aClientThread));
804 r = SendMessages(500, 10, serverName, (TInt) aClientThread);
807 RDBGD_PRINT(("SendMessages[%d] r = %d", (TInt) aClientThread, r));
813 TInt TestIPCBadServer(SPerformTestArgs& aTestArguments)
815 TInt cliRet = KErrNone;
816 TInt serRet = KErrNone;
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);
824 // Create the semaphores for the IPC pinning tests
825 DOTEST1((serRet = gServerArgsArray[KSemServer].iSemArray.CreateLocal(0)), (serRet != KErrNoMemory));
826 if (serRet != KErrNone)
828 RDBGD_PRINT(("Failed to create semaphonre[%d] serRet = %d", KSemServer, serRet));
832 RThread serverThread;
833 DOTEST1((serRet = serverThread.Create(serverInfo)), (serRet != KErrNoMemory));
834 if (serRet != KErrNone)
836 RDBGD_PRINT(("Failed to create server thread serRet = %d", serRet));
839 TRequestStatus serverStat;
840 serverThread.Logon(serverStat);
841 serverThread.Resume();
843 // Wait for the server to start and then create a session to it.
844 gServerArgsArray[KSemServer].iSemArray.Wait();
846 // First check that the server started successfully
847 if (gServerArgsArray[KSemServer].iBadServer)
848 return KErrServerTerminated;
851 //create client threads
852 const TUint KNumClientThreads = 50;
853 RThread clientThreads[KNumClientThreads];
854 TRequestStatus clientStarted[KNumClientThreads];
855 TRequestStatus clientStats[KNumClientThreads];
857 // Create the client threads
858 TBuf<16> clientThreadName;
860 for (i = 0; i < KNumClientThreads; i++)
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)
870 RDBGD_PRINT(("Failed to create client thread [%d] cliRet = %d", i, cliRet));
873 clientThreads[i].Rendezvous(clientStarted[i]);
874 clientThreads[i].Logon(clientStats[i]);
875 clientThreads[i].Resume();
878 // Wait for creation of the client thread sessions
879 for (i = 0; i < KNumClientThreads; i++)
881 User::WaitForRequest(clientStarted[i]);
882 if (clientStarted[i].Int() != KErrNone)
883 return clientStarted[i].Int();
887 // Once the messages are being sent, create a session to the
888 // same server and signal to stop ActiveScheduler
890 serRet = session.PublicCreateSession(KTestServer,5);
891 if (serRet != KErrNone)
893 RDBGD_PRINT(("Failed to create session serRet = %d", serRet));
896 session.PublicSendReceive(CTestSession::EStop, TIpcArgs());
899 // Wait for the client thread to end.
901 for (i = 0; i < KNumClientThreads; i++)
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)
908 cliRet = clientStats[i].Int();
912 // Check that the server ended correctly
914 User::WaitForRequest(serverStat);
915 if (serverThread.ExitType() == EExitKill &&
916 serverThread.ExitReason() != KErrNone)
918 serRet = serverThread.ExitReason();
920 if (serverThread.ExitType() != EExitKill)
922 RDBGD_PRINT(("Server thread panic'd"));
923 serRet = KErrGeneral;
926 // Close all the server thread and client threads
927 for (i = 0; i < KNumClientThreads; i++)
929 clientThreads[i].Close();
931 serverThread.Close();
933 if (cliRet != KErrNone)
943 // Remove ALL chunks allocated
945 // @param aChunkArray The array that stores a reference to the chunks created.
946 // @param aChunkArraySize The size of aChunkArray.
948 void RemoveChunkAlloc(RChunk*& aChunkArray, TUint aChunkArraySize)
950 if (aChunkArray == NULL)
951 {// The chunk array has already been deleted.
955 for (TUint i = 0; i < aChunkArraySize; i++)
957 if (aChunkArray[i].Handle() != NULL)
959 aChunkArray[i].Close();
961 if (gChunksAllocd < gMaxChunks)
962 gMaxChunksReached = EFalse;
965 delete[] aChunkArray;
969 TInt WriteToChunk(RChunk* aChunkArray, TUint aChunkArraySize)
971 for (TUint j = 0; j < aChunkArraySize; j++)
973 if (aChunkArray[j].Handle() != NULL)
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++)
979 *base++ = k; // write index to the chunk
986 TUint32 ReadByte(volatile TUint32* aPtr)
991 TInt ReadChunk(RChunk* aChunkArray, TUint aChunkArraySize)
993 for (TUint j=0; j < aChunkArraySize; j++) //Read all open chunks
995 if (aChunkArray[j].Handle() != NULL)
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++)
1001 TUint value = ReadByte((volatile TUint32*)base++);
1004 RDBGS_PRINT(("Read value incorrect expected 0x%x got 0x%x", k, value));
1014 TInt CreateChunks(SPerformTestArgs& aTestArguments, RChunk*& aChunkArray, TUint aChunkArraySize)
1018 TUint chunkSize = 1 << gPageShift;
1020 // Allocate as many chunks as is specified, either with the default chunk size or a specified chunk size
1021 if (aChunkArray == NULL)
1023 DOTEST1((aChunkArray = new RChunk[aChunkArraySize]), (aChunkArray != NULL));
1024 if (aChunkArray == NULL)
1025 return KErrNoMemory;
1028 TChunkCreateInfo createInfo;
1029 createInfo.SetNormal(chunkSize, chunkSize);
1030 createInfo.SetPaging(TChunkCreateInfo::EPaged);
1033 // Create chunks for each RChunk with a NULL handle.
1034 for (TUint i = 0; i < aChunkArraySize; i++)
1036 DOTEST1((r = aChunkArray[i].Create(createInfo)), (r != KErrNoMemory));
1039 if (r == KErrOverflow)
1041 gMaxChunks = gChunksAllocd;
1042 RDBGD_PRINT(("Max Chunks Allowed = %d", gMaxChunks));
1043 gMaxChunksReached = ETrue;
1048 RDBGD_PRINT(("TID(%d) aChunkArray[%d], r = %d", aTestArguments.iThreadIndex, i, r));
1050 RDBGD_PRINT(("TID(%d) created chunks r = %d", aTestArguments.iThreadIndex, r));
1057 // Create a number of chunks and write to them
1058 // read the chunk back to ensure the values are correct
1061 TInt TestChunkPaging(SPerformTestArgs& aTestArguments)
1064 const TUint KNumChunks = 10;
1067 if(gMaxChunksReached)
1068 {// We cant create any more chunks as the max number has been reached
1072 RChunk* chunkArray = NULL;
1073 r = CreateChunks(aTestArguments, chunkArray, KNumChunks);
1076 if (r == KErrOverflow)
1078 RDBGD_PRINT(("Max number of chunks reached"));
1079 RemoveChunkAlloc(chunkArray, KNumChunks);
1082 RDBGD_PRINT(("TID(%d) CreateChunks r = %d", aTestArguments.iThreadIndex, r));
1086 r = WriteToChunk(chunkArray, KNumChunks);
1089 RemoveChunkAlloc(chunkArray, KNumChunks);
1090 RDBGD_PRINT(("TID(%d) WriteToChunk r = %d", aTestArguments.iThreadIndex, r));
1094 r = ReadChunk(chunkArray, KNumChunks);
1097 RemoveChunkAlloc(chunkArray, KNumChunks);
1098 RDBGD_PRINT(("TID(%d) ReadChunk r = %d", aTestArguments.iThreadIndex, r));
1101 RemoveChunkAlloc(chunkArray, KNumChunks);
1110 // commit a page at a time, write to that page and then decommit the page
1113 TInt TestChunkCommit(SPerformTestArgs& aTestArguments)
1118 TUint chunkSize = 70 << gPageShift;
1120 TChunkCreateInfo createInfo;
1121 createInfo.SetDisconnected(0, 0, chunkSize);
1122 createInfo.SetPaging(TChunkCreateInfo::EPaged);
1123 DOTEST1((r = testChunk.Create(createInfo)), (r != KErrNoMemory));
1129 while(offset < chunkSize)
1132 DOTEST1((r = testChunk.Commit(offset,gPageSize)), (r != KErrNoMemory));
1138 // Write to the page
1139 TUint8* pageStart = testChunk.Base() + offset;
1143 // Decommit the page
1144 r = testChunk.Decommit(offset, gPageSize);
1150 offset += gPageSize;
1159 // PerformTestThread
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.
1168 LOCAL_C TInt PerformTestThread(SPerformTestArgs& aTestArguments)
1171 TUint start = User::TickCount();
1173 DEBUG_PRINT1((_L("%S : thread Starting %d\n"), &gTestNameBuffer, aTestArguments.iThreadIndex));
1174 // now select how we do the test...
1178 if (TEST_ALL == (gTestWhichTests & TEST_ALL))
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;
1190 for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
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 ++)
1196 DEBUG_PRINT1((_L("whichOrder = %d\n"), whichOrder));
1197 switch (order[selOrder][whichOrder])
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));
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));
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));
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));
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)
1237 r = TestIPCPinning(aTestArguments);
1238 DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCPinning() r = %d\n"), aTestArguments.iThreadIndex, r));
1244 default: // this is really an error.
1253 if (gTestWhichTests & TEST_STACK)
1255 for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
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));
1265 if (gTestWhichTests & TEST_CHUNK)
1267 for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
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));
1277 if (gTestWhichTests & TEST_COMMIT)
1279 for (iterIndex = 0; iterIndex < gPerformTestLoop; iterIndex ++)
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));
1289 if (gTestWhichTests & TEST_IPC)
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 ++)
1297 r = TestIPCBadServer(aTestArguments);
1298 DEBUG_PRINT1((_L("ThreadId %d Finished TestIPCBadServer() r = %d\n"), aTestArguments.iThreadIndex, r));
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));
1312 DEBUG_PRINT1((_L("%S : thread Exiting %d (tickcount %u)\n"), &gTestNameBuffer, aTestArguments.iThreadIndex, (User::TickCount() - start)));
1318 // MultipleTestThread
1320 // Thread function, one created for each thread in a multiple thread test.
1323 LOCAL_C TInt MultipleTestThread(TAny* aTestArgs)
1326 TBuf<64> localBuffer;
1328 if (gTestInterleave)
1331 thisThread.SetPriority((TThreadPriority) TEST_INTERLEAVE_PRIO);
1334 SPerformTestArgs& testArgs = *(SPerformTestArgs*)aTestArgs;
1335 testArgs.iBuffer = &localBuffer;
1337 RDBGD_PRINT(("Performing test thread ThreadID(%d)\n", testArgs.iThreadIndex));
1338 r = PerformTestThread(testArgs);
1346 // FindMMCDriveNumber
1348 // Find the first read write drive.
1351 TInt FindMMCDriveNumber(RFs& aFs)
1353 TDriveInfo driveInfo;
1354 for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
1356 TInt r = aFs.Drive(driveInfo, drvNum);
1359 if (driveInfo.iType == EMediaHardDisk)
1367 // PerformRomAndFileSystemAccess
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.
1373 TInt PerformRomAndFileSystemAccessThread(SPerformTestArgs& aTestArguments)
1375 TUint maxBytes = KMaxTUint;
1376 TInt startTime = User::TickCount();
1380 if (KErrNone != fs.Connect())
1382 DEBUG_PRINT(_L("PerformRomAndFileSystemAccessThread : Can't connect to the FS\n"));
1386 // get info about the ROM...
1387 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
1390 if(romHeader->iPageableRomStart)
1392 start = (TUint8*)romHeader + romHeader->iPageableRomStart;
1393 end = start + romHeader->iPageableRomSize;
1397 start = (TUint8*)romHeader;
1398 end = start + romHeader->iUncompressedSize;
1403 // read all ROM pages in a random order...and write out to file in ROFs,
1404 TUint size = end - start - gPageSize;
1412 //TInt drvNum = TestBootedFromMmc ? FindMMCDriveNumber(fs) : FindFsNANDDrive(fs);
1413 TInt drvNum = FindMMCDriveNumber(fs);
1414 TBuf<32> filename = _L("d:\\Pageldrtst.tmp");
1417 filename[0] = (TUint16)('a' + drvNum);
1418 DEBUG_PRINT1((_L("%S : Filename %S\n"), &gTestNameBuffer, &filename));
1421 DEBUG_PRINT((_L("PerformRomAndFileSystemAccessThread : error getting drive num\n")));
1423 for(TInt i = (size >> gPageShift); i > 0; --i)
1425 DEBUG_PRINT1((_L("%S : Opening the file\n"), &gTestNameBuffer));
1426 if (KErrNone != file.Replace(fs, filename, EFileWrite))
1428 DEBUG_PRINT1((_L("%S : Opening the file Failed!\n"), &gTestNameBuffer));
1431 random = random * 69069 + 1;
1432 theAddr = (TUint8*)(start+((TInt64(random)*TInt64(size))>>32));
1433 if (theAddr + gPageSize > end)
1435 DEBUG_PRINT1((_L("%S : address is past the end 0x%x / 0x%x\n"), &gTestNameBuffer, (TInt)theAddr, (TInt)end));
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)
1442 DEBUG_PRINT1((_L("%S : Write returned error %d\n"), &gTestNameBuffer, ret));
1444 DEBUG_PRINT1((_L("%S : Closing the file\n"), &gTestNameBuffer));
1447 DEBUG_PRINT1((_L("%S : Deleting the file\n"), &gTestNameBuffer));
1448 ret = fs.Delete(filename);
1449 if (KErrNone != ret)
1451 DEBUG_PRINT1((_L("%S : Delete returned error %d\n"), &gTestNameBuffer, ret));
1457 DEBUG_PRINT1((_L("Done in %d ticks\n"), User::TickCount() - startTime));
1463 // PerformRomAndFileSystemAccess
1465 // Thread function, kicks off the file system access.
1468 LOCAL_C TInt PerformRomAndFileSystemAccess(TAny* aTestArgs)
1470 TBuf<64> localBuffer;
1472 SPerformTestArgs& testArgs = *(SPerformTestArgs*)aTestArgs;
1473 testArgs.iBuffer = &localBuffer;
1475 PerformRomAndFileSystemAccessThread(testArgs);
1486 // Create a thread that will continuously flush the paging cache
1488 void StartFlushing(TRequestStatus &aStatus, RThread &aFlushThread, TBool aLowMem = EFalse)
1491 gTestRunning = ETrue;
1493 TThreadCreateInfo flushThreadInfo(_L("FlushThread"), FlushFunc, KDefaultStackSize,NULL);
1494 flushThreadInfo.SetCreateHeap(KMinHeapSize, KMinHeapSize);
1498 test_KErrNone(aFlushThread.Create(flushThreadInfo));
1502 DOTEST((ret = aFlushThread.Create(flushThreadInfo)), (ret != KErrNoMemory));
1507 aFlushThread.Logon(aStatus);
1509 aFlushThread.Resume();
1515 // Close the thread flushing the paging cache
1517 void FinishFlushing(TRequestStatus &aStatus, RThread &aFlushThread)
1519 gTestRunning = EFalse;
1520 User::WaitForRequest(aStatus);
1521 // TO DO: Check Exit tyoe
1522 CLOSE_AND_WAIT(aFlushThread);
1529 // Clear the previous results from the results array
1533 for (TUint i = 0; i < KMaxTestThreads; i++)
1535 gResultsArray[i].iExitType = KExitTypeReset;
1536 gResultsArray[i].iExitReason = KErrNone;
1545 // Check that the results are as expected
1550 for (i = 0; i < KMaxTestThreads; i++)
1552 if (gResultsArray[i].iExitType == KExitTypeReset)
1554 RDBGD_PRINT(("%S : Thread %d ExitType(%d) ExitReason(%d)...\n",
1555 &gTestNameBuffer, i, gResultsArray[i].iExitType, gResultsArray[i].iExitReason));
1558 for (i = 0; i < KMaxTestThreads; i++)
1560 if (gResultsArray[i].iExitType == KExitTypeReset)
1563 if (gResultsArray[i].iExitType != EExitKill)
1565 RDBGS_PRINT(("Thread %d ExitType(%d) Expected(%d)\n", i, gResultsArray[i].iExitType, EExitKill));
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)
1575 RDBGS_PRINT(("Thread %d ExitReason(%d) Expected either %d, %d or %d\n",
1576 i, gResultsArray[i].iExitReason, KErrNone, KErrNoMemory, KErrOverflow));
1587 // Print out the options of the test
1591 SVMCacheInfo tempPages;
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);
1599 test.Printf(_L("Loops (%d), Threads (%d), Tests: "), gPerformTestLoop, gNumTestThreads);
1600 if (TEST_ALL == (gTestWhichTests & TEST_ALL))
1602 test.Printf(_L("All, "));
1604 else if (gTestWhichTests & TEST_STACK)
1606 test.Printf(_L("Stack, "));
1608 else if (gTestWhichTests & TEST_CHUNK)
1610 test.Printf(_L("Chunk, "));
1612 else if (gTestWhichTests & TEST_COMMIT)
1614 test.Printf(_L("Commit, "));
1616 else if (gTestWhichTests & TEST_IPC)
1618 test.Printf(_L("IPC Pinning, "));
1622 test.Printf(_L("?, "));
1624 test.Printf(_L("\nOptions: "));
1627 test.Printf(_L("Interleave "));
1629 test.Printf(_L("Priority "));
1630 if(gTestMediaAccess)
1631 test.Printf(_L("Media"));
1633 test.Printf(_L("BadServer"));
1634 test.Printf(_L("\n"));
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.
1644 TInt DoMultipleTest(TBool aLowMem = EFalse)
1646 SVMCacheInfo tempPages;
1647 memset(&tempPages, 0, sizeof(tempPages));
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));
1660 TUint startTime = User::TickCount();
1662 TInt ret = KErrNone;
1663 TBuf<16> multiThreadName;
1664 TBuf<16> rerunThreadName;
1668 TRequestStatus flushStatus;
1669 RThread flushThread;
1670 StartFlushing(flushStatus, flushThread, aLowMem);
1672 DOTEST((gThreadHeap = User::ChunkHeap(NULL, 0x1000, 0x1000)), (gThreadHeap != NULL));
1673 test_NotNull(gThreadHeap);
1675 DOTEST((gStackHeap = User::ChunkHeap(NULL, 0x1000, 0x1000)), (gStackHeap != NULL));
1676 test_NotNull(gStackHeap);
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);
1682 TRequestStatus mediaStatus;
1683 RThread mediaThread;
1686 DOTEST((ret = TestMsgQueue.CreateLocal(gNumTestThreads * 10, EOwnerProcess)),
1689 DOTEST((ret = TestMultiSem.CreateLocal(1)),
1692 // make sure we have a priority higher than that of the threads we spawn...
1694 TThreadPriority savedThreadPriority = thisThread.Priority();
1695 const TThreadPriority KMainThreadPriority = EPriorityMuchMore;
1696 __ASSERT_COMPILE(KMainThreadPriority>TEST_INTERLEAVE_PRIO);
1697 thisThread.SetPriority(KMainThreadPriority);
1699 SPerformTestArgs mediaArgs;
1700 mediaArgs.iMsgQueue = &TestMsgQueue;
1701 mediaArgs.iTheSem = &TestMultiSem;
1702 mediaArgs.iLowMem = aLowMem;
1704 if (gTestMediaAccess)
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)
1713 mediaThread.Logon(mediaStatus);
1714 RUNTEST1(mediaStatus == KRequestPending);
1715 mediaThread.Resume();
1718 TThreadCreateInfo** infoPtrs = new TThreadCreateInfo*[gNumTestThreads];
1719 if (infoPtrs == NULL)
1720 return KErrNoMemory;
1722 SPerformTestArgs *testArgs = new SPerformTestArgs[gNumTestThreads];
1723 if (testArgs == NULL)
1724 return KErrNoMemory;
1726 Mem::FillZ(testArgs, gNumTestThreads * sizeof(SPerformTestArgs));
1728 for (index = 0; index < gNumTestThreads; index++)
1730 RDBGD_PRINT(("%S : Starting thread.%d!\n", &gTestNameBuffer, index));
1731 multiThreadName = _L("TestThread_");
1732 multiThreadName.AppendNum(index);
1734 testArgs[index].iThreadIndex = index;
1735 testArgs[index].iMsgQueue = &TestMsgQueue;
1736 testArgs[index].iTheSem = &TestMultiSem;
1737 testArgs[index].iLowMem = aLowMem;
1739 RDBGD_PRINT(("Creating thread.%d!\n", index));
1740 infoPtrs[index] = new TThreadCreateInfo(multiThreadName, MultipleTestThread, KDefaultStackSize, (TAny*)&testArgs[index]);
1741 if (infoPtrs[index] == NULL)
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)
1749 pTheThreads[index].Resume();
1750 pThreadInUse[index] = 1;
1753 // now process any messages sent from the child threads.
1754 TBool anyUsed = ETrue;
1755 TBuf<64> localBuffer;
1759 // check the message queue and call printf if we get a message.
1760 while (KErrNone == TestMsgQueue.Receive(localBuffer))
1763 test.Printf(localBuffer);
1766 // walk through the thread list to check which are still alive.
1767 for (index = 0; index < gNumTestThreads; index++)
1769 if (pThreadInUse[index])
1771 if (pTheThreads[index].ExitType() != EExitPending)
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
1780 RDBGD_PRINT(("Thread index %d EExitKill KErrNoMemory\n", index));
1781 CLOSE_AND_WAIT(pTheThreads[index]);
1783 RDBGD_PRINT(("Re-running Thread index %d\n", index));
1784 rerunThreadName = _L("RRTestThread_");
1785 rerunThreadName.AppendNum(index);
1787 delete infoPtrs[index];
1788 infoPtrs[index] = new TThreadCreateInfo(rerunThreadName, MultipleTestThread, KDefaultStackSize, (TAny*)&testArgs[index]);
1789 if (infoPtrs[index] == NULL)
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)
1797 pTheThreads[index].Resume();
1798 pThreadInUse[index] = 1;
1801 if (pTheThreads[index].ExitType() == EExitPanic)
1803 RDBGD_PRINT(("%S : Thread Panic'd %d...\n", &gTestNameBuffer, index));
1806 //Store the results but let all the threads finish
1807 gResultsArray[index].iExitType = pTheThreads[index].ExitType();
1808 gResultsArray[index].iExitReason = pTheThreads[index].ExitReason();
1810 pThreadInUse[index] = EFalse;
1811 pTheThreads[index].Close();
1820 User::AfterHighRes(50000);
1823 if (gTestMediaAccess)
1825 gTestStopMedia = ETrue;
1826 RDBGD_PRINT(("%S : Waiting for media thread to exit...\n", &gTestNameBuffer));
1827 User::WaitForRequest(mediaStatus);
1828 mediaThread.Close();
1831 TestMsgQueue.Close();
1832 TestMultiSem.Close();
1834 // cleanup the resources and exit.
1835 User::Free(pTheThreads);
1836 User::Free(pThreadInUse);
1837 User::Free(pThreadCreateInfo);
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));
1851 // put the cache back to the the original values.
1852 UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)tempPages.iMinSize,(TAny*)tempPages.iMaxSize);
1861 // Perform the single thread test,.
1864 LOCAL_C TInt DoSingleTest(TBool aLowMem = EFalse)
1866 TUint origThreadCount = gNumTestThreads;
1867 gNumTestThreads = 1;
1868 TInt r = DoMultipleTest(aLowMem);
1869 gNumTestThreads = origThreadCount;
1878 // read the arguments passed from the command line and set global variables to
1879 // control the tests.
1882 TBool ParseCommandLine()
1885 User::CommandLine(args);
1887 TBool retVal = ETrue;
1889 // initially test for arguments, the parse them, if not apply some sensible defaults.
1890 TBool foundArgs = EFalse;
1894 TPtrC token=lex.NextToken();
1895 if(token.Length()!=0)
1897 if ((token == _L("help")) || (token == _L("-h")) || (token == _L("-?")))
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"));
1917 else if (token == _L("debug"))
1922 gTestPrioChange = ETrue;
1925 else if (token == _L("silent"))
1930 else if (token == _L("single"))
1932 gTestType = ETestSingle;
1934 else if (token == _L("multiple"))
1936 TPtrC val=lex.NextToken();
1940 if (lexv.Val(value) == KErrNone)
1942 if ((value <= 0) || (value > (TInt)KMaxTestThreads))
1944 gNumTestThreads = KMaxTestThreads;
1948 gNumTestThreads = value;
1953 RDBGS_PRINT(("Bad value for thread count '%S' was ignored.\n", &val));
1955 gTestType = ETestMultiple;
1957 else if (token == _L("prio"))
1959 gTestPrioChange = !gTestPrioChange;
1961 else if (token == _L("lowmem"))
1963 gTestType = ETestLowMem;
1965 else if (token == _L("media"))
1967 gTestType = ETestMedia;
1969 else if (token == _L("stack"))
1971 gSetTests = TEST_STACK;
1973 else if (token == _L("chunk"))
1975 gSetTests = TEST_CHUNK;
1977 else if (token == _L("commit"))
1979 gTestType = ETestCommit;
1980 gSetTests = TEST_COMMIT;
1982 else if (token == _L("ipc"))
1984 gSetTests = TEST_IPC;
1986 else if (token == _L("badserver"))
1988 gTestType = ETestBadServer;
1990 else if (token == _L("all"))
1992 gSetTests = TEST_ALL;
1994 else if (token == _L("iters"))
1996 TPtrC val=lex.NextToken();
2000 if (lexv.Val(value) == KErrNone)
2002 gPerformTestLoop = value;
2006 RDBGS_PRINT(("Bad value for loop count '%S' was ignored.\n", &val));
2011 else if (token == _L("interleave"))
2013 gTestType = ETestInterleave;
2017 if ((foundArgs == EFalse) && (token.Length() == 1))
2019 // Single letter argument...only run on 'd'
2020 if (token.CompareF(_L("d")) == 0)
2029 test.Start(_L("Skipping non drive 'd' - Test Exiting."));
2037 RDBGS_PRINT(("Unknown argument '%S' was ignored.\n", &token));
2057 // Test whether we are the root of the tests.
2060 void AreWeTheTestBase(void)
2064 TFileName filename(RProcess().FileName());
2067 myParse.Set(filename, NULL, NULL);
2068 gTestNameBuffer.Zero();
2069 gTestNameBuffer.Append(myParse.Name());
2070 gTestNameBuffer.Append(_L(".exe"));
2072 TestWeAreTheTestBase = !gTestNameBuffer.Compare(_L("t_wdpstress.exe"));
2077 gTestNameBuffer.Zero();
2078 gTestNameBuffer.Append(_L("t_wdpstress.exe"));
2085 // Perform the autotest
2087 TInt PerformAutoTest()
2091 // Run all the different types of test
2092 for (TUint testType = 0; testType < ETestTypes; testType++)
2094 r = DoTest(testType);
2110 TInt r = User::LoadLogicalDevice(KPageStressTestLddName);
2111 RUNTEST1(r==KErrNone || r==KErrAlreadyExists);
2112 RUNTEST(Ldd.Open(),KErrNone);
2114 SVMCacheInfo tempPages;
2115 memset(&tempPages, 0, sizeof(tempPages));
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);
2127 // First load some pages onto the page cache
2128 gPerformTestLoop = 1;
2129 r = DoTest(ETestSingle);
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;
2138 r = DoTest(ETestSingle, ETrue);
2139 Ldd.DoConsumeRamFinish();
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);
2148 Ldd.DoConsumeRamSetup(TEST_LM_NUM_FREE, TEST_LM_BLOCKSIZE);
2150 gPerformTestLoop = 10;
2151 gNumTestThreads = KMaxTestThreads / 2;
2152 r = DoTest(ETestMultiple, ETrue);
2153 Ldd.DoConsumeRamFinish();
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);
2162 Ldd.DoConsumeRamSetup(32, TEST_LM_BLOCKSIZE);
2164 gPerformTestLoop = 10;
2165 gNumTestThreads = KMaxTestThreads / 2;
2166 r = DoTest(ETestMultiple, ETrue);
2167 Ldd.DoConsumeRamFinish();
2170 TEST_NEXT((_L("Close test driver")));
2172 RUNTEST(User::FreeLogicalDevice(KPageStressTestLddName), KErrNone);
2175 TInt minSize = tempPages.iMinSize;
2176 TInt maxSize = tempPages.iMaxSize;
2177 UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize,(TAny*)minSize,(TAny*)maxSize);
2183 void RestoreDefaults()
2185 gPerformTestLoop = 10;
2186 gNumTestThreads = KMaxTestThreads;
2188 gTestInterleave = EFalse;
2190 gTestWhichTests = gSetTests;
2191 gTestPrioChange = EFalse;
2192 gTestStopMedia = EFalse;
2193 gTestMediaAccess = EFalse;
2198 TInt DoTest(TInt gTestType, TBool aLowMem)
2205 TEST_NEXT((_L("Single thread")));
2206 r = DoSingleTest(aLowMem);
2210 TEST_NEXT((_L("Multiple thread")));
2212 r = DoMultipleTest(aLowMem);
2216 TEST_NEXT((_L("Low Memory Tests")));
2221 TEST_NEXT((_L("Background Media Activity Tests")));
2222 gTestMediaAccess = ETrue;
2223 gPerformTestLoop = 2;
2224 gNumTestThreads = KMaxTestThreads / 2;
2225 r = DoMultipleTest(aLowMem);
2229 TEST_NEXT((_L("Committing and Decommitting Tests")));
2230 gTestWhichTests = TEST_COMMIT;
2231 r = DoSingleTest(aLowMem);
2234 case ETestInterleave:
2235 TEST_NEXT((_L("Testing multiple with thread interleaving")));
2236 gTestInterleave = ETrue;
2237 r = DoMultipleTest(aLowMem);
2240 case ETestBadServer:
2241 TEST_NEXT((_L("Testing multiple with thread interleaving")));
2242 gTestBadServer = ETrue;
2243 gTestWhichTests = TEST_IPC;
2244 r = DoSingleTest(aLowMem);
2255 // Main entry point.
2260 #ifndef TEST_ON_UNPAGED
2261 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
2262 if(!romHeader->iPageableRomStart)
2264 gIsDemandPaged = EFalse;
2267 TUint start = User::TickCount();
2269 gResultsArray = (SThreadExitResults *)User::AllocZ(sizeof(SThreadExitResults) * KMaxTestThreads);
2270 if (gResultsArray == NULL)
2271 return KErrNoMemory;
2276 TBool parseResult = ParseCommandLine();
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);
2287 RDBGS_PRINT(("Cannot obtain the page size\n"));
2292 RDBGS_PRINT(("page size = %d\n", gPageSize));
2296 TUint32 pageMask = gPageSize;
2304 test.Printf(_L("ERROR - page size not a power of 2"));
2305 return KErrNotSupported;
2313 TInt minSize = 8 << gPageShift;
2314 TInt maxSize = 64 << gPageShift;
2315 SVMCacheInfo tempPages;
2316 memset(&tempPages, 0, sizeof(tempPages));
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);
2329 test.Start(_L("Writable Data Paging stress tests..."));
2330 test.Printf(_L("%S\n"), &gTestNameBuffer);
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);
2343 if (gTestType < 0 || gTestType >= ETestTypeEnd)
2345 r = PerformAutoTest();
2350 r = DoTest(gTestType);
2356 r = PerformAutoTest();
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);
2370 test.Printf(_L("%S : Complete (%u ticks)\n"), &gTestNameBuffer, User::TickCount() - start);
2374 User::Free(gResultsArray);
2375 gResultsArray = NULL;