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