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