os/kernelhwsrv/kerneltest/e32test/smpsoak/t_smpsoak.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\smpsoak\t_smpsoak.cpp
    15 
    16 //  User Includes
    17 #include <e32hal.h>
    18 #include "t_smpsoak.h"
    19 
    20 void ParseCommandLine ();
    21 
    22 // Global Variables
    23 static TInt gPageSize;
    24 //Timeout 2 Minutes
    25 static TUint gTimeout = 120;
    26 
    27 //class for smpsoak thread and it creates memory, device, timer and spin threads.
    28 class CSMPSoakThread
    29 	{
    30 public:
    31 	CSMPSoakThread();
    32 	~CSMPSoakThread();
    33 	void CreateThread();
    34 	void ResumeThread();
    35 	void CreateChildProcess(TInt aIndex);
    36 	void ResumeChildProcess();
    37 	void TerminateChildProcess();	
    38 private:
    39     //Thread Functions
    40 	static TInt SMPStressMemoryThread(TAny*);
    41 	static TInt SMPStressDeviceThread(TAny*);
    42 	static TInt SMPStressTimerThread(TAny*);
    43 	static TInt SMPStressSpinThread(TAny*);
    44 	//Thread Priority
    45 	void DoCreateThread(TAny*);
    46 	void SetThreadPriority();
    47 private:
    48     //Utils for memory thread
    49 	void CreateChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
    50 	void CommitChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
    51 	void WriteReadChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
    52 private:
    53     //Memebers for threads 
    54     TInt DoSMPStressMemoryThread();
    55     TInt DoSMPStressDeviceThread();
    56     TInt DoSMPStressTimerThread();
    57     TInt DoSMPStressSpinThread();
    58 private:
    59     TThreadData iThreadData;
    60     RProcess    iProcess;
    61     RThread     iThread;
    62     TInt        iPriority;
    63 private:
    64 // Thread Data for each thread- low priority
    65 static TThread KThreadTableLow[];
    66 // Thread Data for each thread- high priority
    67 static TThread KThreadTableHigh[];
    68 //Process Data for each process
    69 static const TProcess KProcessTable[];
    70 //Memory table for memory thread
    71 static const TMemory KMemoryTable[];
    72 //Device table for device thread
    73 static const TDesC* KDeviceTable[];
    74 
    75 	};
    76 TThread CSMPSoakThread::KThreadTableLow[] =
    77     {
    78         { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow,   EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
    79 		{ _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
    80 		{ _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal,   EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
    81 		{ _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow,   EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
    82 		{ _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal,   EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
    83 		{ _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal,   EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
    84 		{ _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
    85     };
    86 TThread CSMPSoakThread::KThreadTableHigh[] =
    87  {
    88         { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow,   EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
    89         { _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
    90         { _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal,   EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
    91         { _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow,   EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
    92         { _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal,   EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
    93         { _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal,   EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
    94         { _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
    95     };
    96 const TProcess CSMPSoakThread::KProcessTable[] =
    97     {
    98         { _L("t_smpsoakprocess.exe"), _L("-W"), KCpuAffinityAny},
    99         { _L("t_smpsoakprocess.exe"), _L("-R"), KCpuAffinityAny},
   100         { _L("t_smpsoakprocess.exe"), _L("-F"), KCpuAffinityAny},
   101         { _L("t_smpsoakprocess.exe"), _L("-T"), KCpuAffinityAny},
   102         { _L("t_smpsoakprocess.exe"), _L("-O"), KCpuAffinityAny},
   103     };
   104 const TMemory CSMPSoakThread::KMemoryTable[] =
   105     {
   106         {_L(""), EChunkNormalThread, 0, 10, 100 },
   107         {_L("Global Chunk 1"), EChunkNormalThread, 0, 20, 200 },
   108         {_L(""), EChunkDisconnectedThread, 3, 30, 300 },
   109         {_L("Global Chunk 2"), EChunkDisconnectedThread, 4, 40, 400 },
   110         {_L(""), EChunkDoubleEndedThread, 5, 50, 500 },
   111         {_L("Global Chunk 3"), EChunkDoubleEndedThread, 6, 60, 600 },
   112         {_L(""), EChunkNormalProcess, 0, 10, 100 },
   113         {_L("Global Chunk 4"), EChunkNormalProcess, 0, 20, 200 },
   114         {_L(""), EChunkDisconnectedProcess, 3, 30, 300 },
   115         {_L("Global Chunk 5"), EChunkDisconnectedProcess, 4, 40, 400 },
   116         {_L(""), EChunkDoubleEndedProcess, 5, 50, 500 },
   117         {_L("Global Chunk 6"), EChunkDoubleEndedProcess, 6, 60, 600 },
   118         {_L(""), EChunkNone, 0, 0, 0 },
   119     };
   120 const TDesC* CSMPSoakThread::KDeviceTable[] =
   121     {
   122     &KDevices, &KDevLdd1, &KDevLdd1Name, &KDevLdd2, &KDevLdd2Name, &KDevLdd3, &KDevLdd3Name,
   123     &KDevLdd4, &KDevLdd4Name, &KDevLdd5, &KDevLdd5Name, NULL
   124     };
   125 
   126 //Constructor
   127 CSMPSoakThread::CSMPSoakThread()
   128     { 
   129     }
   130 //Destructor
   131 CSMPSoakThread::~CSMPSoakThread()
   132     {    
   133     }
   134 //All child process creation
   135 void CSMPSoakThread::CreateChildProcess(TInt aIndex)
   136     {
   137     if(TestSilent)  
   138             gCmdLine.Format(KCmdLineBackground,(KProcessTable[aIndex].operation).Ptr());
   139     else if (Period)
   140         gCmdLine.Format(KCmdLinePeriod,gPeriod,(KProcessTable[aIndex].operation).Ptr());
   141     else
   142         gCmdLine.Format(KCmdLineProcess,(KProcessTable[aIndex].operation).Ptr());
   143     
   144     TInt r = iProcess.Create(KProcessTable[aIndex].processFileName,gCmdLine);
   145     test_KErrNone(r);
   146     iProcess.SetPriority(EPriorityLow);
   147     gSMPStressDrv.ChangeThreadAffinity(&iThread, KProcessTable[aIndex].cpuAffinity);
   148     PRINT ((_L("SetProcessPriority  CPU %d Priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iProcess.Priority()));
   149     }
   150 //Terminate process when user press "Esc key"
   151 void CSMPSoakThread::ResumeChildProcess()
   152     {
   153     iProcess.Resume();
   154     }
   155 //Terminate process when user press "Esc key"
   156 void CSMPSoakThread::TerminateChildProcess()
   157     {
   158     iProcess.Kill(KErrNone);
   159     }
   160 //Changes the thread priority each time time, for each thread by Random, Increment, from List, Fixed.
   161 //pick up the priority option from thread table
   162 void CSMPSoakThread::SetThreadPriority()
   163     {
   164     static TInt64 randSeed = KRandSeed;
   165     static const TThreadPriority priorityTable[]=
   166         {
   167         EPriorityMuchLess, EPriorityLess, EPriorityNormal, EPriorityMore, EPriorityMuchMore,
   168         EPriorityRealTime, EPriorityRealTime, EPriorityAbsoluteVeryLow, EPriorityAbsoluteLowNormal,
   169         EPriorityAbsoluteLow, EPriorityAbsoluteBackgroundNormal, EPriorityAbsoluteBackground,
   170         EPriorityAbsoluteForegroundNormal, EPriorityAbsoluteForeground, EPriorityAbsoluteHighNormal, EPriorityAbsoluteHigh
   171         };
   172     TInt priorityIndex = 0;
   173     switch (iThreadData.threadPriorityChange)
   174         {
   175         case EpriorityFixed:
   176             break;
   177 
   178         case EPriorityList:
   179             if (++iPriority >= KPriorityOrder)
   180                 iPriority = 0;
   181             if (iThreadData.threadPriorities[iPriority] == 0)
   182                 iPriority = 0;
   183           //  PRINT(_L("SetPriority List CPU %d index %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread),iPriority, iThreadData.threadPriorities[iPriority]);
   184             iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[iPriority]);
   185             break;
   186 
   187         case EPriorityIncrement:
   188             while (priorityTable[priorityIndex] <= iPriority)
   189                 {
   190                 priorityIndex++;
   191                 }
   192             iPriority = priorityTable[priorityIndex];
   193             if (iPriority > iThreadData.threadPriorities[2])
   194                 iPriority = iThreadData.threadPriorities[1];
   195           //  PRINT(_L("SetPriority Increment CPU %d iPriority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
   196             iThread.SetPriority((TThreadPriority)iPriority);
   197             break;
   198 
   199         case EPriorityRandom:
   200             iPriority = Math::Rand(randSeed) % (iThreadData.threadPriorities[2] - iThreadData.threadPriorities[1] + 1);
   201             iPriority += iThreadData.threadPriorities[1];
   202             while (priorityTable[priorityIndex] < iPriority)
   203                 {
   204                 priorityIndex++;
   205                 }
   206             iPriority = priorityTable[priorityIndex];
   207          //   PRINT(_L("SetPriority Random CPU %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
   208             iThread.SetPriority((TThreadPriority)iPriority);
   209             break;
   210         }
   211     }
   212 //Resume each thread
   213 void CSMPSoakThread::ResumeThread()
   214     {
   215     iThread.Resume();
   216     }
   217 //thread creation
   218 void CSMPSoakThread::CreateThread()
   219     {
   220     CSMPSoakThread* smpthread = new CSMPSoakThread[KNumThreads];
   221     for (TInt i = 0; i < KNumThreads ; i++)
   222         {
   223         if(ThreadPriorityLow)
   224             {
   225             PRINT ((_L("Thread Table - Priority Low \n")));
   226             smpthread[i].DoCreateThread(&KThreadTableLow[i]);
   227             }
   228         else
   229             {
   230             PRINT ((_L("Thread Table - Priority High \n")));
   231             smpthread[i].DoCreateThread(&KThreadTableHigh[i]);
   232             }
   233         }
   234     PRINT (_L("Resuming all threads\n"));
   235     for (TInt i = 0; i < KNumThreads; i++)
   236            smpthread[i].ResumeThread();
   237     }
   238 /**
   239  * CSMPSoakThread Thread Creation.
   240  * @param aIndex to exercise each row(thread) in the thread table          
   241  *
   242  * @return  N/A
   243  *
   244  * @pre     Initialize thread Table values
   245  * @post    None
   246  */
   247 void CSMPSoakThread::DoCreateThread(TAny* aThread)
   248     {
   249     //Initialize each thread data
   250        iThreadData = ((TThread*)aThread)->threadData;
   251        test.Next(_L("Create Thread"));
   252        PRINT ((_L("%s   CPU affinity %d  Priority %d\n"),((TThread*)aThread)->threadName.Ptr(),iThreadData.cpuAffinity,iThreadData.threadPriorities[0]));
   253        TInt r = iThread.Create(((TThread*)aThread)->threadName, ((TThread*)aThread)->threadFunction, KDefaultStackSize, KHeapMinSize, KHeapMaxSize,(TAny*)this);
   254        test_KErrNone(r);
   255        if (iThreadData.threadPriorityChange == EPriorityList)
   256            {
   257            iPriority = 0;
   258            }
   259        else
   260            {
   261            iPriority = iThreadData.threadPriorities[0];
   262            }
   263        iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[0]);
   264        //Set the thread CPU Affinity
   265        gSMPStressDrv.ChangeThreadAffinity(&iThread, iThreadData.cpuAffinity);
   266       }
   267 //Create Chunk - different types 
   268 void CSMPSoakThread::CreateChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
   269 	{
   270 	//RDebug::Print(_L("Creating chunk name %s type %d bottom %d top %d max %d\n"),aMemoryTablePtr->globalChunkName.Ptr(),aMemoryTablePtr->chunkType,aMemoryTablePtr->initialBottom,aMemoryTablePtr->initialTop,aMemoryTablePtr->maxSize);
   271 	TOwnerType ownerType = EOwnerProcess;
   272 	aChunkInfo->lastBottom = aMemoryTablePtr->initialBottom;
   273 	aChunkInfo->lastTop = aMemoryTablePtr->initialTop;
   274 	switch (aMemoryTablePtr->chunkType)
   275 		{
   276 		case EChunkNormalThread:
   277 			ownerType = EOwnerThread;			// drop through to create chunk
   278 		case EChunkNormalProcess:
   279 			if (aMemoryTablePtr->globalChunkName.Length())
   280 				{
   281 				test_KErrNone(aChunkInfo->chunk.CreateGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   282 				}
   283 			else
   284 				{
   285 				test_KErrNone(aChunkInfo->chunk.CreateLocal(aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   286 				}
   287 			aChunkInfo->lastBottom = 0;			// ensure that this is zero
   288 			break;
   289 
   290 		case EChunkDisconnectedThread:
   291 			ownerType = EOwnerThread;			// drop through to create chunk
   292 		case EChunkDisconnectedProcess:
   293 			if (aMemoryTablePtr->globalChunkName.Length())
   294 				{
   295 				test_KErrNone(aChunkInfo->chunk.CreateDisconnectedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   296 				}
   297 			else
   298 				{
   299 				test_KErrNone(aChunkInfo->chunk.CreateDisconnectedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   300 				}
   301 			break;
   302 
   303 		case EChunkDoubleEndedThread:
   304 			ownerType = EOwnerThread;			// drop through to create chunk
   305 		case EChunkDoubleEndedProcess:
   306 			if (aMemoryTablePtr->globalChunkName.Length())
   307 				{
   308 				test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   309 				}
   310 			else
   311 				{
   312 				test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
   313 				}
   314 			break;
   315 		}
   316 	}
   317 //Commit chunk
   318 void CSMPSoakThread::CommitChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
   319 	{
   320 	TInt commitPages;
   321 
   322 	switch (aMemoryTablePtr->chunkType)
   323 		{
   324 		case EChunkNormalThread:
   325 		case EChunkNormalProcess:
   326 			if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
   327 				{
   328 				aChunkInfo->lastTop += (aMemoryTablePtr->maxSize - 1 - aChunkInfo->lastTop) / 2 + 1;
   329 				//PRINT(_L("Adjust chunk memory - top %d pagesize %d\n"),aChunkInfo->lastTop,gPageSize);
   330 				test_KErrNone(aChunkInfo->chunk.Adjust(aChunkInfo->lastTop*gPageSize));
   331 				}
   332 			break;
   333 
   334 		case EChunkDisconnectedThread:
   335 		case EChunkDisconnectedProcess:
   336 			commitPages = ((aChunkInfo->lastTop - aChunkInfo->lastBottom) / 2) + 1;
   337 			//PRINT(_L("Decommitting from bottom %d of %d pages\n"),aChunkInfo->lastBottom,commitPages);
   338 			test_KErrNone(aChunkInfo->chunk.Decommit(aChunkInfo->lastBottom*gPageSize,commitPages * gPageSize));
   339 			if ((aChunkInfo->lastBottom > 0) && (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop))
   340 				{
   341 				aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
   342 				aChunkInfo->lastBottom /= 2;
   343 				commitPages = aChunkInfo->lastTop - aChunkInfo->lastBottom + 1;
   344 				}
   345 			else
   346 				{
   347 				if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize -1))
   348 					{
   349 					if (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop)
   350 						{
   351 						aChunkInfo->lastBottom = aMemoryTablePtr->initialTop + 1;
   352 						}
   353 					else
   354 						{
   355 						aChunkInfo->lastBottom = aChunkInfo->lastTop + 1;
   356 						}
   357 					commitPages = ((aMemoryTablePtr->maxSize - aChunkInfo->lastBottom) / 2) + 1;
   358 					aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
   359 					}
   360 				else
   361 					{
   362 					commitPages = 0;
   363 					}
   364 				}
   365 			if (commitPages)
   366 				{
   367 				//PRINT(_L("Commit chunk memory bottom %d size %d pages\n"),aChunkInfo->lastBottom,commitPages);
   368 				test_KErrNone(aChunkInfo->chunk.Commit(aChunkInfo->lastBottom*gPageSize,commitPages*gPageSize));
   369 				}
   370 		break;
   371 
   372 		case EChunkDoubleEndedThread:
   373 		case EChunkDoubleEndedProcess:
   374 			if (aChunkInfo->lastBottom > 0 || aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
   375 				{
   376 				if (aChunkInfo->lastBottom > 0)
   377 					{
   378 					aChunkInfo->lastBottom--;
   379 					}
   380 				if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
   381 					{
   382 					aChunkInfo->lastTop++;
   383 					}
   384 			//	PRINT(_L("Adjust Double Ended bottom %d top %d\n"),aChunkInfo->lastBottom,aChunkInfo->lastTop);
   385 				test_KErrNone(aChunkInfo->chunk.AdjustDoubleEnded(aChunkInfo->lastBottom*gPageSize,aChunkInfo->lastTop*gPageSize));
   386 				}
   387 			break;
   388 		}
   389 	}
   390 //Write then read chunk
   391 void CSMPSoakThread::WriteReadChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
   392 	{
   393 	if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
   394 		{
   395 		TInt chunkSize = aChunkInfo->lastTop*gPageSize - aChunkInfo->lastBottom*gPageSize;
   396 		//RDebug::Print(_L("WriteReadChunk Last Top %d lastBottom %d\n"),aChunkInfo->lastTop,aChunkInfo->lastBottom);
   397 		TUint8 *writeaddr = aChunkInfo->chunk.Base()+ aChunkInfo->lastBottom*gPageSize;
   398 		TPtr8 write(writeaddr,chunkSize);
   399 		write.Copy(pattern,sizeof(pattern));
   400 		test_KErrNone(Mem::Compare(writeaddr,sizeof(pattern),pattern,sizeof(pattern)));
   401 		}
   402 	}
   403 //Memory Thread : will do memory associated operation
   404 //param aSmp - CSMPSoakUtil pointer
   405 TInt CSMPSoakThread::SMPStressMemoryThread(TAny* aSmp)
   406     {
   407     CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
   408      __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressMemoryThread Panic"),0));
   409     return self->DoSMPStressMemoryThread();
   410     }
   411 // Member for thread function
   412 TInt CSMPSoakThread::DoSMPStressMemoryThread()
   413 	{
   414 	RTest test(_L("SMPStressMemoryThread"));
   415 	
   416 	TMemory *memoryTablePtr;
   417 	TChunkInfo chunkTable[KNumChunks];
   418 	TInt ctIndex = 0;
   419 	test_KErrNone(UserHal::PageSizeInBytes(gPageSize));
   420 
   421 	FOREVER
   422 		{
   423 		SetThreadPriority();
   424 
   425 		if (gAbort)
   426 			break;
   427 
   428 		memoryTablePtr = (TMemory *) (iThreadData.listPtr);
   429 		ctIndex = 0;
   430 		
   431 		//Create different type of chunks and write/read/verfiy it
   432 		while (memoryTablePtr->chunkType != EChunkNone)
   433 			{
   434 			PRINT((_L("Create Chunk")));
   435 			CreateChunk (&chunkTable[ctIndex],memoryTablePtr);
   436 
   437 			PRINT(_L("Write and Read Chunk"));
   438 			WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
   439 
   440 			ctIndex++;
   441 			memoryTablePtr++;
   442 			}
   443 		
   444 		//Commit different type of chunks
   445 		TBool anyCommit;
   446 		do
   447 			{
   448 			anyCommit = EFalse;
   449 			memoryTablePtr = (TMemory *) (iThreadData.listPtr);
   450 			ctIndex = 0;
   451 			while (memoryTablePtr->chunkType != EChunkNone)
   452 				{
   453 				//Commit Chunks
   454 				PRINT((_L("Commit Chunk Memory")));
   455 				PRINT ((_L("CommitChunk %d bottom %d top %d\n"),ctIndex,memoryTablePtr->initialBottom,memoryTablePtr->initialTop));
   456 				CommitChunk (&chunkTable[ctIndex],memoryTablePtr);
   457 				anyCommit = ETrue;
   458 				
   459 				//Write into Chunks
   460 				WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
   461 				PRINT((_L("Write Read Chunk Size %d\n"), (memoryTablePtr->initialTop) - (memoryTablePtr->initialBottom)));
   462 				ctIndex++;
   463 				memoryTablePtr++;
   464 				}
   465 			}
   466 		while (anyCommit);
   467 		
   468 		//Close the Chunks
   469 		memoryTablePtr = (TMemory *) (iThreadData.listPtr);
   470 		ctIndex = 0;
   471 		while (memoryTablePtr->chunkType != EChunkNone)
   472 			{
   473 			chunkTable[ctIndex].chunk.Close();
   474 
   475 			ctIndex++;
   476 			memoryTablePtr++;
   477 			}
   478 		User::After(gPeriod);
   479 		}
   480 	return 0x00;
   481 	}
   482 //Device Thread : will do device associated operation
   483 //param aSmp - CSMPSoakUtil pointer
   484 TInt CSMPSoakThread::SMPStressDeviceThread(TAny* aSmp)
   485     {
   486     CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
   487      __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressDeviceThread Panic"),0));
   488     return self->DoSMPStressDeviceThread();
   489     }
   490 // Member for thread function
   491 TInt CSMPSoakThread::DoSMPStressDeviceThread()
   492 	{
   493 	RTest test(_L("SMPStressDeviceThread"));
   494 	
   495 	RTimer timer;
   496 	RFs session;
   497 	TFileName sessionPath;
   498 
   499 	test_KErrNone(timer.CreateLocal());
   500 	TRequestStatus s;
   501 
   502 	TDesC** ptrDevices =  (TDesC**) (iThreadData.listPtr);
   503 	PRINT ((_L("Devices  Number %d [%s]\n"), ptrDevices[0]->Length(), ptrDevices[0]->Ptr()));
   504 	for (TInt i = 1; ptrDevices[i] ; i++)
   505 		PRINT ((_L("LDD%d=%s "),i,ptrDevices[i]->Ptr()));
   506 	PRINT (_L("\n"));
   507 
   508 	FOREVER
   509 		{
   510 		for (TInt i = 0; i < ptrDevices[0]->Length(); i++)
   511 			{
   512 			TText driveLetter = (*ptrDevices[0])[i];
   513 			PRINT ((_L("Device %c\n"),driveLetter));
   514 
   515 			test_KErrNone(session.Connect());
   516 
   517 			sessionPath=(_L("?:\\SESSION_TEST\\"));
   518 			sessionPath[0]=driveLetter;
   519 			test_KErrNone(session.SetSessionPath(sessionPath));
   520 
   521 			TInt driveNumber;
   522 			test_KErrNone(session.CharToDrive(driveLetter, driveNumber));
   523 
   524 			TBuf<64> fileSystemName;
   525 			test_KErrNone(session.FileSystemName(fileSystemName,driveNumber));
   526 
   527 			PRINT ((_L("File System Name %s\n"),fileSystemName.PtrZ()));
   528 
   529 			TDriveInfo driveInfo;
   530 			test_KErrNone(session.Drive(driveInfo, driveNumber));
   531 
   532 			TVolumeInfo volumeInfo;
   533 			test_KErrNone(session.Volume(volumeInfo, driveNumber));
   534 
   535 			session.Close();
   536 			}
   537 		for (TInt i = 1; ptrDevices[i] ; i += 2)
   538 			{
   539 			RDevice device;
   540 
   541 			TInt r = User::LoadLogicalDevice(*ptrDevices[i]);
   542 			test(r == KErrNone || r == KErrAlreadyExists);
   543 
   544 			test_KErrNone(device.Open(*ptrDevices[i+1]));
   545 
   546 			TBuf8<64> deviceCaps;
   547 			device.GetCaps(deviceCaps);
   548 
   549 			TVersion deviceVersion;
   550 			device.QueryVersionSupported(deviceVersion);
   551 
   552 			device.Close();
   553 			}
   554 		SetThreadPriority();
   555 		timer.After(s, iThreadData.delayTime*1000);
   556 		User::WaitForRequest(s);
   557 		test (s == KErrNone);
   558 
   559 		if (gAbort)
   560 			break;
   561 		User::After(gPeriod);
   562 		}
   563 	timer.Close();
   564 	PRINT((_L("SMPStressDeviceThread MyTimer.Cancel() called\n")));
   565 	return 0x00;
   566 	}
   567 //Spin Thread : will do thread sync 
   568 //param aSmp - CSMPSoakUtil pointer
   569 TInt CSMPSoakThread::SMPStressSpinThread(TAny* aSmp)
   570     {
   571     CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
   572      __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressSpinThread Panic"),0));
   573     return self->DoSMPStressSpinThread();
   574     }
   575 // Member for thread function
   576 TInt CSMPSoakThread::DoSMPStressSpinThread()
   577 	{
   578 	RTest test(_L("SMPStressSpinThread"));
   579 
   580 	TTime startTime;
   581 	TTime endTime;
   582 	TTimeIntervalMicroSeconds loopTimeMicroSeconds;
   583 	PRINT (_L("SMPStressSpinThread\n"));
   584 	FOREVER
   585 		{
   586 		SetThreadPriority();
   587 		gSwitchSem.Wait();
   588 		startTime.UniversalTime();
   589 		do
   590 		{
   591 			endTime.UniversalTime();
   592 			loopTimeMicroSeconds = endTime.MicroSecondsFrom(startTime);
   593 		}while (loopTimeMicroSeconds <= iThreadData.delayTime*1000);
   594 
   595 		if (gAbort)
   596 			break;
   597 		User::After(gPeriod);
   598 		}
   599 	return 0x00;
   600 	}
   601 //Timer Thread : Timer operation and  thread sync 
   602 //param aSmp - CSMPSoakUtil pointer
   603 TInt CSMPSoakThread::SMPStressTimerThread(TAny* aSmp)
   604     {
   605     CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
   606      __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressTimerThread Panic"),0));
   607     return self->DoSMPStressTimerThread();
   608     }
   609 // Member for thread function
   610 TInt CSMPSoakThread::DoSMPStressTimerThread()
   611 	{
   612 	RTest test(_L("SMPStressTimerThread"));
   613 
   614 	PRINT (_L("SMPStressTimerThread\n"));
   615 	RTimer timer;
   616 	test_KErrNone(timer.CreateLocal());
   617 	TRequestStatus s;
   618 
   619 	FOREVER
   620 		{
   621 		timer.After(s, iThreadData.delayTime*1000);
   622 		User::WaitForRequest(s);
   623 		test (s == KErrNone);
   624 		PRINT ((_L("*")));
   625 		gSwitchSem.Signal(iThreadData.numThreads);
   626 
   627 		if (gAbort)
   628 			break;
   629 		User::After(gPeriod);
   630 		}
   631 	timer.Cancel();
   632 	PRINT((_L("SMPStressTimerThread MyTimer.Cancel() called\n")));
   633 	return 0x00;
   634 	}
   635 // CActive class to monitor KeyStrokes from User
   636 class CActiveConsole : public CActive
   637 	{
   638 public:
   639 	CActiveConsole();
   640 	~CActiveConsole();
   641 	void GetCharacter();
   642 	static TInt Callback(TAny* aCtrl);
   643 	static CPeriodic* TimerL();
   644 private:
   645 	// Defined as pure virtual by CActive;
   646 	// implementation provided by this class.
   647 	virtual void DoCancel();
   648 	// Defined as pure virtual by CActive;
   649 	// implementation provided by this class,
   650 	virtual void RunL();
   651 	void ProcessKeyPressL(TChar aChar);
   652 private:
   653     
   654 	};
   655 // Class CActiveConsole
   656 CActiveConsole::CActiveConsole()
   657 	: CActive(EPriorityHigh)
   658 	{
   659 	CActiveScheduler::Add(this);
   660 	}
   661 
   662 CActiveConsole::~CActiveConsole()
   663 	{
   664 	Cancel();
   665 	}
   666 CPeriodic* CActiveConsole::TimerL()
   667     {
   668     return(CPeriodic::NewL(EPriorityNormal));
   669     }
   670 // Callback function for timer expiry
   671 TInt CActiveConsole::Callback(TAny* aControl)
   672 	{
   673 	return KErrNone;
   674 	}
   675 
   676 void CActiveConsole::GetCharacter()
   677 	{
   678 	test.Console()->Read(iStatus);
   679 	SetActive();
   680 	}
   681 
   682 void CActiveConsole::DoCancel()
   683 	{
   684 	PRINT(_L("CActiveConsole::DoCancel\n"));
   685 	test.Console()->ReadCancel();
   686 	}
   687 
   688 void CActiveConsole::ProcessKeyPressL(TChar aChar)
   689 	{
   690 	if (aChar == EKeyEscape)
   691 		{
   692 		PRINT(_L("CActiveConsole: ESC key pressed -> stopping active scheduler...\n"));
   693 		gAbort = ETrue;
   694 		CActiveScheduler::Stop();
   695 		return;
   696 		}
   697 	aChar.UpperCase();
   698 	GetCharacter();
   699 	}
   700 
   701 void CActiveConsole::RunL()
   702 	{
   703 	ProcessKeyPressL(static_cast<TChar>(test.Console()->KeyCode()));
   704 	}
   705 
   706 // CActiveTimer class to monitor timeout expiry
   707 class CActiveTimer : public CActive
   708     {
   709 public:
   710     CActiveTimer();
   711     ~CActiveTimer();
   712     void Delay(TTimeIntervalMicroSeconds32 aDelay);
   713 private:
   714     RTimer iTimer;
   715     // Defined as pure virtual by CActive;
   716     // implementation provided by this class.
   717     virtual void DoCancel();
   718     // Defined as pure virtual by CActive;
   719     // implementation provided by this class,
   720     virtual void RunL();
   721    
   722     };
   723 // Class CActiveConsole
   724 CActiveTimer::CActiveTimer()
   725     : CActive(EPriorityHigh)
   726     {
   727     CActiveScheduler::Add(this);
   728     User::LeaveIfError(iTimer.CreateLocal());
   729     }
   730 
   731 CActiveTimer::~CActiveTimer()
   732     {
   733     Cancel();
   734     iTimer.Close();
   735     }
   736 
   737 
   738 void CActiveTimer::Delay(TTimeIntervalMicroSeconds32 aDelay)
   739     {
   740     iTimer.After(iStatus, aDelay);
   741     SetActive();
   742     }
   743 
   744 void CActiveTimer::DoCancel()
   745     {
   746     iTimer.Cancel();
   747     }
   748 
   749 void CActiveTimer::RunL()
   750     {
   751     PRINT(_L("CActiveTimer: Application runtime expired..."));
   752     gAbort = ETrue;
   753     CActiveScheduler::Stop();
   754     return;
   755     }
   756 
   757 //T_SMPSOAK Entry Point
   758 TInt E32Main()
   759 	{
   760 	test.Title();
   761 	__UHEAP_MARK;
   762 	test.Start(_L("t_smpsoak.exe"));
   763 	
   764 	// When running as a stand alone test, 
   765 	// there needs to be a timeout
   766 	timeout = ETrue;
   767 
   768 	ParseCommandLine();
   769 	if (gAbort)
   770 		return 0x00;
   771 
   772 	PRINT (_L("Load device driver\n"));
   773 	TInt r = User::LoadLogicalDevice(_L("d_smpsoak.ldd"));
   774 	if (r == KErrNotFound)
   775 		{
   776 		PRINT (_L("Test not supported on this platform because the D_SMPSOAK.LDD Driver is Not Present\n"));
   777 		test(EFalse);
   778 		}
   779 	PRINT (_L("Calling SMPStressDrv Open\n"));
   780 	r = gSMPStressDrv.Open();
   781 	test_KErrNone(r);
   782 
   783 	PRINT (_L("Creating our local semaphore\n"));
   784 	r=gSwitchSem.CreateLocal(0);
   785 	test_KErrNone(r);
   786 
   787 	CSMPSoakThread smpthread;
   788 	PRINT ((_L("Creating all threads =%d\n"),KNumThreads));
   789 	smpthread.CreateThread();
   790 			
   791 	CSMPSoakThread *smpprocess= new CSMPSoakThread[NumProcess];
   792 	PRINT ((_L("Creating all process =%d\n"),NumProcess));
   793 	for (TInt i = 0; i < NumProcess; i++)
   794 	    smpprocess[i].CreateChildProcess(i);
   795 	
   796 	PRINT (_L("Resuming all process \n"));
   797 	for (TInt i = 0; i < NumProcess; i++)
   798 	    smpprocess[i].ResumeChildProcess();
   799 	
   800 	PRINT (_L("Starting ActiveScheduler\n"));
   801 	test.Next(_L("Press ESC Key to Shutdown SMPSoak...\n"));
   802 	CActiveScheduler* myScheduler = new (ELeave) CActiveScheduler();
   803 	test(myScheduler != NULL);
   804 	CActiveScheduler::Install(myScheduler);
   805 	
   806 	CPeriodic* theTimer=NULL;
   807 	TRAPD(ret,theTimer=CActiveConsole::TimerL())
   808 	test_KErrNone(ret);
   809 	theTimer->Start(0,KTimerPeriod,TCallBack(CActiveConsole::Callback));
   810 	if(timeout)
   811 	    {
   812 	    CActiveTimer* myActiveTimer = new CActiveTimer();
   813 	    test(myActiveTimer != NULL);
   814 	    myActiveTimer->Delay(gTimeout*1000000);
   815 	    }
   816 	CActiveConsole* myActiveConsole = new CActiveConsole();
   817 	test(myActiveConsole != NULL);
   818 	myActiveConsole->GetCharacter();
   819 	CActiveScheduler::Start();
   820 	if (gAbort)
   821 			{
   822 			PRINT (_L("gAbort TRUE \n"));
   823 			for (TInt i = 0; i < NumProcess; i++)
   824 			smpprocess[i].TerminateChildProcess();
   825 			delete[] smpprocess;
   826 			delete theTimer;
   827 			gSMPStressDrv.Close();
   828 			gSwitchSem.Close();
   829 			return 0;
   830 			}
   831 	__UHEAP_MARKEND;
   832 	test.End();
   833 	return 0;
   834 	}
   835 void ParseCommandLine()
   836 	{
   837 	TBuf<256> args;
   838 	User::CommandLine(args);
   839 	TLex	lex(args);
   840 	PRINT ((_L("****Command line = %s\n"), args.PtrZ()));
   841 
   842 	FOREVER
   843 		{
   844 		TPtrC  token=lex.NextToken();
   845 		if(token.Length()!=0)
   846 			{
   847                 if (token.Length()==0)
   848 			        break;  // ignore trailing whitespace
   849                 else if (token.Mid(0) == _L("-h"))
   850 				{
   851                     PRINT (_L("T_SMPSOAK.EXE Usage Options:\n"));
   852                     PRINT (_L("Type t_smpsoak.exe -h\n"));
   853 					ShowHelp();
   854 					gAbort = ETrue;
   855 					break;
   856 				}
   857 				else if (token.Mid(0) == _L("-l"))
   858 				{
   859                     //Read OOM entry from KProcessTable and run
   860                     test.Printf(_L("SMPSOAK:lowmem\n"));
   861                     NumProcess = KNumProcess+1;
   862                     break;
   863 				}
   864 				else if (token.Mid(0) == _L("-b"))
   865 				{
   866                     test.Printf(_L("SMPSOAK: Test Silent Mode\n")); 
   867                     ThreadPriorityLow = ETrue;
   868                     TestSilent = ETrue;
   869 					// If we have tests running in the background
   870 					// we want an endless loop
   871 					timeout = EFalse;
   872                     break;
   873 				}
   874 				else if (token.Left(2) == _L("-t"))
   875 				{
   876 				    test.Printf(_L("SMPSOAK:Timeout\n"));
   877 				    lex.SkipSpaceAndMark();
   878 				    token.Set(lex.NextToken());
   879 				    TLex lexNum(token);
   880 				    lexNum.Val(gTimeout,EDecimal);   
   881 				    test.Printf(_L("Timeout in Seconds=%u \n"),gTimeout);  
   882 				    timeout = ETrue;
   883                     break;
   884 				}
   885 				else if (token.Left(2) == _L("-p"))
   886 				{
   887                     test.Printf(_L("SMPSOAK:period\n"));
   888                     lex.SkipSpaceAndMark();
   889                     token.Set(lex.NextToken());
   890                     TLex lexNum(token);
   891                     lexNum.Val(gPeriod,EDecimal);   
   892 				    test.Printf(_L("period in mSeconds=%d \n"),gPeriod);  
   893 				    Period = ETrue;
   894 				    break;
   895 				}
   896 				else
   897 				{
   898                     test.Printf(_L("Error- Invalid SMPSOAK CMD Line Argument"));
   899 				  	break;
   900 				}
   901 			}
   902 		break;
   903 		}
   904 	}