--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/smpsoak/t_smpsoak.cpp Thu Jan 07 13:38:45 2010 +0200
@@ -0,0 +1,903 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\smpsoak\t_smpsoak.cpp
+
+// User Includes
+#include "t_smpsoak.h"
+
+void ParseCommandLine ();
+
+// Global Variables
+static TInt gPageSize;
+//Timeout 2 Minutes
+static TUint gTimeout = 120;
+
+//class for smpsoak thread and it creates memory, device, timer and spin threads.
+class CSMPSoakThread
+ {
+public:
+ CSMPSoakThread();
+ ~CSMPSoakThread();
+ void CreateThread();
+ void ResumeThread();
+ void CreateChildProcess(TInt aIndex);
+ void ResumeChildProcess();
+ void TerminateChildProcess();
+private:
+ //Thread Functions
+ static TInt SMPStressMemoryThread(TAny*);
+ static TInt SMPStressDeviceThread(TAny*);
+ static TInt SMPStressTimerThread(TAny*);
+ static TInt SMPStressSpinThread(TAny*);
+ //Thread Priority
+ void DoCreateThread(TAny*);
+ void SetThreadPriority();
+private:
+ //Utils for memory thread
+ void CreateChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
+ void CommitChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
+ void WriteReadChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
+private:
+ //Memebers for threads
+ TInt DoSMPStressMemoryThread();
+ TInt DoSMPStressDeviceThread();
+ TInt DoSMPStressTimerThread();
+ TInt DoSMPStressSpinThread();
+private:
+ TThreadData iThreadData;
+ RProcess iProcess;
+ RThread iThread;
+ TInt iPriority;
+private:
+// Thread Data for each thread- low priority
+static TThread KThreadTableLow[];
+// Thread Data for each thread- high priority
+static TThread KThreadTableHigh[];
+//Process Data for each process
+static const TProcess KProcessTable[];
+//Memory table for memory thread
+static const TMemory KMemoryTable[];
+//Device table for device thread
+static const TDesC* KDeviceTable[];
+
+ };
+TThread CSMPSoakThread::KThreadTableLow[] =
+ {
+ { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
+ { _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
+ { _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
+ { _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
+ };
+TThread CSMPSoakThread::KThreadTableHigh[] =
+ {
+ { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
+ { _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
+ { _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
+ { _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
+ { _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
+ };
+const TProcess CSMPSoakThread::KProcessTable[] =
+ {
+ { _L("t_smpsoakprocess.exe"), _L("-W"), KCpuAffinityAny},
+ { _L("t_smpsoakprocess.exe"), _L("-R"), KCpuAffinityAny},
+ { _L("t_smpsoakprocess.exe"), _L("-F"), KCpuAffinityAny},
+ { _L("t_smpsoakprocess.exe"), _L("-T"), KCpuAffinityAny},
+ { _L("t_smpsoakprocess.exe"), _L("-O"), KCpuAffinityAny},
+ };
+const TMemory CSMPSoakThread::KMemoryTable[] =
+ {
+ {_L(""), EChunkNormalThread, 0, 10, 100 },
+ {_L("Global Chunk 1"), EChunkNormalThread, 0, 20, 200 },
+ {_L(""), EChunkDisconnectedThread, 3, 30, 300 },
+ {_L("Global Chunk 2"), EChunkDisconnectedThread, 4, 40, 400 },
+ {_L(""), EChunkDoubleEndedThread, 5, 50, 500 },
+ {_L("Global Chunk 3"), EChunkDoubleEndedThread, 6, 60, 600 },
+ {_L(""), EChunkNormalProcess, 0, 10, 100 },
+ {_L("Global Chunk 4"), EChunkNormalProcess, 0, 20, 200 },
+ {_L(""), EChunkDisconnectedProcess, 3, 30, 300 },
+ {_L("Global Chunk 5"), EChunkDisconnectedProcess, 4, 40, 400 },
+ {_L(""), EChunkDoubleEndedProcess, 5, 50, 500 },
+ {_L("Global Chunk 6"), EChunkDoubleEndedProcess, 6, 60, 600 },
+ {_L(""), EChunkNone, 0, 0, 0 },
+ };
+const TDesC* CSMPSoakThread::KDeviceTable[] =
+ {
+ &KDevices, &KDevLdd1, &KDevLdd1Name, &KDevLdd2, &KDevLdd2Name, &KDevLdd3, &KDevLdd3Name,
+ &KDevLdd4, &KDevLdd4Name, &KDevLdd5, &KDevLdd5Name, NULL
+ };
+
+//Constructor
+CSMPSoakThread::CSMPSoakThread()
+ {
+ }
+//Destructor
+CSMPSoakThread::~CSMPSoakThread()
+ {
+ }
+//All child process creation
+void CSMPSoakThread::CreateChildProcess(TInt aIndex)
+ {
+ if(TestSilent)
+ gCmdLine.Format(KCmdLineBackground,(KProcessTable[aIndex].operation).Ptr());
+ else if (Period)
+ gCmdLine.Format(KCmdLinePeriod,gPeriod,(KProcessTable[aIndex].operation).Ptr());
+ else
+ gCmdLine.Format(KCmdLineProcess,(KProcessTable[aIndex].operation).Ptr());
+
+ TInt r = iProcess.Create(KProcessTable[aIndex].processFileName,gCmdLine);
+ test_KErrNone(r);
+ iProcess.SetPriority(EPriorityLow);
+ gSMPStressDrv.ChangeThreadAffinity(&iThread, KProcessTable[aIndex].cpuAffinity);
+ PRINT ((_L("SetProcessPriority CPU %d Priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iProcess.Priority()));
+ }
+//Terminate process when user press "Esc key"
+void CSMPSoakThread::ResumeChildProcess()
+ {
+ iProcess.Resume();
+ }
+//Terminate process when user press "Esc key"
+void CSMPSoakThread::TerminateChildProcess()
+ {
+ iProcess.Kill(KErrNone);
+ }
+//Changes the thread priority each time time, for each thread by Random, Increment, from List, Fixed.
+//pick up the priority option from thread table
+void CSMPSoakThread::SetThreadPriority()
+ {
+ static TInt64 randSeed = KRandSeed;
+ static const TThreadPriority priorityTable[]=
+ {
+ EPriorityMuchLess, EPriorityLess, EPriorityNormal, EPriorityMore, EPriorityMuchMore,
+ EPriorityRealTime, EPriorityRealTime, EPriorityAbsoluteVeryLow, EPriorityAbsoluteLowNormal,
+ EPriorityAbsoluteLow, EPriorityAbsoluteBackgroundNormal, EPriorityAbsoluteBackground,
+ EPriorityAbsoluteForegroundNormal, EPriorityAbsoluteForeground, EPriorityAbsoluteHighNormal, EPriorityAbsoluteHigh
+ };
+ TInt priorityIndex = 0;
+ switch (iThreadData.threadPriorityChange)
+ {
+ case EpriorityFixed:
+ break;
+
+ case EPriorityList:
+ if (++iPriority >= KPriorityOrder)
+ iPriority = 0;
+ if (iThreadData.threadPriorities[iPriority] == 0)
+ iPriority = 0;
+ // PRINT(_L("SetPriority List CPU %d index %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread),iPriority, iThreadData.threadPriorities[iPriority]);
+ iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[iPriority]);
+ break;
+
+ case EPriorityIncrement:
+ while (priorityTable[priorityIndex] <= iPriority)
+ {
+ priorityIndex++;
+ }
+ iPriority = priorityTable[priorityIndex];
+ if (iPriority > iThreadData.threadPriorities[2])
+ iPriority = iThreadData.threadPriorities[1];
+ // PRINT(_L("SetPriority Increment CPU %d iPriority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
+ iThread.SetPriority((TThreadPriority)iPriority);
+ break;
+
+ case EPriorityRandom:
+ iPriority = Math::Rand(randSeed) % (iThreadData.threadPriorities[2] - iThreadData.threadPriorities[1] + 1);
+ iPriority += iThreadData.threadPriorities[1];
+ while (priorityTable[priorityIndex] < iPriority)
+ {
+ priorityIndex++;
+ }
+ iPriority = priorityTable[priorityIndex];
+ // PRINT(_L("SetPriority Random CPU %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
+ iThread.SetPriority((TThreadPriority)iPriority);
+ break;
+ }
+ }
+//Resume each thread
+void CSMPSoakThread::ResumeThread()
+ {
+ iThread.Resume();
+ }
+//thread creation
+void CSMPSoakThread::CreateThread()
+ {
+ CSMPSoakThread* smpthread = new CSMPSoakThread[KNumThreads];
+ for (TInt i = 0; i < KNumThreads ; i++)
+ {
+ if(ThreadPriorityLow)
+ {
+ PRINT ((_L("Thread Table - Priority Low \n")));
+ smpthread[i].DoCreateThread(&KThreadTableLow[i]);
+ }
+ else
+ {
+ PRINT ((_L("Thread Table - Priority High \n")));
+ smpthread[i].DoCreateThread(&KThreadTableHigh[i]);
+ }
+ }
+ PRINT (_L("Resuming all threads\n"));
+ for (TInt i = 0; i < KNumThreads; i++)
+ smpthread[i].ResumeThread();
+ }
+/**
+ * CSMPSoakThread Thread Creation.
+ * @param aIndex to exercise each row(thread) in the thread table
+ *
+ * @return N/A
+ *
+ * @pre Initialize thread Table values
+ * @post None
+ */
+void CSMPSoakThread::DoCreateThread(TAny* aThread)
+ {
+ //Initialize each thread data
+ iThreadData = ((TThread*)aThread)->threadData;
+ test.Next(_L("Create Thread"));
+ PRINT ((_L("%s CPU affinity %d Priority %d\n"),((TThread*)aThread)->threadName.Ptr(),iThreadData.cpuAffinity,iThreadData.threadPriorities[0]));
+ TInt r = iThread.Create(((TThread*)aThread)->threadName, ((TThread*)aThread)->threadFunction, KDefaultStackSize, KHeapMinSize, KHeapMaxSize,(TAny*)this);
+ test_KErrNone(r);
+ if (iThreadData.threadPriorityChange == EPriorityList)
+ {
+ iPriority = 0;
+ }
+ else
+ {
+ iPriority = iThreadData.threadPriorities[0];
+ }
+ iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[0]);
+ //Set the thread CPU Affinity
+ gSMPStressDrv.ChangeThreadAffinity(&iThread, iThreadData.cpuAffinity);
+ }
+//Create Chunk - different types
+void CSMPSoakThread::CreateChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
+ {
+ //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);
+ TOwnerType ownerType = EOwnerProcess;
+ aChunkInfo->lastBottom = aMemoryTablePtr->initialBottom;
+ aChunkInfo->lastTop = aMemoryTablePtr->initialTop;
+ switch (aMemoryTablePtr->chunkType)
+ {
+ case EChunkNormalThread:
+ ownerType = EOwnerThread; // drop through to create chunk
+ case EChunkNormalProcess:
+ if (aMemoryTablePtr->globalChunkName.Length())
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ else
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateLocal(aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ aChunkInfo->lastBottom = 0; // ensure that this is zero
+ break;
+
+ case EChunkDisconnectedThread:
+ ownerType = EOwnerThread; // drop through to create chunk
+ case EChunkDisconnectedProcess:
+ if (aMemoryTablePtr->globalChunkName.Length())
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateDisconnectedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ else
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateDisconnectedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ break;
+
+ case EChunkDoubleEndedThread:
+ ownerType = EOwnerThread; // drop through to create chunk
+ case EChunkDoubleEndedProcess:
+ if (aMemoryTablePtr->globalChunkName.Length())
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ else
+ {
+ test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
+ }
+ break;
+ }
+ }
+//Commit chunk
+void CSMPSoakThread::CommitChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
+ {
+ TInt commitPages;
+
+ switch (aMemoryTablePtr->chunkType)
+ {
+ case EChunkNormalThread:
+ case EChunkNormalProcess:
+ if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
+ {
+ aChunkInfo->lastTop += (aMemoryTablePtr->maxSize - 1 - aChunkInfo->lastTop) / 2 + 1;
+ //PRINT(_L("Adjust chunk memory - top %d pagesize %d\n"),aChunkInfo->lastTop,gPageSize);
+ test_KErrNone(aChunkInfo->chunk.Adjust(aChunkInfo->lastTop*gPageSize));
+ }
+ break;
+
+ case EChunkDisconnectedThread:
+ case EChunkDisconnectedProcess:
+ commitPages = ((aChunkInfo->lastTop - aChunkInfo->lastBottom) / 2) + 1;
+ //PRINT(_L("Decommitting from bottom %d of %d pages\n"),aChunkInfo->lastBottom,commitPages);
+ test_KErrNone(aChunkInfo->chunk.Decommit(aChunkInfo->lastBottom*gPageSize,commitPages * gPageSize));
+ if ((aChunkInfo->lastBottom > 0) && (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop))
+ {
+ aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
+ aChunkInfo->lastBottom /= 2;
+ commitPages = aChunkInfo->lastTop - aChunkInfo->lastBottom + 1;
+ }
+ else
+ {
+ if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize -1))
+ {
+ if (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop)
+ {
+ aChunkInfo->lastBottom = aMemoryTablePtr->initialTop + 1;
+ }
+ else
+ {
+ aChunkInfo->lastBottom = aChunkInfo->lastTop + 1;
+ }
+ commitPages = ((aMemoryTablePtr->maxSize - aChunkInfo->lastBottom) / 2) + 1;
+ aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
+ }
+ else
+ {
+ commitPages = 0;
+ }
+ }
+ if (commitPages)
+ {
+ //PRINT(_L("Commit chunk memory bottom %d size %d pages\n"),aChunkInfo->lastBottom,commitPages);
+ test_KErrNone(aChunkInfo->chunk.Commit(aChunkInfo->lastBottom*gPageSize,commitPages*gPageSize));
+ }
+ break;
+
+ case EChunkDoubleEndedThread:
+ case EChunkDoubleEndedProcess:
+ if (aChunkInfo->lastBottom > 0 || aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
+ {
+ if (aChunkInfo->lastBottom > 0)
+ {
+ aChunkInfo->lastBottom--;
+ }
+ if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
+ {
+ aChunkInfo->lastTop++;
+ }
+ // PRINT(_L("Adjust Double Ended bottom %d top %d\n"),aChunkInfo->lastBottom,aChunkInfo->lastTop);
+ test_KErrNone(aChunkInfo->chunk.AdjustDoubleEnded(aChunkInfo->lastBottom*gPageSize,aChunkInfo->lastTop*gPageSize));
+ }
+ break;
+ }
+ }
+//Write then read chunk
+void CSMPSoakThread::WriteReadChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
+ {
+ if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
+ {
+ TInt chunkSize = aChunkInfo->lastTop*gPageSize - aChunkInfo->lastBottom*gPageSize;
+ //RDebug::Print(_L("WriteReadChunk Last Top %d lastBottom %d\n"),aChunkInfo->lastTop,aChunkInfo->lastBottom);
+ TUint8 *writeaddr = aChunkInfo->chunk.Base()+ aChunkInfo->lastBottom*gPageSize;
+ TPtr8 write(writeaddr,chunkSize);
+ write.Copy(pattern,sizeof(pattern));
+ test_KErrNone(Mem::Compare(writeaddr,sizeof(pattern),pattern,sizeof(pattern)));
+ }
+ }
+//Memory Thread : will do memory associated operation
+//param aSmp - CSMPSoakUtil pointer
+TInt CSMPSoakThread::SMPStressMemoryThread(TAny* aSmp)
+ {
+ CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
+ __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressMemoryThread Panic"),0));
+ return self->DoSMPStressMemoryThread();
+ }
+// Member for thread function
+TInt CSMPSoakThread::DoSMPStressMemoryThread()
+ {
+ RTest test(_L("SMPStressMemoryThread"));
+
+ TMemory *memoryTablePtr;
+ TChunkInfo chunkTable[KNumChunks];
+ TInt ctIndex = 0;
+ test_KErrNone(UserHal::PageSizeInBytes(gPageSize));
+
+ FOREVER
+ {
+ SetThreadPriority();
+
+ if (gAbort)
+ break;
+
+ memoryTablePtr = (TMemory *) (iThreadData.listPtr);
+ ctIndex = 0;
+
+ //Create different type of chunks and write/read/verfiy it
+ while (memoryTablePtr->chunkType != EChunkNone)
+ {
+ PRINT((_L("Create Chunk")));
+ CreateChunk (&chunkTable[ctIndex],memoryTablePtr);
+
+ PRINT(_L("Write and Read Chunk"));
+ WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
+
+ ctIndex++;
+ memoryTablePtr++;
+ }
+
+ //Commit different type of chunks
+ TBool anyCommit;
+ do
+ {
+ anyCommit = EFalse;
+ memoryTablePtr = (TMemory *) (iThreadData.listPtr);
+ ctIndex = 0;
+ while (memoryTablePtr->chunkType != EChunkNone)
+ {
+ //Commit Chunks
+ PRINT((_L("Commit Chunk Memory")));
+ PRINT ((_L("CommitChunk %d bottom %d top %d\n"),ctIndex,memoryTablePtr->initialBottom,memoryTablePtr->initialTop));
+ CommitChunk (&chunkTable[ctIndex],memoryTablePtr);
+ anyCommit = ETrue;
+
+ //Write into Chunks
+ WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
+ PRINT((_L("Write Read Chunk Size %d\n"), (memoryTablePtr->initialTop) - (memoryTablePtr->initialBottom)));
+ ctIndex++;
+ memoryTablePtr++;
+ }
+ }
+ while (anyCommit);
+
+ //Close the Chunks
+ memoryTablePtr = (TMemory *) (iThreadData.listPtr);
+ ctIndex = 0;
+ while (memoryTablePtr->chunkType != EChunkNone)
+ {
+ chunkTable[ctIndex].chunk.Close();
+
+ ctIndex++;
+ memoryTablePtr++;
+ }
+ User::After(gPeriod);
+ }
+ return 0x00;
+ }
+//Device Thread : will do device associated operation
+//param aSmp - CSMPSoakUtil pointer
+TInt CSMPSoakThread::SMPStressDeviceThread(TAny* aSmp)
+ {
+ CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
+ __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressDeviceThread Panic"),0));
+ return self->DoSMPStressDeviceThread();
+ }
+// Member for thread function
+TInt CSMPSoakThread::DoSMPStressDeviceThread()
+ {
+ RTest test(_L("SMPStressDeviceThread"));
+
+ RTimer timer;
+ RFs session;
+ TFileName sessionPath;
+
+ test_KErrNone(timer.CreateLocal());
+ TRequestStatus s;
+
+ TDesC** ptrDevices = (TDesC**) (iThreadData.listPtr);
+ PRINT ((_L("Devices Number %d [%s]\n"), ptrDevices[0]->Length(), ptrDevices[0]->Ptr()));
+ for (TInt i = 1; ptrDevices[i] ; i++)
+ PRINT ((_L("LDD%d=%s "),i,ptrDevices[i]->Ptr()));
+ PRINT (_L("\n"));
+
+ FOREVER
+ {
+ for (TInt i = 0; i < ptrDevices[0]->Length(); i++)
+ {
+ TText driveLetter = (*ptrDevices[0])[i];
+ PRINT ((_L("Device %c\n"),driveLetter));
+
+ test_KErrNone(session.Connect());
+
+ sessionPath=(_L("?:\\SESSION_TEST\\"));
+ sessionPath[0]=driveLetter;
+ test_KErrNone(session.SetSessionPath(sessionPath));
+
+ TInt driveNumber;
+ test_KErrNone(session.CharToDrive(driveLetter, driveNumber));
+
+ TBuf<64> fileSystemName;
+ test_KErrNone(session.FileSystemName(fileSystemName,driveNumber));
+
+ PRINT ((_L("File System Name %s\n"),fileSystemName.PtrZ()));
+
+ TDriveInfo driveInfo;
+ test_KErrNone(session.Drive(driveInfo, driveNumber));
+
+ TVolumeInfo volumeInfo;
+ test_KErrNone(session.Volume(volumeInfo, driveNumber));
+
+ session.Close();
+ }
+ for (TInt i = 1; ptrDevices[i] ; i += 2)
+ {
+ RDevice device;
+
+ TInt r = User::LoadLogicalDevice(*ptrDevices[i]);
+ test(r == KErrNone || r == KErrAlreadyExists);
+
+ test_KErrNone(device.Open(*ptrDevices[i+1]));
+
+ TBuf8<64> deviceCaps;
+ device.GetCaps(deviceCaps);
+
+ TVersion deviceVersion;
+ device.QueryVersionSupported(deviceVersion);
+
+ device.Close();
+ }
+ SetThreadPriority();
+ timer.After(s, iThreadData.delayTime*1000);
+ User::WaitForRequest(s);
+ test (s == KErrNone);
+
+ if (gAbort)
+ break;
+ User::After(gPeriod);
+ }
+ timer.Close();
+ PRINT((_L("SMPStressDeviceThread MyTimer.Cancel() called\n")));
+ return 0x00;
+ }
+//Spin Thread : will do thread sync
+//param aSmp - CSMPSoakUtil pointer
+TInt CSMPSoakThread::SMPStressSpinThread(TAny* aSmp)
+ {
+ CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
+ __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressSpinThread Panic"),0));
+ return self->DoSMPStressSpinThread();
+ }
+// Member for thread function
+TInt CSMPSoakThread::DoSMPStressSpinThread()
+ {
+ RTest test(_L("SMPStressSpinThread"));
+
+ TTime startTime;
+ TTime endTime;
+ TTimeIntervalMicroSeconds loopTimeMicroSeconds;
+ PRINT (_L("SMPStressSpinThread\n"));
+ FOREVER
+ {
+ SetThreadPriority();
+ gSwitchSem.Wait();
+ startTime.UniversalTime();
+ do
+ {
+ endTime.UniversalTime();
+ loopTimeMicroSeconds = endTime.MicroSecondsFrom(startTime);
+ }while (loopTimeMicroSeconds <= iThreadData.delayTime*1000);
+
+ if (gAbort)
+ break;
+ User::After(gPeriod);
+ }
+ return 0x00;
+ }
+//Timer Thread : Timer operation and thread sync
+//param aSmp - CSMPSoakUtil pointer
+TInt CSMPSoakThread::SMPStressTimerThread(TAny* aSmp)
+ {
+ CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
+ __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressTimerThread Panic"),0));
+ return self->DoSMPStressTimerThread();
+ }
+// Member for thread function
+TInt CSMPSoakThread::DoSMPStressTimerThread()
+ {
+ RTest test(_L("SMPStressTimerThread"));
+
+ PRINT (_L("SMPStressTimerThread\n"));
+ RTimer timer;
+ test_KErrNone(timer.CreateLocal());
+ TRequestStatus s;
+
+ FOREVER
+ {
+ timer.After(s, iThreadData.delayTime*1000);
+ User::WaitForRequest(s);
+ test (s == KErrNone);
+ PRINT ((_L("*")));
+ gSwitchSem.Signal(iThreadData.numThreads);
+
+ if (gAbort)
+ break;
+ User::After(gPeriod);
+ }
+ timer.Cancel();
+ PRINT((_L("SMPStressTimerThread MyTimer.Cancel() called\n")));
+ return 0x00;
+ }
+// CActive class to monitor KeyStrokes from User
+class CActiveConsole : public CActive
+ {
+public:
+ CActiveConsole();
+ ~CActiveConsole();
+ void GetCharacter();
+ static TInt Callback(TAny* aCtrl);
+ static CPeriodic* TimerL();
+private:
+ // Defined as pure virtual by CActive;
+ // implementation provided by this class.
+ virtual void DoCancel();
+ // Defined as pure virtual by CActive;
+ // implementation provided by this class,
+ virtual void RunL();
+ void ProcessKeyPressL(TChar aChar);
+private:
+
+ };
+// Class CActiveConsole
+CActiveConsole::CActiveConsole()
+ : CActive(EPriorityHigh)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CActiveConsole::~CActiveConsole()
+ {
+ Cancel();
+ }
+CPeriodic* CActiveConsole::TimerL()
+ {
+ return(CPeriodic::NewL(EPriorityNormal));
+ }
+// Callback function for timer expiry
+TInt CActiveConsole::Callback(TAny* aControl)
+ {
+ return KErrNone;
+ }
+
+void CActiveConsole::GetCharacter()
+ {
+ test.Console()->Read(iStatus);
+ SetActive();
+ }
+
+void CActiveConsole::DoCancel()
+ {
+ PRINT(_L("CActiveConsole::DoCancel\n"));
+ test.Console()->ReadCancel();
+ }
+
+void CActiveConsole::ProcessKeyPressL(TChar aChar)
+ {
+ if (aChar == EKeyEscape)
+ {
+ PRINT(_L("CActiveConsole: ESC key pressed -> stopping active scheduler...\n"));
+ gAbort = ETrue;
+ CActiveScheduler::Stop();
+ return;
+ }
+ aChar.UpperCase();
+ GetCharacter();
+ }
+
+void CActiveConsole::RunL()
+ {
+ ProcessKeyPressL(static_cast<TChar>(test.Console()->KeyCode()));
+ }
+
+// CActiveTimer class to monitor timeout expiry
+class CActiveTimer : public CActive
+ {
+public:
+ CActiveTimer();
+ ~CActiveTimer();
+ void Delay(TTimeIntervalMicroSeconds32 aDelay);
+private:
+ RTimer iTimer;
+ // Defined as pure virtual by CActive;
+ // implementation provided by this class.
+ virtual void DoCancel();
+ // Defined as pure virtual by CActive;
+ // implementation provided by this class,
+ virtual void RunL();
+
+ };
+// Class CActiveConsole
+CActiveTimer::CActiveTimer()
+ : CActive(EPriorityHigh)
+ {
+ CActiveScheduler::Add(this);
+ User::LeaveIfError(iTimer.CreateLocal());
+ }
+
+CActiveTimer::~CActiveTimer()
+ {
+ Cancel();
+ iTimer.Close();
+ }
+
+
+void CActiveTimer::Delay(TTimeIntervalMicroSeconds32 aDelay)
+ {
+ iTimer.After(iStatus, aDelay);
+ SetActive();
+ }
+
+void CActiveTimer::DoCancel()
+ {
+ iTimer.Cancel();
+ }
+
+void CActiveTimer::RunL()
+ {
+ PRINT(_L("CActiveTimer: Application runtime expired..."));
+ gAbort = ETrue;
+ CActiveScheduler::Stop();
+ return;
+ }
+
+//T_SMPSOAK Entry Point
+TInt E32Main()
+ {
+ test.Title();
+ __UHEAP_MARK;
+ test.Start(_L("t_smpsoak.exe"));
+
+ // When running as a stand alone test,
+ // there needs to be a timeout
+ timeout = ETrue;
+
+ ParseCommandLine();
+ if (gAbort)
+ return 0x00;
+
+ PRINT (_L("Load device driver\n"));
+ TInt r = User::LoadLogicalDevice(_L("d_smpsoak.ldd"));
+ if (r == KErrNotFound)
+ {
+ PRINT (_L("Test not supported on this platform because the D_SMPSOAK.LDD Driver is Not Present\n"));
+ test(EFalse);
+ }
+ PRINT (_L("Calling SMPStressDrv Open\n"));
+ r = gSMPStressDrv.Open();
+ test_KErrNone(r);
+
+ PRINT (_L("Creating our local semaphore\n"));
+ r=gSwitchSem.CreateLocal(0);
+ test_KErrNone(r);
+
+ CSMPSoakThread smpthread;
+ PRINT ((_L("Creating all threads =%d\n"),KNumThreads));
+ smpthread.CreateThread();
+
+ CSMPSoakThread *smpprocess= new CSMPSoakThread[NumProcess];
+ PRINT ((_L("Creating all process =%d\n"),NumProcess));
+ for (TInt i = 0; i < NumProcess; i++)
+ smpprocess[i].CreateChildProcess(i);
+
+ PRINT (_L("Resuming all process \n"));
+ for (TInt i = 0; i < NumProcess; i++)
+ smpprocess[i].ResumeChildProcess();
+
+ PRINT (_L("Starting ActiveScheduler\n"));
+ test.Next(_L("Press ESC Key to Shutdown SMPSoak...\n"));
+ CActiveScheduler* myScheduler = new (ELeave) CActiveScheduler();
+ test(myScheduler != NULL);
+ CActiveScheduler::Install(myScheduler);
+
+ CPeriodic* theTimer=NULL;
+ TRAPD(ret,theTimer=CActiveConsole::TimerL())
+ test_KErrNone(ret);
+ theTimer->Start(0,KTimerPeriod,TCallBack(CActiveConsole::Callback));
+ if(timeout)
+ {
+ CActiveTimer* myActiveTimer = new CActiveTimer();
+ test(myActiveTimer != NULL);
+ myActiveTimer->Delay(gTimeout*1000000);
+ }
+ CActiveConsole* myActiveConsole = new CActiveConsole();
+ test(myActiveConsole != NULL);
+ myActiveConsole->GetCharacter();
+ CActiveScheduler::Start();
+ if (gAbort)
+ {
+ PRINT (_L("gAbort TRUE \n"));
+ for (TInt i = 0; i < NumProcess; i++)
+ smpprocess[i].TerminateChildProcess();
+ delete[] smpprocess;
+ delete theTimer;
+ gSMPStressDrv.Close();
+ gSwitchSem.Close();
+ return 0;
+ }
+ __UHEAP_MARKEND;
+ test.End();
+ return 0;
+ }
+void ParseCommandLine()
+ {
+ TBuf<256> args;
+ User::CommandLine(args);
+ TLex lex(args);
+ PRINT ((_L("****Command line = %s\n"), args.PtrZ()));
+
+ FOREVER
+ {
+ TPtrC token=lex.NextToken();
+ if(token.Length()!=0)
+ {
+ if (token.Length()==0)
+ break; // ignore trailing whitespace
+ else if (token.Mid(0) == _L("-h"))
+ {
+ PRINT (_L("T_SMPSOAK.EXE Usage Options:\n"));
+ PRINT (_L("Type t_smpsoak.exe -h\n"));
+ ShowHelp();
+ gAbort = ETrue;
+ break;
+ }
+ else if (token.Mid(0) == _L("-l"))
+ {
+ //Read OOM entry from KProcessTable and run
+ test.Printf(_L("SMPSOAK:lowmem\n"));
+ NumProcess = KNumProcess+1;
+ break;
+ }
+ else if (token.Mid(0) == _L("-b"))
+ {
+ test.Printf(_L("SMPSOAK: Test Silent Mode\n"));
+ ThreadPriorityLow = ETrue;
+ TestSilent = ETrue;
+ // If we have tests running in the background
+ // we want an endless loop
+ timeout = EFalse;
+ break;
+ }
+ else if (token.Left(2) == _L("-t"))
+ {
+ test.Printf(_L("SMPSOAK:Timeout\n"));
+ lex.SkipSpaceAndMark();
+ token.Set(lex.NextToken());
+ TLex lexNum(token);
+ lexNum.Val(gTimeout,EDecimal);
+ test.Printf(_L("Timeout in Seconds=%u \n"),gTimeout);
+ timeout = ETrue;
+ break;
+ }
+ else if (token.Left(2) == _L("-p"))
+ {
+ test.Printf(_L("SMPSOAK:period\n"));
+ lex.SkipSpaceAndMark();
+ token.Set(lex.NextToken());
+ TLex lexNum(token);
+ lexNum.Val(gPeriod,EDecimal);
+ test.Printf(_L("period in mSeconds=%d \n"),gPeriod);
+ Period = ETrue;
+ break;
+ }
+ else
+ {
+ test.Printf(_L("Error- Invalid SMPSOAK CMD Line Argument"));
+ break;
+ }
+ }
+ break;
+ }
+ }