Update contrib.
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\misc\t_cputime.cpp
15 // Tests User::FastCounter() and RThread::GetCpuTime()
16 // Note: This test only works on the emulator when run in textshell mode. The
17 // reason for this is that is assumes that it will be able to use 100% of CPU
18 // time, but when techview is starting up there are many other threads consuming
31 RTest test(_L("T_CPUTIME"));
36 const TInt KLongWait = 3000000; // 3 seconds
37 const TInt KShortWait = 100000; // 0.1 seconds
38 const TInt KTolerance = 1000; // 1 ms
39 const TInt numCpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
41 #define FailIfError(EXPR) \
44 if (aErr != KErrNone) \
46 test.Printf(_L("Return code == %d\n"), aErr); \
58 TBool GetCpuTimeIsSupported()
61 TTimeIntervalMicroSeconds time;
62 TInt err = thread.GetCpuTime(time);
63 test(err == KErrNone || err == KErrNotSupported);
64 return err == KErrNone;
67 TInt SetCpuAffinity(TInt aCore)
69 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)aCore, 0);
75 //! @SYMTestCaseID t_cputime_0
77 //! @SYMTestCaseDesc Fast counter tests
78 //! @SYMREQ CR RFID-66JJKX
79 //! @SYMTestActions Compares the high res timer against the nanokernel microsecond tick
80 //! @SYMTestExpectedResults The differnce measured should be < 1%
81 //! @SYMTestPriority High
82 //! @SYMTestStatus Defined
83 void TestFastCounter()
85 test.Start(_L("Comparing NTickCount with FastCounter"));
88 FailIfError(HAL::Get(HAL::ENanoTickPeriod, tickPeriod));
89 test.Printf(_L(" tick period == %d\n"), tickPeriod);
92 FailIfError(HAL::Get(HAL::EFastCounterFrequency, countFreq));
93 test.Printf(_L(" count freq == %d\n"), countFreq);
96 FailIfError(HAL::Get(HAL::EFastCounterCountsUp, fcCountsUp));
97 test.Printf(_L(" count dir == %S\n"), fcCountsUp ? &KUp : &KDown);
99 TUint startTick = User::NTickCount();
100 TUint startCount = User::FastCounter();
102 User::After(KLongWait);
104 TUint endTick = User::NTickCount();
105 TUint endCount = User::FastCounter();
107 TInt tickDiff = endTick - startTick;
108 TInt countDiff = fcCountsUp ? (endCount - startCount) : (startCount - endCount);
110 test.Printf(_L(" tick difference == %d\n"), tickDiff);
111 test.Printf(_L(" fast count difference == %d\n"), countDiff);
113 TInt elapsedTickUs = tickDiff * tickPeriod;
114 TInt elapsedCountUs = (TInt)(((TInt64)1000000 * countDiff) / countFreq);
116 test.Printf(_L(" tick time == %d\n"), elapsedTickUs);
117 test.Printf(_L(" count time == %d\n"), elapsedCountUs);
119 TReal diff = (100.0 * Abs(elapsedCountUs - elapsedTickUs)) / elapsedTickUs;
121 test.Printf(_L(" %% difference == %f\n"), diff);
126 TInt ThreadFunction(TAny* aParam)
130 TInt& core = (static_cast<TThreadParam*>(aParam))->iCpu;
131 FailIfError(SetCpuAffinity(core));
134 RSemaphore& semaphore = (static_cast<TThreadParam*>(aParam))->iSem;
142 void EnsureSystemIdle()
144 // This test assumes 100% cpu resource is available, so it can fail on
145 // windows builds if something else is running in the background. This
146 // function attempts to wait for the system to become idle.
150 const TInt KMaxWait = 60 * 1000000;
151 const TInt KSampleTime = 1 * 1000000;
152 const TInt KWaitTime = 5 * 1000000;
154 test.Start(_L("Waiting for system to become idle"));
159 test(totalTime < KMaxWait);
161 TThreadParam threadParam;
162 FailIfError((threadParam.iSem).CreateLocal(0));
163 threadParam.iCpu = 1;
166 FailIfError(thread.Create(_L("Thread"), ThreadFunction, 1024, NULL, &threadParam));
167 thread.SetPriority(EPriorityLess);
170 User::After(KShortWait); // Pause to allow thread setup
172 (threadParam.iSem).Signal();
173 User::After(KSampleTime);
176 TTimeIntervalMicroSeconds time;
177 FailIfError(thread.GetCpuTime(time));
178 TReal error = (100.0 * Abs(time.Int64() - KSampleTime)) / KSampleTime;
179 test.Printf(_L(" time == %ld, error == %f%%\n"), time, error);
183 thread.Kill(KErrNone);
184 TRequestStatus status;
185 thread.Logon(status);
186 User::WaitForRequest(status);
187 test(status == KErrNone);
188 CLOSE_AND_WAIT(thread);
190 (threadParam.iSem).Close();
193 User::After(KWaitTime); // Allow system to finish whatever it's doing
195 totalTime += KShortWait + KSampleTime + KWaitTime;
204 //! @SYMTestCaseID t_cputime_1
206 //! @SYMTestCaseDesc Thread CPU time tests
207 //! @SYMREQ CR RFID-66JJKX
208 //! @SYMTestActions Tests cpu time when a thread is put through the various states
209 //! @SYMTestExpectedResults Reported cpu time increses only when the thread is running
210 //! @SYMTestPriority High
211 //! @SYMTestStatus Defined
212 void TestThreadCpuTime()
214 test.Start(_L("CPU thread time unit tests"));
216 TThreadParam threadParam;
217 FailIfError((threadParam.iSem).CreateLocal(0));
218 threadParam.iCpu = 0; // Later tests will exercise other CPUs
224 FailIfError(thread.Create(_L("Thread"), ThreadFunction, 1024, NULL, &threadParam));
225 thread.SetPriority(EPriorityLess);
226 FailIfError(u.Create());
227 FailIfError(u.Logon(s,h));
228 test(s==KRequestPending);
230 TTimeIntervalMicroSeconds time, time2;
232 // Test time is initially zero
233 FailIfError(thread.GetCpuTime(time));
236 // Test not increased while waiting on semaphore
238 User::After(KShortWait);
239 FailIfError(thread.GetCpuTime(time));
240 test(time < KTolerance); // wait happens in less than 0.5ms
242 // Test increases when thread allowed to run
243 (threadParam.iSem).Signal();
244 User::After(KShortWait);
245 FailIfError(thread.GetCpuTime(time));
246 test(time > (KShortWait - KTolerance));
248 // Test not increased while suspended
250 FailIfError(thread.GetCpuTime(time));
251 User::After(KShortWait);
252 FailIfError(thread.GetCpuTime(time2));
256 // Test not increased while dead
257 thread.Kill(KErrNone);
258 User::WaitForRequest(s); // wait on undertaker since that completes in supervisor thread
259 FailIfError(thread.GetCpuTime(time));
260 User::After(KShortWait);
261 FailIfError(thread.GetCpuTime(time2));
266 test(t.Id()==thread.Id());
270 (threadParam.iSem).Close();
274 //! @SYMTestCaseID t_cputime_2
276 //! @SYMTestCaseDesc Thread CPU time tests
277 //! @SYMREQ CR RFID-66JJKX
278 //! @SYMTestActions Tests cpu time when multiple threads are running
279 //! @SYMTestExpectedResults Total time is divided evenly among running threads
280 //! @SYMTestPriority High
281 //! @SYMTestStatus Defined
283 TBool DoTestThreadCpuTime2() // Returns ETrue if test passed
285 test.Start(_L("Testing time shared between threads"));
289 test.Printf(_L("** SMP system detected - not testing time shared between threads until load balancing optimized **\n"));
293 const TInt KMaxThreads = 4;
295 TThreadParam threadParam;
297 RThread* threads = NULL;
298 threads = new(ELeave) RThread[numCpus*KMaxThreads];
299 FailIfError((threadParam.iSem).CreateLocal(0));
302 for (TInt numThreads = 1 ; pass && numThreads <= KMaxThreads ; ++numThreads)
304 test.Printf(_L(" testing with %d threads on each of %d CPUs:\n"), numThreads, numCpus);
307 for (i = 0 ; i < numThreads ; ++i)
309 for (j = 0 ; j < numCpus ; ++j)
312 name.AppendFormat(_L("Thread%d%d"), i, j);
313 threadParam.iCpu = j;
315 FailIfError(threads[k].Create(name, ThreadFunction, 1024, NULL, &threadParam));
316 threads[k].SetPriority(EPriorityLess);
321 User::After(KShortWait); // Pause to allow thread setup
323 (threadParam.iSem).Signal(numThreads*numCpus);
324 User::After(KLongWait);
325 for (i = 0 ; i < numThreads ; ++i)
326 for (j = 0 ; j < numCpus ; ++j)
327 threads[i+j*KMaxThreads].Suspend();
329 TInt expected = KLongWait / numThreads;
330 for (i = 0 ; i < numThreads ; ++i)
332 for (j = 0 ; j < numCpus ; ++j)
335 TTimeIntervalMicroSeconds time;
336 FailIfError(threads[k].GetCpuTime(time));
338 TReal error = (100.0 * Abs(time.Int64() - expected)) / expected;
340 test.Printf(_L(" %d%d: time == %ld, error == %d%%\n"), i, j, time.Int64(), TInt(error));
345 threads[k].Kill(KErrNone);
346 TRequestStatus status;
347 threads[k].Logon(status);
348 User::WaitForRequest(status);
349 test(status == KErrNone);
350 CLOSE_AND_WAIT(threads[k]);
355 (threadParam.iSem).Close();
361 void TestThreadCpuTime2()
365 for (TInt retry = 0 ; !pass && retry < 5 ; ++retry)
369 test.Printf(_L("Test failed, retrying...\n"));
372 pass = DoTestThreadCpuTime2();
376 test(DoTestThreadCpuTime2());
380 TInt ThreadFunction2(TAny* aParam)
382 TTimeIntervalMicroSeconds& time = *(TTimeIntervalMicroSeconds*)aParam;
384 return thread.GetCpuTime(time);
389 void DoTestThreadCpuTime3(TAny* aParam, TExitType aExpectedExitType, TInt aExpectedExitReason)
392 FailIfError(thread.Create(_L("TestThread"), ThreadFunction2, 1024, NULL, aParam));
394 TRequestStatus status;
395 thread.Logon(status);
396 User::WaitForRequest(status);
398 TExitCategoryName exitCat = thread.ExitCategory();
399 test.Printf(_L("Thread exit with type == %d, reason == %d, cat == %S\n"),
400 thread.ExitType(), thread.ExitReason(), &exitCat);
402 test(thread.ExitType() == aExpectedExitType);
403 test(thread.ExitReason() == aExpectedExitReason);
404 CLOSE_AND_WAIT(thread);
407 void TestThreadCpuTime3()
409 // Test kernel writes the return value back to user-space with the correct permissions
410 TTimeIntervalMicroSeconds time;
411 DoTestThreadCpuTime3(&time, EExitKill, 0); // ok
412 DoTestThreadCpuTime3((TAny*)0, EExitPanic, 3); // null pointer
413 DoTestThreadCpuTime3((TAny*)0x64000000, EExitPanic, 3); // start of kernel data on moving memory model
414 DoTestThreadCpuTime3((TAny*)0xc8000000, EExitPanic, 3); // start of kernel data on moving multiple model
419 GLDEF_C TInt E32Main()
422 test.Start(_L("T_CPUTIME"));
425 FailIfError(SetCpuAffinity(0));
428 if (GetCpuTimeIsSupported())
432 TestThreadCpuTime2();
434 TestThreadCpuTime3();