kerneltest/e32test/smpsoak/t_smpsoak.cpp
branchanywhere
changeset 41 d32f34975bbf
parent 36 538db54a451d
child 252 0a40b8675b23
equal deleted inserted replaced
40:04a1b74efd48 41:d32f34975bbf
       
     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 	}