1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/smp_demo/smp_demo.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,544 @@
1.4 +// Copyright (c) 2006-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\smp_demo\smp_demo.cpp
1.18 +// Demonstration for SMP
1.19 +//
1.20 +//
1.21 +
1.22 +#include <e32test.h>
1.23 +#include <u32hal.h>
1.24 +#include <e32svr.h>
1.25 +#include <f32file.h>
1.26 +#include <hal.h>
1.27 +#include <e32math.h>
1.28 +
1.29 +RTest test(_L("SMP_DEMO"));
1.30 +
1.31 +#define DEBUG_PRINT(__args) test.Printf __args ;
1.32 +
1.33 +TBool TestThreadsExit = EFalse;
1.34 +_LIT(KTestBlank, "");
1.35 +
1.36 +
1.37 +//#define LOCK_TYPE RMutex
1.38 +//#define LOCK_TYPE_CREATE_PARAM
1.39 +#define LOCK_TYPE RFastLock
1.40 +#define LOCK_TYPE_CREATE_PARAM
1.41 +//#define LOCK_TYPE RSemaphore
1.42 +//#define LOCK_TYPE_CREATE_PARAM 0
1.43 +
1.44 +#define MAX_THREADS 8
1.45 +#define MAX_CHAPTERS 28
1.46 +
1.47 +TUint8 TestGuess[MAX_THREADS];
1.48 +TInt TestGuessReady[MAX_THREADS];
1.49 +LOCK_TYPE TestGuessLock[MAX_THREADS];
1.50 +
1.51 +TInt TestGuessChanged[MAX_THREADS];
1.52 +LOCK_TYPE TestChangedLock[MAX_THREADS];
1.53 +TUint8 TestNext[MAX_THREADS];
1.54 +
1.55 +TUint TestGuessMisses[MAX_THREADS];
1.56 +TUint TestGuessCorrect[MAX_THREADS];
1.57 +TUint TestGuessIncorrect[MAX_THREADS];
1.58 +TUint TestGuessCollision[MAX_THREADS];
1.59 +TInt TestCpuCount = 0;
1.60 +
1.61 +TBool TestUseMathRandom = ETrue;
1.62 +TBool TestSingleCpu = EFalse;
1.63 +TBool TestDualCpu = EFalse;
1.64 +TBool TestNoPrint = EFalse;
1.65 +TBool TestSingleThread = EFalse;
1.66 +TBool TestUseAffinity = ETrue;
1.67 +
1.68 +TInt LoadChapter(TInt chapterIndex, HBufC8 **aChapterPtrPtr)
1.69 + {
1.70 + RFile file;
1.71 + RFs fs;
1.72 + if (KErrNone != fs.Connect())
1.73 + {
1.74 + DEBUG_PRINT(_L("LoadChapter : Can't connect to the FS\n"));
1.75 + return KErrGeneral;
1.76 + }
1.77 +
1.78 + TBuf<32> filename;
1.79 + filename.Format(_L("z:\\Test\\war_and_peace_ch%d.txt"), chapterIndex);
1.80 +
1.81 + TInt ret = file.Open(fs,filename,EFileRead);
1.82 + if (ret == KErrNone)
1.83 + {
1.84 + TInt fileSize = 0;
1.85 + ret = file.Size(fileSize);
1.86 + if (ret == KErrNone)
1.87 + {
1.88 + HBufC8 *theBuf = HBufC8::New(fileSize + 10);
1.89 + if (theBuf != NULL)
1.90 + {
1.91 + TPtr8 des2=theBuf->Des();
1.92 + ret = file.Read((TInt)0, des2,fileSize);
1.93 + if (ret == KErrNone)
1.94 + {
1.95 + *aChapterPtrPtr = theBuf;
1.96 + }
1.97 + else
1.98 + {
1.99 + DEBUG_PRINT((_L("LoadChapter : Read Failed for %S of %d\n"), &filename, fileSize));
1.100 + }
1.101 + }
1.102 + else
1.103 + {
1.104 + DEBUG_PRINT((_L("LoadChapter : Buffer Alloc Failed for %S\n"), &filename));
1.105 + }
1.106 + }
1.107 + else
1.108 + {
1.109 + DEBUG_PRINT((_L("LoadChapter : Size Failed for %S\n"), &filename));
1.110 + }
1.111 + file.Close();
1.112 + }
1.113 + else
1.114 + {
1.115 + DEBUG_PRINT((_L("LoadChapter : Open Failed for %S\n"), &filename));
1.116 + }
1.117 +
1.118 + return ret;
1.119 + }
1.120 +
1.121 +TInt SetCpuAffinity(TInt aThreadId)
1.122 + {
1.123 + if (TestUseAffinity)
1.124 + {
1.125 + TUint32 cpu;
1.126 +
1.127 + if (TestCpuCount == 4)
1.128 + cpu = (TUint32)(aThreadId % 3) + 1;
1.129 + else if (TestCpuCount == 2)
1.130 + cpu = (TUint32)1;
1.131 + else
1.132 + cpu = 0;
1.133 +
1.134 + TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
1.135 + test(r==KErrNone);
1.136 + return r;
1.137 + }
1.138 + return KErrNone;
1.139 + }
1.140 +
1.141 +
1.142 +LOCAL_C TInt DemoThread(TAny* aUseTb)
1.143 + {
1.144 + TInt threadId = (TInt)aUseTb;
1.145 +
1.146 + SetCpuAffinity(threadId);
1.147 + User::After(100);
1.148 +
1.149 + TestGuessChanged[threadId] = EFalse;
1.150 + TestGuessReady[threadId] = EFalse;
1.151 + TestGuessMisses[threadId] = 0;
1.152 + TestGuessCorrect[threadId] = 0;
1.153 + TestGuessIncorrect[threadId] = 0;
1.154 + TestGuessCollision[threadId] = 0;
1.155 +
1.156 + TUint8 guess = 0;
1.157 + TUint8 nextChar = TestNext[threadId];
1.158 + TBool correct = EFalse;
1.159 +
1.160 + while (!TestThreadsExit)
1.161 + {
1.162 + correct = EFalse;
1.163 +
1.164 + if (TestUseMathRandom)
1.165 + guess = (TUint8)Math::Random();
1.166 + else
1.167 + guess ++;
1.168 +
1.169 + if (TestGuessChanged[threadId])
1.170 + {
1.171 + TestChangedLock[threadId].Wait();
1.172 + nextChar = TestNext[threadId];
1.173 + TestGuessChanged[threadId] = EFalse;
1.174 + TestChangedLock[threadId].Signal();
1.175 + }
1.176 + correct = (nextChar == guess);
1.177 +
1.178 + if (correct)
1.179 + {
1.180 + if (TestGuessReady[threadId] == EFalse)
1.181 + {
1.182 + TestGuessLock[threadId].Wait();
1.183 + TestGuess[threadId] = guess;
1.184 + TestGuessReady[threadId] = ETrue;
1.185 + TestGuessLock[threadId].Signal();
1.186 + TestGuessCorrect[threadId] ++;
1.187 + }
1.188 + else
1.189 + {
1.190 + TestGuessMisses[threadId] ++;
1.191 + }
1.192 + }
1.193 + else
1.194 + {
1.195 + TestGuessIncorrect[threadId] ++;
1.196 + }
1.197 + if (TestCpuCount == 1)
1.198 + {
1.199 + User::After(0);
1.200 + }
1.201 + }
1.202 + return KErrNone;
1.203 + }
1.204 +
1.205 +TInt NumberOfCpus()
1.206 + {
1.207 + TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
1.208 + test(r>0);
1.209 + return r;
1.210 + }
1.211 +
1.212 +TInt ParseArgs(void)
1.213 + {
1.214 + TBuf<256> args;
1.215 + User::CommandLine(args);
1.216 + TLex lex(args);
1.217 +
1.218 + FOREVER
1.219 + {
1.220 + TPtrC token=lex.NextToken();
1.221 + if(token.Length()!=0)
1.222 + {
1.223 + if (token == _L("unbound"))
1.224 + {
1.225 + TestUseMathRandom = EFalse;
1.226 + }
1.227 + if (token == _L("single"))
1.228 + {
1.229 + TestSingleCpu = ETrue;
1.230 + }
1.231 + if (token == _L("dual"))
1.232 + {
1.233 + TestDualCpu = ETrue;
1.234 + }
1.235 + if (token == _L("silent"))
1.236 + {
1.237 + TestNoPrint = ETrue;
1.238 + }
1.239 + if (token == _L("onethread"))
1.240 + {
1.241 + TestSingleCpu = ETrue;
1.242 + TestSingleThread = ETrue;
1.243 + }
1.244 + if (token == _L("help"))
1.245 + {
1.246 + test.Printf(_L("smp_demo: unbound | single | onethread | silent | dual | noaffinity | help \n"));
1.247 + return -1;
1.248 + }
1.249 + if (token == _L("noaffinity"))
1.250 + {
1.251 + TestUseAffinity = EFalse;
1.252 + }
1.253 + }
1.254 + else
1.255 + {
1.256 + break;
1.257 + }
1.258 + }
1.259 + return KErrNone;
1.260 + }
1.261 +
1.262 +TInt E32Main()
1.263 + {
1.264 + test.Title();
1.265 + test.Start(_L("SMP Demonstration guessing War and Peace...."));
1.266 +
1.267 + if (ParseArgs() != KErrNone)
1.268 + {
1.269 + test.Getch();
1.270 + test.End();
1.271 + return KErrNone;
1.272 + }
1.273 +
1.274 + TUint start = User::TickCount();
1.275 + TInt tickPeriod = 0;
1.276 + HAL::Get(HAL::ESystemTickPeriod, tickPeriod);
1.277 +
1.278 + if (TestSingleCpu)
1.279 + {
1.280 + TestCpuCount = 1;
1.281 + }
1.282 + else if (TestDualCpu)
1.283 + {
1.284 + TestCpuCount = 2;
1.285 + }
1.286 + else
1.287 + {
1.288 + TestCpuCount = NumberOfCpus();
1.289 + }
1.290 +
1.291 + DEBUG_PRINT((_L("CPU Count %d\n"), TestCpuCount));
1.292 +
1.293 + TRequestStatus theStatus[MAX_THREADS];
1.294 + RThread theThreads[MAX_THREADS];
1.295 + TBool threadInUse[MAX_THREADS];
1.296 +
1.297 + TInt index;
1.298 + TInt maxChapters = MAX_CHAPTERS;
1.299 +
1.300 + if (TestUseMathRandom)
1.301 + {
1.302 + maxChapters = 2;
1.303 + }
1.304 +
1.305 + TInt maxIndex = TestCpuCount - 1;
1.306 + if (maxIndex == 0)
1.307 + {
1.308 + maxChapters = 2;
1.309 + maxIndex = 1;
1.310 + }
1.311 + else if ((maxIndex == 1) && (TestUseMathRandom))
1.312 + {
1.313 + maxChapters = 4;
1.314 + }
1.315 +
1.316 + TInt ret;
1.317 + TUint32 cpu = 0;
1.318 +
1.319 + if (TestUseAffinity)
1.320 + {
1.321 + UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
1.322 + }
1.323 +
1.324 + if (TestSingleThread)
1.325 + {
1.326 + TInt chapterIndex;
1.327 + TUint8 guess = 0;
1.328 +
1.329 + maxChapters = MAX_CHAPTERS;
1.330 +
1.331 + TRequestStatus keyStatus;
1.332 + CConsoleBase* console=test.Console();
1.333 +
1.334 + console->Read(keyStatus);
1.335 +
1.336 + for (chapterIndex = 0; chapterIndex < maxChapters; chapterIndex ++)
1.337 + {
1.338 + HBufC8 *chapterPtr = NULL;
1.339 + ret = LoadChapter(chapterIndex + 1, &chapterPtr);
1.340 + if ((ret != KErrNone) || (chapterPtr == NULL))
1.341 + {
1.342 + DEBUG_PRINT((_L("E32Main: LoadChapter failed %d\n"), ret));
1.343 + }
1.344 + else
1.345 + {
1.346 + TPtr8 theDes = chapterPtr->Des();
1.347 + TUint8 *pData = (TUint8 *)theDes.Ptr();
1.348 + TInt dataLength = chapterPtr->Length();
1.349 +
1.350 +
1.351 + while (dataLength > 0)
1.352 + {
1.353 + if (TestUseMathRandom)
1.354 + guess = (TUint8)Math::Random();
1.355 + else
1.356 + guess ++;
1.357 +
1.358 + if (*pData == guess)
1.359 + {
1.360 + pData ++;
1.361 + dataLength --;
1.362 + if (!TestNoPrint)
1.363 + {
1.364 + test.Printf(_L("%c"), (TUint8)guess);
1.365 + }
1.366 + }
1.367 + if (keyStatus != KRequestPending)
1.368 + {
1.369 + if (console->KeyCode() == EKeyEscape)
1.370 + {
1.371 + TestThreadsExit = ETrue;
1.372 + break;
1.373 + }
1.374 + console->Read(keyStatus);
1.375 + }
1.376 + }
1.377 + // clean up
1.378 + delete chapterPtr;
1.379 + test.Printf(_L("\n\n"));
1.380 + if (TestThreadsExit)
1.381 + {
1.382 + break;
1.383 + }
1.384 + }
1.385 + }
1.386 + console->ReadCancel();
1.387 + test.Printf(_L("Finished after %d chapters!\n"),chapterIndex);
1.388 + }
1.389 + else
1.390 + {
1.391 + for (index = 0; index < maxIndex; index ++)
1.392 + {
1.393 + TestGuessLock[index].CreateLocal(LOCK_TYPE_CREATE_PARAM);
1.394 + TestChangedLock[index].CreateLocal(LOCK_TYPE_CREATE_PARAM);
1.395 + ret = theThreads[index].Create(KTestBlank,DemoThread,KDefaultStackSize,NULL,(TAny*) index);
1.396 + if (ret == KErrNone)
1.397 + {
1.398 + theThreads[index].Logon(theStatus[index]);
1.399 + if (theStatus[index] != KRequestPending)
1.400 + {
1.401 + DEBUG_PRINT((_L("E32Main: !KRequestPending %d\n"), theStatus[index].Int() ));
1.402 + }
1.403 + theThreads[index].Resume();
1.404 + threadInUse[index] = ETrue;
1.405 + DEBUG_PRINT((_L("E32Main: starting thread %d %d\n"), index, index % TestCpuCount));
1.406 + }
1.407 + else
1.408 + {
1.409 + DEBUG_PRINT((_L("E32Main: Create thread failed %d\n"), ret));
1.410 + return KErrGeneral;
1.411 + }
1.412 + }
1.413 +
1.414 + TInt chapterIndex;
1.415 + TInt index2;
1.416 +
1.417 + TRequestStatus keyStatus;
1.418 + CConsoleBase* console=test.Console();
1.419 +
1.420 + console->Read(keyStatus);
1.421 +
1.422 + for (chapterIndex = 0; chapterIndex < maxChapters; chapterIndex ++)
1.423 + {
1.424 + HBufC8 *chapterPtr = NULL;
1.425 + ret = LoadChapter(chapterIndex + 1, &chapterPtr);
1.426 + if ((ret != KErrNone) || (chapterPtr == NULL))
1.427 + {
1.428 + DEBUG_PRINT((_L("E32Main: LoadChapter failed %d\n"), ret));
1.429 + }
1.430 + else
1.431 + {
1.432 + TPtr8 theDes = chapterPtr->Des();
1.433 + TUint8 *pData = (TUint8 *)theDes.Ptr();
1.434 + TInt dataLength = chapterPtr->Length();
1.435 + for (index2 = 0; index2 < maxIndex; index2 ++)
1.436 + {
1.437 + TestChangedLock[index2].Wait();
1.438 + TestGuessChanged[index2] = ETrue;
1.439 + TestNext[index2] = (TUint8)*pData;
1.440 + TestChangedLock[index2].Signal();
1.441 + }
1.442 + // where the real code goes!!
1.443 + TUint8 guess = 0;
1.444 + TBool wasReady = EFalse;
1.445 + while (dataLength > 0)
1.446 + {
1.447 + for (index = 0; index < maxIndex; index ++)
1.448 + {
1.449 + wasReady = EFalse;
1.450 + if (TestGuessReady[index])
1.451 + {
1.452 + wasReady = ETrue;
1.453 + TestGuessLock[index].Wait();
1.454 + guess = (TUint8)TestGuess[index];
1.455 + TestGuessReady[index] = EFalse;
1.456 + TestGuessLock[index].Signal();
1.457 + }
1.458 + if (wasReady)
1.459 + {
1.460 + if (*pData == guess)
1.461 + {
1.462 + pData ++;
1.463 + dataLength --;
1.464 + for (index2 = 0; index2 < maxIndex; index2 ++)
1.465 + {
1.466 + TestChangedLock[index2].Wait();
1.467 + TestNext[index2] = (TUint8)*pData;
1.468 + TestGuessChanged[index2] = ETrue;
1.469 + TestChangedLock[index2].Signal();
1.470 + }
1.471 + if (!TestNoPrint)
1.472 + {
1.473 + test.Printf(_L("%c"), (TUint8)guess);
1.474 + }
1.475 + }
1.476 + else
1.477 + {
1.478 + TestGuessCollision[index] ++;
1.479 + }
1.480 + }
1.481 + if (TestCpuCount == 1)
1.482 + {
1.483 + User::After(0);
1.484 + }
1.485 + }
1.486 + if (keyStatus != KRequestPending)
1.487 + {
1.488 + if (console->KeyCode() == EKeyEscape)
1.489 + {
1.490 + TestThreadsExit = ETrue;
1.491 + break;
1.492 + }
1.493 + console->Read(keyStatus);
1.494 + }
1.495 + }
1.496 + // clean up
1.497 + delete chapterPtr;
1.498 + test.Printf(_L("\n\n"));
1.499 + if (TestThreadsExit)
1.500 + {
1.501 + break;
1.502 + }
1.503 + }
1.504 + }
1.505 +
1.506 + console->ReadCancel();
1.507 +
1.508 + test.Printf(_L("Finished after %d chapters!\n"),chapterIndex);
1.509 + for (index = 0; index < maxIndex; index ++)
1.510 + {
1.511 + test.Printf(_L("Thread %d stalls %u correct %u incorrect %u collision %u\n"), index, TestGuessMisses[index],TestGuessCorrect[index],TestGuessIncorrect[index], TestGuessCollision[index]);
1.512 + }
1.513 +
1.514 + // real code ends!!
1.515 + TestThreadsExit = ETrue;
1.516 +
1.517 + TBool anyUsed = ETrue;
1.518 +
1.519 + while(anyUsed)
1.520 + {
1.521 + anyUsed = EFalse;
1.522 +
1.523 + for (index = 0; index < maxIndex; index++)
1.524 + {
1.525 + if (threadInUse[index])
1.526 + {
1.527 + if (theThreads[index].ExitType() != EExitPending)
1.528 + {
1.529 + threadInUse[index] = EFalse;
1.530 + TestGuessLock[index].Close();
1.531 + TestChangedLock[index].Close();
1.532 + }
1.533 + else
1.534 + {
1.535 + anyUsed = ETrue;
1.536 + }
1.537 + }
1.538 + }
1.539 + }
1.540 + }
1.541 + TUint time = TUint((TUint64)(User::TickCount()-start)*(TUint64)tickPeriod/(TUint64)1000000);
1.542 + test.Printf(_L("Complete in %u seconds\n"), time);
1.543 + test.Getch();
1.544 + test.End();
1.545 + return KErrNone;
1.546 + }
1.547 +