1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/smpsoak/t_smpsoak.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,904 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\smpsoak\t_smpsoak.cpp
1.18 +
1.19 +// User Includes
1.20 +#include <e32hal.h>
1.21 +#include "t_smpsoak.h"
1.22 +
1.23 +void ParseCommandLine ();
1.24 +
1.25 +// Global Variables
1.26 +static TInt gPageSize;
1.27 +//Timeout 2 Minutes
1.28 +static TUint gTimeout = 120;
1.29 +
1.30 +//class for smpsoak thread and it creates memory, device, timer and spin threads.
1.31 +class CSMPSoakThread
1.32 + {
1.33 +public:
1.34 + CSMPSoakThread();
1.35 + ~CSMPSoakThread();
1.36 + void CreateThread();
1.37 + void ResumeThread();
1.38 + void CreateChildProcess(TInt aIndex);
1.39 + void ResumeChildProcess();
1.40 + void TerminateChildProcess();
1.41 +private:
1.42 + //Thread Functions
1.43 + static TInt SMPStressMemoryThread(TAny*);
1.44 + static TInt SMPStressDeviceThread(TAny*);
1.45 + static TInt SMPStressTimerThread(TAny*);
1.46 + static TInt SMPStressSpinThread(TAny*);
1.47 + //Thread Priority
1.48 + void DoCreateThread(TAny*);
1.49 + void SetThreadPriority();
1.50 +private:
1.51 + //Utils for memory thread
1.52 + void CreateChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
1.53 + void CommitChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
1.54 + void WriteReadChunk(TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr);
1.55 +private:
1.56 + //Memebers for threads
1.57 + TInt DoSMPStressMemoryThread();
1.58 + TInt DoSMPStressDeviceThread();
1.59 + TInt DoSMPStressTimerThread();
1.60 + TInt DoSMPStressSpinThread();
1.61 +private:
1.62 + TThreadData iThreadData;
1.63 + RProcess iProcess;
1.64 + RThread iThread;
1.65 + TInt iPriority;
1.66 +private:
1.67 +// Thread Data for each thread- low priority
1.68 +static TThread KThreadTableLow[];
1.69 +// Thread Data for each thread- high priority
1.70 +static TThread KThreadTableHigh[];
1.71 +//Process Data for each process
1.72 +static const TProcess KProcessTable[];
1.73 +//Memory table for memory thread
1.74 +static const TMemory KMemoryTable[];
1.75 +//Device table for device thread
1.76 +static const TDesC* KDeviceTable[];
1.77 +
1.78 + };
1.79 +TThread CSMPSoakThread::KThreadTableLow[] =
1.80 + {
1.81 + { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
1.82 + { _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
1.83 + { _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
1.84 + { _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
1.85 + { _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
1.86 + { _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
1.87 + { _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
1.88 + };
1.89 +TThread CSMPSoakThread::KThreadTableHigh[] =
1.90 + {
1.91 + { _L("Memory Thread"), CSMPSoakThread::SMPStressMemoryThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 250, 1, (TAny *)&KMemoryTable, NULL, NULL}},
1.92 + { _L("Device Thread"), CSMPSoakThread::SMPStressDeviceThread, {{EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow, EPriorityNormal, 0}, EPriorityList, KCpuAffinityAny, 300, 1, &KDeviceTable, NULL, NULL}},
1.93 + { _L("Spin Thread 0"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 200, 0, NULL, NULL, NULL}},
1.94 + { _L("Spin Thread 1"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 300, 0, NULL, NULL, NULL}},
1.95 + { _L("Spin Thread 2"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteVeryLow, EPriorityNormal}, EPriorityList, KCpuAffinityAny, 400, 0, NULL, NULL, NULL}},
1.96 + { _L("Spin Thread 3"), CSMPSoakThread::SMPStressSpinThread, {{EPriorityNormal, EPriorityNormal, EPriorityAbsoluteLow, EPriorityAbsoluteVeryLow}, EPriorityList, KCpuAffinityAny, 500, 0, NULL, NULL, NULL}},
1.97 + { _L("Timer Thread"), CSMPSoakThread::SMPStressTimerThread, {{EPriorityNormal, 0, 0, 0}, EPriorityList, KCpuAffinityAny, 1000, 4, NULL}},
1.98 + };
1.99 +const TProcess CSMPSoakThread::KProcessTable[] =
1.100 + {
1.101 + { _L("t_smpsoakprocess.exe"), _L("-W"), KCpuAffinityAny},
1.102 + { _L("t_smpsoakprocess.exe"), _L("-R"), KCpuAffinityAny},
1.103 + { _L("t_smpsoakprocess.exe"), _L("-F"), KCpuAffinityAny},
1.104 + { _L("t_smpsoakprocess.exe"), _L("-T"), KCpuAffinityAny},
1.105 + { _L("t_smpsoakprocess.exe"), _L("-O"), KCpuAffinityAny},
1.106 + };
1.107 +const TMemory CSMPSoakThread::KMemoryTable[] =
1.108 + {
1.109 + {_L(""), EChunkNormalThread, 0, 10, 100 },
1.110 + {_L("Global Chunk 1"), EChunkNormalThread, 0, 20, 200 },
1.111 + {_L(""), EChunkDisconnectedThread, 3, 30, 300 },
1.112 + {_L("Global Chunk 2"), EChunkDisconnectedThread, 4, 40, 400 },
1.113 + {_L(""), EChunkDoubleEndedThread, 5, 50, 500 },
1.114 + {_L("Global Chunk 3"), EChunkDoubleEndedThread, 6, 60, 600 },
1.115 + {_L(""), EChunkNormalProcess, 0, 10, 100 },
1.116 + {_L("Global Chunk 4"), EChunkNormalProcess, 0, 20, 200 },
1.117 + {_L(""), EChunkDisconnectedProcess, 3, 30, 300 },
1.118 + {_L("Global Chunk 5"), EChunkDisconnectedProcess, 4, 40, 400 },
1.119 + {_L(""), EChunkDoubleEndedProcess, 5, 50, 500 },
1.120 + {_L("Global Chunk 6"), EChunkDoubleEndedProcess, 6, 60, 600 },
1.121 + {_L(""), EChunkNone, 0, 0, 0 },
1.122 + };
1.123 +const TDesC* CSMPSoakThread::KDeviceTable[] =
1.124 + {
1.125 + &KDevices, &KDevLdd1, &KDevLdd1Name, &KDevLdd2, &KDevLdd2Name, &KDevLdd3, &KDevLdd3Name,
1.126 + &KDevLdd4, &KDevLdd4Name, &KDevLdd5, &KDevLdd5Name, NULL
1.127 + };
1.128 +
1.129 +//Constructor
1.130 +CSMPSoakThread::CSMPSoakThread()
1.131 + {
1.132 + }
1.133 +//Destructor
1.134 +CSMPSoakThread::~CSMPSoakThread()
1.135 + {
1.136 + }
1.137 +//All child process creation
1.138 +void CSMPSoakThread::CreateChildProcess(TInt aIndex)
1.139 + {
1.140 + if(TestSilent)
1.141 + gCmdLine.Format(KCmdLineBackground,(KProcessTable[aIndex].operation).Ptr());
1.142 + else if (Period)
1.143 + gCmdLine.Format(KCmdLinePeriod,gPeriod,(KProcessTable[aIndex].operation).Ptr());
1.144 + else
1.145 + gCmdLine.Format(KCmdLineProcess,(KProcessTable[aIndex].operation).Ptr());
1.146 +
1.147 + TInt r = iProcess.Create(KProcessTable[aIndex].processFileName,gCmdLine);
1.148 + test_KErrNone(r);
1.149 + iProcess.SetPriority(EPriorityLow);
1.150 + gSMPStressDrv.ChangeThreadAffinity(&iThread, KProcessTable[aIndex].cpuAffinity);
1.151 + PRINT ((_L("SetProcessPriority CPU %d Priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iProcess.Priority()));
1.152 + }
1.153 +//Terminate process when user press "Esc key"
1.154 +void CSMPSoakThread::ResumeChildProcess()
1.155 + {
1.156 + iProcess.Resume();
1.157 + }
1.158 +//Terminate process when user press "Esc key"
1.159 +void CSMPSoakThread::TerminateChildProcess()
1.160 + {
1.161 + iProcess.Kill(KErrNone);
1.162 + }
1.163 +//Changes the thread priority each time time, for each thread by Random, Increment, from List, Fixed.
1.164 +//pick up the priority option from thread table
1.165 +void CSMPSoakThread::SetThreadPriority()
1.166 + {
1.167 + static TInt64 randSeed = KRandSeed;
1.168 + static const TThreadPriority priorityTable[]=
1.169 + {
1.170 + EPriorityMuchLess, EPriorityLess, EPriorityNormal, EPriorityMore, EPriorityMuchMore,
1.171 + EPriorityRealTime, EPriorityRealTime, EPriorityAbsoluteVeryLow, EPriorityAbsoluteLowNormal,
1.172 + EPriorityAbsoluteLow, EPriorityAbsoluteBackgroundNormal, EPriorityAbsoluteBackground,
1.173 + EPriorityAbsoluteForegroundNormal, EPriorityAbsoluteForeground, EPriorityAbsoluteHighNormal, EPriorityAbsoluteHigh
1.174 + };
1.175 + TInt priorityIndex = 0;
1.176 + switch (iThreadData.threadPriorityChange)
1.177 + {
1.178 + case EpriorityFixed:
1.179 + break;
1.180 +
1.181 + case EPriorityList:
1.182 + if (++iPriority >= KPriorityOrder)
1.183 + iPriority = 0;
1.184 + if (iThreadData.threadPriorities[iPriority] == 0)
1.185 + iPriority = 0;
1.186 + // PRINT(_L("SetPriority List CPU %d index %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread),iPriority, iThreadData.threadPriorities[iPriority]);
1.187 + iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[iPriority]);
1.188 + break;
1.189 +
1.190 + case EPriorityIncrement:
1.191 + while (priorityTable[priorityIndex] <= iPriority)
1.192 + {
1.193 + priorityIndex++;
1.194 + }
1.195 + iPriority = priorityTable[priorityIndex];
1.196 + if (iPriority > iThreadData.threadPriorities[2])
1.197 + iPriority = iThreadData.threadPriorities[1];
1.198 + // PRINT(_L("SetPriority Increment CPU %d iPriority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
1.199 + iThread.SetPriority((TThreadPriority)iPriority);
1.200 + break;
1.201 +
1.202 + case EPriorityRandom:
1.203 + iPriority = Math::Rand(randSeed) % (iThreadData.threadPriorities[2] - iThreadData.threadPriorities[1] + 1);
1.204 + iPriority += iThreadData.threadPriorities[1];
1.205 + while (priorityTable[priorityIndex] < iPriority)
1.206 + {
1.207 + priorityIndex++;
1.208 + }
1.209 + iPriority = priorityTable[priorityIndex];
1.210 + // PRINT(_L("SetPriority Random CPU %d priority %d\n"),gSMPStressDrv.GetThreadCPU(&iThread), iPriority);
1.211 + iThread.SetPriority((TThreadPriority)iPriority);
1.212 + break;
1.213 + }
1.214 + }
1.215 +//Resume each thread
1.216 +void CSMPSoakThread::ResumeThread()
1.217 + {
1.218 + iThread.Resume();
1.219 + }
1.220 +//thread creation
1.221 +void CSMPSoakThread::CreateThread()
1.222 + {
1.223 + CSMPSoakThread* smpthread = new CSMPSoakThread[KNumThreads];
1.224 + for (TInt i = 0; i < KNumThreads ; i++)
1.225 + {
1.226 + if(ThreadPriorityLow)
1.227 + {
1.228 + PRINT ((_L("Thread Table - Priority Low \n")));
1.229 + smpthread[i].DoCreateThread(&KThreadTableLow[i]);
1.230 + }
1.231 + else
1.232 + {
1.233 + PRINT ((_L("Thread Table - Priority High \n")));
1.234 + smpthread[i].DoCreateThread(&KThreadTableHigh[i]);
1.235 + }
1.236 + }
1.237 + PRINT (_L("Resuming all threads\n"));
1.238 + for (TInt i = 0; i < KNumThreads; i++)
1.239 + smpthread[i].ResumeThread();
1.240 + }
1.241 +/**
1.242 + * CSMPSoakThread Thread Creation.
1.243 + * @param aIndex to exercise each row(thread) in the thread table
1.244 + *
1.245 + * @return N/A
1.246 + *
1.247 + * @pre Initialize thread Table values
1.248 + * @post None
1.249 + */
1.250 +void CSMPSoakThread::DoCreateThread(TAny* aThread)
1.251 + {
1.252 + //Initialize each thread data
1.253 + iThreadData = ((TThread*)aThread)->threadData;
1.254 + test.Next(_L("Create Thread"));
1.255 + PRINT ((_L("%s CPU affinity %d Priority %d\n"),((TThread*)aThread)->threadName.Ptr(),iThreadData.cpuAffinity,iThreadData.threadPriorities[0]));
1.256 + TInt r = iThread.Create(((TThread*)aThread)->threadName, ((TThread*)aThread)->threadFunction, KDefaultStackSize, KHeapMinSize, KHeapMaxSize,(TAny*)this);
1.257 + test_KErrNone(r);
1.258 + if (iThreadData.threadPriorityChange == EPriorityList)
1.259 + {
1.260 + iPriority = 0;
1.261 + }
1.262 + else
1.263 + {
1.264 + iPriority = iThreadData.threadPriorities[0];
1.265 + }
1.266 + iThread.SetPriority((TThreadPriority)iThreadData.threadPriorities[0]);
1.267 + //Set the thread CPU Affinity
1.268 + gSMPStressDrv.ChangeThreadAffinity(&iThread, iThreadData.cpuAffinity);
1.269 + }
1.270 +//Create Chunk - different types
1.271 +void CSMPSoakThread::CreateChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
1.272 + {
1.273 + //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);
1.274 + TOwnerType ownerType = EOwnerProcess;
1.275 + aChunkInfo->lastBottom = aMemoryTablePtr->initialBottom;
1.276 + aChunkInfo->lastTop = aMemoryTablePtr->initialTop;
1.277 + switch (aMemoryTablePtr->chunkType)
1.278 + {
1.279 + case EChunkNormalThread:
1.280 + ownerType = EOwnerThread; // drop through to create chunk
1.281 + case EChunkNormalProcess:
1.282 + if (aMemoryTablePtr->globalChunkName.Length())
1.283 + {
1.284 + test_KErrNone(aChunkInfo->chunk.CreateGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.285 + }
1.286 + else
1.287 + {
1.288 + test_KErrNone(aChunkInfo->chunk.CreateLocal(aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.289 + }
1.290 + aChunkInfo->lastBottom = 0; // ensure that this is zero
1.291 + break;
1.292 +
1.293 + case EChunkDisconnectedThread:
1.294 + ownerType = EOwnerThread; // drop through to create chunk
1.295 + case EChunkDisconnectedProcess:
1.296 + if (aMemoryTablePtr->globalChunkName.Length())
1.297 + {
1.298 + test_KErrNone(aChunkInfo->chunk.CreateDisconnectedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.299 + }
1.300 + else
1.301 + {
1.302 + test_KErrNone(aChunkInfo->chunk.CreateDisconnectedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.303 + }
1.304 + break;
1.305 +
1.306 + case EChunkDoubleEndedThread:
1.307 + ownerType = EOwnerThread; // drop through to create chunk
1.308 + case EChunkDoubleEndedProcess:
1.309 + if (aMemoryTablePtr->globalChunkName.Length())
1.310 + {
1.311 + test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedGlobal(aMemoryTablePtr->globalChunkName,aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.312 + }
1.313 + else
1.314 + {
1.315 + test_KErrNone(aChunkInfo->chunk.CreateDoubleEndedLocal(aMemoryTablePtr->initialBottom*gPageSize,aMemoryTablePtr->initialTop*gPageSize,aMemoryTablePtr->maxSize*gPageSize,ownerType));
1.316 + }
1.317 + break;
1.318 + }
1.319 + }
1.320 +//Commit chunk
1.321 +void CSMPSoakThread::CommitChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
1.322 + {
1.323 + TInt commitPages;
1.324 +
1.325 + switch (aMemoryTablePtr->chunkType)
1.326 + {
1.327 + case EChunkNormalThread:
1.328 + case EChunkNormalProcess:
1.329 + if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
1.330 + {
1.331 + aChunkInfo->lastTop += (aMemoryTablePtr->maxSize - 1 - aChunkInfo->lastTop) / 2 + 1;
1.332 + //PRINT(_L("Adjust chunk memory - top %d pagesize %d\n"),aChunkInfo->lastTop,gPageSize);
1.333 + test_KErrNone(aChunkInfo->chunk.Adjust(aChunkInfo->lastTop*gPageSize));
1.334 + }
1.335 + break;
1.336 +
1.337 + case EChunkDisconnectedThread:
1.338 + case EChunkDisconnectedProcess:
1.339 + commitPages = ((aChunkInfo->lastTop - aChunkInfo->lastBottom) / 2) + 1;
1.340 + //PRINT(_L("Decommitting from bottom %d of %d pages\n"),aChunkInfo->lastBottom,commitPages);
1.341 + test_KErrNone(aChunkInfo->chunk.Decommit(aChunkInfo->lastBottom*gPageSize,commitPages * gPageSize));
1.342 + if ((aChunkInfo->lastBottom > 0) && (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop))
1.343 + {
1.344 + aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
1.345 + aChunkInfo->lastBottom /= 2;
1.346 + commitPages = aChunkInfo->lastTop - aChunkInfo->lastBottom + 1;
1.347 + }
1.348 + else
1.349 + {
1.350 + if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize -1))
1.351 + {
1.352 + if (aChunkInfo->lastTop <= aMemoryTablePtr->initialTop)
1.353 + {
1.354 + aChunkInfo->lastBottom = aMemoryTablePtr->initialTop + 1;
1.355 + }
1.356 + else
1.357 + {
1.358 + aChunkInfo->lastBottom = aChunkInfo->lastTop + 1;
1.359 + }
1.360 + commitPages = ((aMemoryTablePtr->maxSize - aChunkInfo->lastBottom) / 2) + 1;
1.361 + aChunkInfo->lastTop = aChunkInfo->lastBottom + commitPages - 1;
1.362 + }
1.363 + else
1.364 + {
1.365 + commitPages = 0;
1.366 + }
1.367 + }
1.368 + if (commitPages)
1.369 + {
1.370 + //PRINT(_L("Commit chunk memory bottom %d size %d pages\n"),aChunkInfo->lastBottom,commitPages);
1.371 + test_KErrNone(aChunkInfo->chunk.Commit(aChunkInfo->lastBottom*gPageSize,commitPages*gPageSize));
1.372 + }
1.373 + break;
1.374 +
1.375 + case EChunkDoubleEndedThread:
1.376 + case EChunkDoubleEndedProcess:
1.377 + if (aChunkInfo->lastBottom > 0 || aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
1.378 + {
1.379 + if (aChunkInfo->lastBottom > 0)
1.380 + {
1.381 + aChunkInfo->lastBottom--;
1.382 + }
1.383 + if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
1.384 + {
1.385 + aChunkInfo->lastTop++;
1.386 + }
1.387 + // PRINT(_L("Adjust Double Ended bottom %d top %d\n"),aChunkInfo->lastBottom,aChunkInfo->lastTop);
1.388 + test_KErrNone(aChunkInfo->chunk.AdjustDoubleEnded(aChunkInfo->lastBottom*gPageSize,aChunkInfo->lastTop*gPageSize));
1.389 + }
1.390 + break;
1.391 + }
1.392 + }
1.393 +//Write then read chunk
1.394 +void CSMPSoakThread::WriteReadChunk (TChunkInfo * aChunkInfo, TMemory * aMemoryTablePtr)
1.395 + {
1.396 + if (aChunkInfo->lastTop < (aMemoryTablePtr->maxSize - 1))
1.397 + {
1.398 + TInt chunkSize = aChunkInfo->lastTop*gPageSize - aChunkInfo->lastBottom*gPageSize;
1.399 + //RDebug::Print(_L("WriteReadChunk Last Top %d lastBottom %d\n"),aChunkInfo->lastTop,aChunkInfo->lastBottom);
1.400 + TUint8 *writeaddr = aChunkInfo->chunk.Base()+ aChunkInfo->lastBottom*gPageSize;
1.401 + TPtr8 write(writeaddr,chunkSize);
1.402 + write.Copy(pattern,sizeof(pattern));
1.403 + test_KErrNone(Mem::Compare(writeaddr,sizeof(pattern),pattern,sizeof(pattern)));
1.404 + }
1.405 + }
1.406 +//Memory Thread : will do memory associated operation
1.407 +//param aSmp - CSMPSoakUtil pointer
1.408 +TInt CSMPSoakThread::SMPStressMemoryThread(TAny* aSmp)
1.409 + {
1.410 + CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
1.411 + __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressMemoryThread Panic"),0));
1.412 + return self->DoSMPStressMemoryThread();
1.413 + }
1.414 +// Member for thread function
1.415 +TInt CSMPSoakThread::DoSMPStressMemoryThread()
1.416 + {
1.417 + RTest test(_L("SMPStressMemoryThread"));
1.418 +
1.419 + TMemory *memoryTablePtr;
1.420 + TChunkInfo chunkTable[KNumChunks];
1.421 + TInt ctIndex = 0;
1.422 + test_KErrNone(UserHal::PageSizeInBytes(gPageSize));
1.423 +
1.424 + FOREVER
1.425 + {
1.426 + SetThreadPriority();
1.427 +
1.428 + if (gAbort)
1.429 + break;
1.430 +
1.431 + memoryTablePtr = (TMemory *) (iThreadData.listPtr);
1.432 + ctIndex = 0;
1.433 +
1.434 + //Create different type of chunks and write/read/verfiy it
1.435 + while (memoryTablePtr->chunkType != EChunkNone)
1.436 + {
1.437 + PRINT((_L("Create Chunk")));
1.438 + CreateChunk (&chunkTable[ctIndex],memoryTablePtr);
1.439 +
1.440 + PRINT(_L("Write and Read Chunk"));
1.441 + WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
1.442 +
1.443 + ctIndex++;
1.444 + memoryTablePtr++;
1.445 + }
1.446 +
1.447 + //Commit different type of chunks
1.448 + TBool anyCommit;
1.449 + do
1.450 + {
1.451 + anyCommit = EFalse;
1.452 + memoryTablePtr = (TMemory *) (iThreadData.listPtr);
1.453 + ctIndex = 0;
1.454 + while (memoryTablePtr->chunkType != EChunkNone)
1.455 + {
1.456 + //Commit Chunks
1.457 + PRINT((_L("Commit Chunk Memory")));
1.458 + PRINT ((_L("CommitChunk %d bottom %d top %d\n"),ctIndex,memoryTablePtr->initialBottom,memoryTablePtr->initialTop));
1.459 + CommitChunk (&chunkTable[ctIndex],memoryTablePtr);
1.460 + anyCommit = ETrue;
1.461 +
1.462 + //Write into Chunks
1.463 + WriteReadChunk (&chunkTable[ctIndex],memoryTablePtr);
1.464 + PRINT((_L("Write Read Chunk Size %d\n"), (memoryTablePtr->initialTop) - (memoryTablePtr->initialBottom)));
1.465 + ctIndex++;
1.466 + memoryTablePtr++;
1.467 + }
1.468 + }
1.469 + while (anyCommit);
1.470 +
1.471 + //Close the Chunks
1.472 + memoryTablePtr = (TMemory *) (iThreadData.listPtr);
1.473 + ctIndex = 0;
1.474 + while (memoryTablePtr->chunkType != EChunkNone)
1.475 + {
1.476 + chunkTable[ctIndex].chunk.Close();
1.477 +
1.478 + ctIndex++;
1.479 + memoryTablePtr++;
1.480 + }
1.481 + User::After(gPeriod);
1.482 + }
1.483 + return 0x00;
1.484 + }
1.485 +//Device Thread : will do device associated operation
1.486 +//param aSmp - CSMPSoakUtil pointer
1.487 +TInt CSMPSoakThread::SMPStressDeviceThread(TAny* aSmp)
1.488 + {
1.489 + CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
1.490 + __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressDeviceThread Panic"),0));
1.491 + return self->DoSMPStressDeviceThread();
1.492 + }
1.493 +// Member for thread function
1.494 +TInt CSMPSoakThread::DoSMPStressDeviceThread()
1.495 + {
1.496 + RTest test(_L("SMPStressDeviceThread"));
1.497 +
1.498 + RTimer timer;
1.499 + RFs session;
1.500 + TFileName sessionPath;
1.501 +
1.502 + test_KErrNone(timer.CreateLocal());
1.503 + TRequestStatus s;
1.504 +
1.505 + TDesC** ptrDevices = (TDesC**) (iThreadData.listPtr);
1.506 + PRINT ((_L("Devices Number %d [%s]\n"), ptrDevices[0]->Length(), ptrDevices[0]->Ptr()));
1.507 + for (TInt i = 1; ptrDevices[i] ; i++)
1.508 + PRINT ((_L("LDD%d=%s "),i,ptrDevices[i]->Ptr()));
1.509 + PRINT (_L("\n"));
1.510 +
1.511 + FOREVER
1.512 + {
1.513 + for (TInt i = 0; i < ptrDevices[0]->Length(); i++)
1.514 + {
1.515 + TText driveLetter = (*ptrDevices[0])[i];
1.516 + PRINT ((_L("Device %c\n"),driveLetter));
1.517 +
1.518 + test_KErrNone(session.Connect());
1.519 +
1.520 + sessionPath=(_L("?:\\SESSION_TEST\\"));
1.521 + sessionPath[0]=driveLetter;
1.522 + test_KErrNone(session.SetSessionPath(sessionPath));
1.523 +
1.524 + TInt driveNumber;
1.525 + test_KErrNone(session.CharToDrive(driveLetter, driveNumber));
1.526 +
1.527 + TBuf<64> fileSystemName;
1.528 + test_KErrNone(session.FileSystemName(fileSystemName,driveNumber));
1.529 +
1.530 + PRINT ((_L("File System Name %s\n"),fileSystemName.PtrZ()));
1.531 +
1.532 + TDriveInfo driveInfo;
1.533 + test_KErrNone(session.Drive(driveInfo, driveNumber));
1.534 +
1.535 + TVolumeInfo volumeInfo;
1.536 + test_KErrNone(session.Volume(volumeInfo, driveNumber));
1.537 +
1.538 + session.Close();
1.539 + }
1.540 + for (TInt i = 1; ptrDevices[i] ; i += 2)
1.541 + {
1.542 + RDevice device;
1.543 +
1.544 + TInt r = User::LoadLogicalDevice(*ptrDevices[i]);
1.545 + test(r == KErrNone || r == KErrAlreadyExists);
1.546 +
1.547 + test_KErrNone(device.Open(*ptrDevices[i+1]));
1.548 +
1.549 + TBuf8<64> deviceCaps;
1.550 + device.GetCaps(deviceCaps);
1.551 +
1.552 + TVersion deviceVersion;
1.553 + device.QueryVersionSupported(deviceVersion);
1.554 +
1.555 + device.Close();
1.556 + }
1.557 + SetThreadPriority();
1.558 + timer.After(s, iThreadData.delayTime*1000);
1.559 + User::WaitForRequest(s);
1.560 + test (s == KErrNone);
1.561 +
1.562 + if (gAbort)
1.563 + break;
1.564 + User::After(gPeriod);
1.565 + }
1.566 + timer.Close();
1.567 + PRINT((_L("SMPStressDeviceThread MyTimer.Cancel() called\n")));
1.568 + return 0x00;
1.569 + }
1.570 +//Spin Thread : will do thread sync
1.571 +//param aSmp - CSMPSoakUtil pointer
1.572 +TInt CSMPSoakThread::SMPStressSpinThread(TAny* aSmp)
1.573 + {
1.574 + CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
1.575 + __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressSpinThread Panic"),0));
1.576 + return self->DoSMPStressSpinThread();
1.577 + }
1.578 +// Member for thread function
1.579 +TInt CSMPSoakThread::DoSMPStressSpinThread()
1.580 + {
1.581 + RTest test(_L("SMPStressSpinThread"));
1.582 +
1.583 + TTime startTime;
1.584 + TTime endTime;
1.585 + TTimeIntervalMicroSeconds loopTimeMicroSeconds;
1.586 + PRINT (_L("SMPStressSpinThread\n"));
1.587 + FOREVER
1.588 + {
1.589 + SetThreadPriority();
1.590 + gSwitchSem.Wait();
1.591 + startTime.UniversalTime();
1.592 + do
1.593 + {
1.594 + endTime.UniversalTime();
1.595 + loopTimeMicroSeconds = endTime.MicroSecondsFrom(startTime);
1.596 + }while (loopTimeMicroSeconds <= iThreadData.delayTime*1000);
1.597 +
1.598 + if (gAbort)
1.599 + break;
1.600 + User::After(gPeriod);
1.601 + }
1.602 + return 0x00;
1.603 + }
1.604 +//Timer Thread : Timer operation and thread sync
1.605 +//param aSmp - CSMPSoakUtil pointer
1.606 +TInt CSMPSoakThread::SMPStressTimerThread(TAny* aSmp)
1.607 + {
1.608 + CSMPSoakThread* self = (CSMPSoakThread*)aSmp;
1.609 + __ASSERT_ALWAYS(self !=NULL, User::Panic(_L("CSMPSoakThread::SMPStressTimerThread Panic"),0));
1.610 + return self->DoSMPStressTimerThread();
1.611 + }
1.612 +// Member for thread function
1.613 +TInt CSMPSoakThread::DoSMPStressTimerThread()
1.614 + {
1.615 + RTest test(_L("SMPStressTimerThread"));
1.616 +
1.617 + PRINT (_L("SMPStressTimerThread\n"));
1.618 + RTimer timer;
1.619 + test_KErrNone(timer.CreateLocal());
1.620 + TRequestStatus s;
1.621 +
1.622 + FOREVER
1.623 + {
1.624 + timer.After(s, iThreadData.delayTime*1000);
1.625 + User::WaitForRequest(s);
1.626 + test (s == KErrNone);
1.627 + PRINT ((_L("*")));
1.628 + gSwitchSem.Signal(iThreadData.numThreads);
1.629 +
1.630 + if (gAbort)
1.631 + break;
1.632 + User::After(gPeriod);
1.633 + }
1.634 + timer.Cancel();
1.635 + PRINT((_L("SMPStressTimerThread MyTimer.Cancel() called\n")));
1.636 + return 0x00;
1.637 + }
1.638 +// CActive class to monitor KeyStrokes from User
1.639 +class CActiveConsole : public CActive
1.640 + {
1.641 +public:
1.642 + CActiveConsole();
1.643 + ~CActiveConsole();
1.644 + void GetCharacter();
1.645 + static TInt Callback(TAny* aCtrl);
1.646 + static CPeriodic* TimerL();
1.647 +private:
1.648 + // Defined as pure virtual by CActive;
1.649 + // implementation provided by this class.
1.650 + virtual void DoCancel();
1.651 + // Defined as pure virtual by CActive;
1.652 + // implementation provided by this class,
1.653 + virtual void RunL();
1.654 + void ProcessKeyPressL(TChar aChar);
1.655 +private:
1.656 +
1.657 + };
1.658 +// Class CActiveConsole
1.659 +CActiveConsole::CActiveConsole()
1.660 + : CActive(EPriorityHigh)
1.661 + {
1.662 + CActiveScheduler::Add(this);
1.663 + }
1.664 +
1.665 +CActiveConsole::~CActiveConsole()
1.666 + {
1.667 + Cancel();
1.668 + }
1.669 +CPeriodic* CActiveConsole::TimerL()
1.670 + {
1.671 + return(CPeriodic::NewL(EPriorityNormal));
1.672 + }
1.673 +// Callback function for timer expiry
1.674 +TInt CActiveConsole::Callback(TAny* aControl)
1.675 + {
1.676 + return KErrNone;
1.677 + }
1.678 +
1.679 +void CActiveConsole::GetCharacter()
1.680 + {
1.681 + test.Console()->Read(iStatus);
1.682 + SetActive();
1.683 + }
1.684 +
1.685 +void CActiveConsole::DoCancel()
1.686 + {
1.687 + PRINT(_L("CActiveConsole::DoCancel\n"));
1.688 + test.Console()->ReadCancel();
1.689 + }
1.690 +
1.691 +void CActiveConsole::ProcessKeyPressL(TChar aChar)
1.692 + {
1.693 + if (aChar == EKeyEscape)
1.694 + {
1.695 + PRINT(_L("CActiveConsole: ESC key pressed -> stopping active scheduler...\n"));
1.696 + gAbort = ETrue;
1.697 + CActiveScheduler::Stop();
1.698 + return;
1.699 + }
1.700 + aChar.UpperCase();
1.701 + GetCharacter();
1.702 + }
1.703 +
1.704 +void CActiveConsole::RunL()
1.705 + {
1.706 + ProcessKeyPressL(static_cast<TChar>(test.Console()->KeyCode()));
1.707 + }
1.708 +
1.709 +// CActiveTimer class to monitor timeout expiry
1.710 +class CActiveTimer : public CActive
1.711 + {
1.712 +public:
1.713 + CActiveTimer();
1.714 + ~CActiveTimer();
1.715 + void Delay(TTimeIntervalMicroSeconds32 aDelay);
1.716 +private:
1.717 + RTimer iTimer;
1.718 + // Defined as pure virtual by CActive;
1.719 + // implementation provided by this class.
1.720 + virtual void DoCancel();
1.721 + // Defined as pure virtual by CActive;
1.722 + // implementation provided by this class,
1.723 + virtual void RunL();
1.724 +
1.725 + };
1.726 +// Class CActiveConsole
1.727 +CActiveTimer::CActiveTimer()
1.728 + : CActive(EPriorityHigh)
1.729 + {
1.730 + CActiveScheduler::Add(this);
1.731 + User::LeaveIfError(iTimer.CreateLocal());
1.732 + }
1.733 +
1.734 +CActiveTimer::~CActiveTimer()
1.735 + {
1.736 + Cancel();
1.737 + iTimer.Close();
1.738 + }
1.739 +
1.740 +
1.741 +void CActiveTimer::Delay(TTimeIntervalMicroSeconds32 aDelay)
1.742 + {
1.743 + iTimer.After(iStatus, aDelay);
1.744 + SetActive();
1.745 + }
1.746 +
1.747 +void CActiveTimer::DoCancel()
1.748 + {
1.749 + iTimer.Cancel();
1.750 + }
1.751 +
1.752 +void CActiveTimer::RunL()
1.753 + {
1.754 + PRINT(_L("CActiveTimer: Application runtime expired..."));
1.755 + gAbort = ETrue;
1.756 + CActiveScheduler::Stop();
1.757 + return;
1.758 + }
1.759 +
1.760 +//T_SMPSOAK Entry Point
1.761 +TInt E32Main()
1.762 + {
1.763 + test.Title();
1.764 + __UHEAP_MARK;
1.765 + test.Start(_L("t_smpsoak.exe"));
1.766 +
1.767 + // When running as a stand alone test,
1.768 + // there needs to be a timeout
1.769 + timeout = ETrue;
1.770 +
1.771 + ParseCommandLine();
1.772 + if (gAbort)
1.773 + return 0x00;
1.774 +
1.775 + PRINT (_L("Load device driver\n"));
1.776 + TInt r = User::LoadLogicalDevice(_L("d_smpsoak.ldd"));
1.777 + if (r == KErrNotFound)
1.778 + {
1.779 + PRINT (_L("Test not supported on this platform because the D_SMPSOAK.LDD Driver is Not Present\n"));
1.780 + test(EFalse);
1.781 + }
1.782 + PRINT (_L("Calling SMPStressDrv Open\n"));
1.783 + r = gSMPStressDrv.Open();
1.784 + test_KErrNone(r);
1.785 +
1.786 + PRINT (_L("Creating our local semaphore\n"));
1.787 + r=gSwitchSem.CreateLocal(0);
1.788 + test_KErrNone(r);
1.789 +
1.790 + CSMPSoakThread smpthread;
1.791 + PRINT ((_L("Creating all threads =%d\n"),KNumThreads));
1.792 + smpthread.CreateThread();
1.793 +
1.794 + CSMPSoakThread *smpprocess= new CSMPSoakThread[NumProcess];
1.795 + PRINT ((_L("Creating all process =%d\n"),NumProcess));
1.796 + for (TInt i = 0; i < NumProcess; i++)
1.797 + smpprocess[i].CreateChildProcess(i);
1.798 +
1.799 + PRINT (_L("Resuming all process \n"));
1.800 + for (TInt i = 0; i < NumProcess; i++)
1.801 + smpprocess[i].ResumeChildProcess();
1.802 +
1.803 + PRINT (_L("Starting ActiveScheduler\n"));
1.804 + test.Next(_L("Press ESC Key to Shutdown SMPSoak...\n"));
1.805 + CActiveScheduler* myScheduler = new (ELeave) CActiveScheduler();
1.806 + test(myScheduler != NULL);
1.807 + CActiveScheduler::Install(myScheduler);
1.808 +
1.809 + CPeriodic* theTimer=NULL;
1.810 + TRAPD(ret,theTimer=CActiveConsole::TimerL())
1.811 + test_KErrNone(ret);
1.812 + theTimer->Start(0,KTimerPeriod,TCallBack(CActiveConsole::Callback));
1.813 + if(timeout)
1.814 + {
1.815 + CActiveTimer* myActiveTimer = new CActiveTimer();
1.816 + test(myActiveTimer != NULL);
1.817 + myActiveTimer->Delay(gTimeout*1000000);
1.818 + }
1.819 + CActiveConsole* myActiveConsole = new CActiveConsole();
1.820 + test(myActiveConsole != NULL);
1.821 + myActiveConsole->GetCharacter();
1.822 + CActiveScheduler::Start();
1.823 + if (gAbort)
1.824 + {
1.825 + PRINT (_L("gAbort TRUE \n"));
1.826 + for (TInt i = 0; i < NumProcess; i++)
1.827 + smpprocess[i].TerminateChildProcess();
1.828 + delete[] smpprocess;
1.829 + delete theTimer;
1.830 + gSMPStressDrv.Close();
1.831 + gSwitchSem.Close();
1.832 + return 0;
1.833 + }
1.834 + __UHEAP_MARKEND;
1.835 + test.End();
1.836 + return 0;
1.837 + }
1.838 +void ParseCommandLine()
1.839 + {
1.840 + TBuf<256> args;
1.841 + User::CommandLine(args);
1.842 + TLex lex(args);
1.843 + PRINT ((_L("****Command line = %s\n"), args.PtrZ()));
1.844 +
1.845 + FOREVER
1.846 + {
1.847 + TPtrC token=lex.NextToken();
1.848 + if(token.Length()!=0)
1.849 + {
1.850 + if (token.Length()==0)
1.851 + break; // ignore trailing whitespace
1.852 + else if (token.Mid(0) == _L("-h"))
1.853 + {
1.854 + PRINT (_L("T_SMPSOAK.EXE Usage Options:\n"));
1.855 + PRINT (_L("Type t_smpsoak.exe -h\n"));
1.856 + ShowHelp();
1.857 + gAbort = ETrue;
1.858 + break;
1.859 + }
1.860 + else if (token.Mid(0) == _L("-l"))
1.861 + {
1.862 + //Read OOM entry from KProcessTable and run
1.863 + test.Printf(_L("SMPSOAK:lowmem\n"));
1.864 + NumProcess = KNumProcess+1;
1.865 + break;
1.866 + }
1.867 + else if (token.Mid(0) == _L("-b"))
1.868 + {
1.869 + test.Printf(_L("SMPSOAK: Test Silent Mode\n"));
1.870 + ThreadPriorityLow = ETrue;
1.871 + TestSilent = ETrue;
1.872 + // If we have tests running in the background
1.873 + // we want an endless loop
1.874 + timeout = EFalse;
1.875 + break;
1.876 + }
1.877 + else if (token.Left(2) == _L("-t"))
1.878 + {
1.879 + test.Printf(_L("SMPSOAK:Timeout\n"));
1.880 + lex.SkipSpaceAndMark();
1.881 + token.Set(lex.NextToken());
1.882 + TLex lexNum(token);
1.883 + lexNum.Val(gTimeout,EDecimal);
1.884 + test.Printf(_L("Timeout in Seconds=%u \n"),gTimeout);
1.885 + timeout = ETrue;
1.886 + break;
1.887 + }
1.888 + else if (token.Left(2) == _L("-p"))
1.889 + {
1.890 + test.Printf(_L("SMPSOAK:period\n"));
1.891 + lex.SkipSpaceAndMark();
1.892 + token.Set(lex.NextToken());
1.893 + TLex lexNum(token);
1.894 + lexNum.Val(gPeriod,EDecimal);
1.895 + test.Printf(_L("period in mSeconds=%d \n"),gPeriod);
1.896 + Period = ETrue;
1.897 + break;
1.898 + }
1.899 + else
1.900 + {
1.901 + test.Printf(_L("Error- Invalid SMPSOAK CMD Line Argument"));
1.902 + break;
1.903 + }
1.904 + }
1.905 + break;
1.906 + }
1.907 + }