|
1 // Copyright (c) 2009-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\misc\ccthrash.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #define __E32TEST_EXTENSION__ |
|
19 |
|
20 #include <e32test.h> |
|
21 #include <e32hal.h> |
|
22 #include <e32svr.h> |
|
23 #include <e32atomics.h> |
|
24 #include "u32std.h" |
|
25 #include "prbs.h" |
|
26 |
|
27 RTest test(_L("Core Control Thrasher")); |
|
28 |
|
29 TInt NumberOfCpus() |
|
30 { |
|
31 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0); |
|
32 test(r>0); |
|
33 return r; |
|
34 } |
|
35 |
|
36 const TInt NCPU = NumberOfCpus(); |
|
37 volatile TInt STFU = 1; |
|
38 |
|
39 TInt NumberOfActiveCpus(TInt* a) |
|
40 { |
|
41 SCpuStates s; |
|
42 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalCpuStates, &s, 0); |
|
43 test_KErrNone(r); |
|
44 TUint32 ta = s.iTA; |
|
45 TUint32 ia = s.iIA; |
|
46 if (a) |
|
47 *a = __e32_bit_count_32(ta); |
|
48 return __e32_bit_count_32(ia); |
|
49 } |
|
50 |
|
51 TInt StableState() |
|
52 { |
|
53 SCpuStates s; |
|
54 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalCpuStates, &s, 0); |
|
55 test_KErrNone(r); |
|
56 if (s.iCU || s.iDC) |
|
57 return KErrNotReady; |
|
58 if (s.iTA != s.iIA) |
|
59 return KErrNotReady; |
|
60 if (s.iGD & s.iIA) |
|
61 return KErrNotReady; |
|
62 TInt i; |
|
63 for (i=0; i<NCPU; ++i) |
|
64 { |
|
65 TBool attached = (s.iUDC[i] == s.iUAC[i]); |
|
66 TBool on = s.iIA & (1u<<i); |
|
67 if ((on && !attached) || (!on && attached)) |
|
68 return KErrNotReady; |
|
69 } |
|
70 return __e32_bit_count_32(s.iTA); |
|
71 } |
|
72 |
|
73 class CThrasher : public CBase |
|
74 { |
|
75 public: |
|
76 CThrasher(); |
|
77 ~CThrasher(); |
|
78 static CThrasher* New(); |
|
79 TInt Construct(); |
|
80 void Run(); |
|
81 void Display(); |
|
82 TInt ChangeNumberOfCores(TInt aNum, TInt* aCores); |
|
83 public: |
|
84 TUint64 iRunCount; |
|
85 TUint64 iTotalTime; |
|
86 TUint32 iTimeouts; |
|
87 TUint32 iDiff; |
|
88 TUint32 iPeriod; |
|
89 TUint iSeed[2]; |
|
90 TUint32 iLastDisplay; |
|
91 TUint32 iDisplayPeriod; |
|
92 TUint32 iTimeoutPeriod; |
|
93 }; |
|
94 |
|
95 CThrasher::CThrasher() |
|
96 { |
|
97 iSeed[0] = 0xb504f334u; |
|
98 iPeriod = 19; |
|
99 iLastDisplay = User::NTickCount(); |
|
100 iDisplayPeriod = 2000; |
|
101 iTimeoutPeriod = 200; |
|
102 } |
|
103 |
|
104 CThrasher::~CThrasher() |
|
105 { |
|
106 } |
|
107 |
|
108 TInt CThrasher::Construct() |
|
109 { |
|
110 return KErrNone; |
|
111 } |
|
112 |
|
113 CThrasher* CThrasher::New() |
|
114 { |
|
115 CThrasher* p = new CThrasher; |
|
116 if (!p) |
|
117 return 0; |
|
118 TInt r = p->Construct(); |
|
119 if (r!=KErrNone) |
|
120 { |
|
121 delete p; |
|
122 return 0; |
|
123 } |
|
124 return p; |
|
125 } |
|
126 |
|
127 TInt CThrasher::ChangeNumberOfCores(TInt aNum, TInt* aCores) |
|
128 { |
|
129 TUint32 initial = User::NTickCount(); |
|
130 TUint32 final = initial; |
|
131 TUint32 elapsed = 0; |
|
132 TInt n = -1; |
|
133 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalSetNumberOfCpus, (TAny*)aNum, 0); |
|
134 test_KErrNone(r); |
|
135 FOREVER |
|
136 { |
|
137 n = StableState(); |
|
138 final = User::NTickCount(); |
|
139 elapsed = final - initial; |
|
140 if (n<0 || elapsed<iTimeoutPeriod) |
|
141 break; |
|
142 User::AfterHighRes(1000); |
|
143 } |
|
144 if (aCores) |
|
145 *aCores = n; |
|
146 if (n>=0) |
|
147 return elapsed; |
|
148 return KErrTimedOut; |
|
149 } |
|
150 |
|
151 void CThrasher::Run() |
|
152 { |
|
153 TUint x = Random(iSeed); |
|
154 x %= iPeriod; |
|
155 x += 1; |
|
156 x *= 1000; |
|
157 User::AfterHighRes(x); |
|
158 TUint y = Random(iSeed); |
|
159 y %= TUint(NCPU); |
|
160 y += 1; |
|
161 TInt n = 0; |
|
162 TInt t = ChangeNumberOfCores(y, &n); |
|
163 if (t < 0) |
|
164 { |
|
165 ++iTimeouts; |
|
166 iTotalTime += TUint64(iTimeoutPeriod); |
|
167 } |
|
168 else |
|
169 { |
|
170 iTotalTime += TUint64(t); |
|
171 if (TUint(n) != y) |
|
172 ++iDiff; |
|
173 } |
|
174 ++iRunCount; |
|
175 TUint32 now = User::NTickCount(); |
|
176 TUint32 elapsed = now - iLastDisplay; |
|
177 if (elapsed >= iDisplayPeriod) |
|
178 { |
|
179 iLastDisplay = now; |
|
180 Display(); |
|
181 } |
|
182 } |
|
183 |
|
184 void CThrasher::Display() |
|
185 { |
|
186 TUint64 avg = iTotalTime; |
|
187 avg *= TUint64(100); |
|
188 avg += TUint64(50); |
|
189 avg /= iRunCount; |
|
190 TUint32 frac = TUint32(avg % TUint64(100)); |
|
191 TUint32 integer = TUint32(avg / TUint64(100)); |
|
192 TUint32 rc32 = (TUint32)iRunCount; |
|
193 test.Printf(_L("RC:%10u AVG:%10u.%02u TO:%10u D:%10u\n"), rc32, integer, frac, iTimeouts, iDiff); |
|
194 } |
|
195 |
|
196 GLDEF_C TInt E32Main() |
|
197 { |
|
198 test.Title(); |
|
199 RThread().SetPriority(EPriorityAbsoluteHigh); |
|
200 |
|
201 if (NCPU==1) |
|
202 { |
|
203 test.Printf(_L("Only works on SMP systems\n")); |
|
204 return 0; |
|
205 } |
|
206 |
|
207 CThrasher* p = CThrasher::New(); |
|
208 test_NotNull(p); |
|
209 while(STFU) |
|
210 { |
|
211 p->Run(); |
|
212 } |
|
213 |
|
214 |
|
215 return 0; |
|
216 } |
|
217 |