|
1 // Copyright (c) 1996-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 // Very simple test of CPU overhead |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file bf_cpu.cpp |
|
20 */ |
|
21 |
|
22 #include <e32std.h> |
|
23 #include <e32std_private.h> |
|
24 #include <e32base.h> |
|
25 #include <e32base_private.h> |
|
26 #include <e32test.h> |
|
27 #include <e32svr.h> |
|
28 #include "user_config.h" |
|
29 |
|
30 |
|
31 #define TEST_WRITE_OVERHEAD |
|
32 #define NON_WRITING_LOOPS |
|
33 |
|
34 const TInt KAverageOverInSeconds=10; ///< Number of seconds to run tests for |
|
35 |
|
36 TInt64 Count; ///< Global variable used to count number of operations completed |
|
37 RSemaphore CountSem; ///< control access to Count; |
|
38 |
|
39 |
|
40 RTest test(_L("BF_CPU")); |
|
41 |
|
42 |
|
43 |
|
44 TBusLocalDrive drive; |
|
45 TLocalDriveCapsV2Buf driveInfo; |
|
46 |
|
47 LOCAL_D TBool StopTest; ///< set to ETrue to stop the test |
|
48 |
|
49 |
|
50 #ifdef TEST_WRITE_OVERHEAD |
|
51 LOCAL_D TBool StopZeroTest; |
|
52 |
|
53 LOCAL_C TInt WriteZeroThread(TAny*) |
|
54 /** |
|
55 * Performs writes of zero length continuously |
|
56 */ |
|
57 { |
|
58 #if 0 |
|
59 _LIT( KPanicCat, "ZERWRTH" ); |
|
60 #endif |
|
61 |
|
62 TBuf8<513> buf; |
|
63 buf.SetLength(513); |
|
64 |
|
65 while( !StopZeroTest ) |
|
66 { |
|
67 // Return values are bogus when doing overhead testing |
|
68 drive.Write( 513, buf ); |
|
69 } |
|
70 return KErrNone; |
|
71 } |
|
72 #endif |
|
73 |
|
74 |
|
75 LOCAL_C TInt WriteThread(TAny*) |
|
76 /** |
|
77 * Performs writes continuously |
|
78 */ |
|
79 { |
|
80 _LIT( KPanicCat, "WRTHRD" ); |
|
81 |
|
82 TBuf8<512> buf; |
|
83 buf.SetLength(512); |
|
84 buf.Fill(0xFF); // all 0xFF so we can repeatedly overwrite |
|
85 |
|
86 while( !StopTest ) |
|
87 { |
|
88 TInt r = drive.Write( 0, buf ); |
|
89 if( KErrNone != r ) |
|
90 { |
|
91 User::Panic( KPanicCat, r ); |
|
92 } |
|
93 } |
|
94 return KErrNone; |
|
95 } |
|
96 |
|
97 |
|
98 |
|
99 LOCAL_C TInt CpuThread(TAny*) |
|
100 /** |
|
101 * Just increments the counter |
|
102 */ |
|
103 { |
|
104 while( !StopTest ) |
|
105 { |
|
106 CountSem.Wait(); |
|
107 #ifdef NON_WRITING_LOOPS |
|
108 for( volatile TInt i = 5000; i > 0; i-- ); |
|
109 #endif |
|
110 ++Count; |
|
111 CountSem.Signal(); |
|
112 } |
|
113 return KErrNone; |
|
114 } |
|
115 |
|
116 |
|
117 void runTest() |
|
118 { |
|
119 RThread writeThread; |
|
120 TInt r=writeThread.Create(_L("WRITER"),WriteThread,KDefaultStackSize,&User::Heap(),NULL); |
|
121 test(r==KErrNone); |
|
122 |
|
123 RThread cpuThread; |
|
124 r=cpuThread.Create(_L("CPU-ER"),CpuThread,KDefaultStackSize,&User::Heap(),NULL); |
|
125 test(r==KErrNone); |
|
126 |
|
127 #ifdef TEST_WRITE_OVERHEAD |
|
128 RThread writeZeroThread; |
|
129 r=writeZeroThread.Create(_L("WRITERZERO"),WriteZeroThread,KDefaultStackSize,&User::Heap(),NULL); |
|
130 test(r==KErrNone); |
|
131 #endif |
|
132 |
|
133 r = CountSem.CreateLocal(1); |
|
134 test(r==KErrNone); |
|
135 |
|
136 |
|
137 StopTest = EFalse; // allow the test to run |
|
138 |
|
139 TRequestStatus deadStatWrite; |
|
140 TRequestStatus deadStatCpu; |
|
141 writeThread.Logon( deadStatWrite ); |
|
142 cpuThread.Logon( deadStatCpu ); |
|
143 |
|
144 // make writer thread have priority over CPU usage thread |
|
145 writeThread.SetPriority( EPriorityMore ); |
|
146 |
|
147 // make this thread highest priority |
|
148 RThread().SetPriority( EPriorityMuchMore ); |
|
149 |
|
150 |
|
151 cpuThread.Resume(); |
|
152 |
|
153 #ifdef TEST_WRITE_OVERHEAD |
|
154 TRequestStatus deadStatWriteZero; |
|
155 writeZeroThread.Logon( deadStatWriteZero ); |
|
156 // make writer thread have priority over CPU usage thread |
|
157 writeZeroThread.SetPriority( EPriorityMore ); |
|
158 StopZeroTest = EFalse; |
|
159 writeZeroThread.Resume(); |
|
160 #endif |
|
161 |
|
162 // wait for thread to initialise |
|
163 User::After(1000000); |
|
164 |
|
165 CountSem.Wait(); |
|
166 Count=0; |
|
167 CountSem.Signal(); |
|
168 |
|
169 User::After(KAverageOverInSeconds*1000000); |
|
170 |
|
171 CountSem.Wait(); |
|
172 TInt64 noWriteCount( Count ); // number of counts when not writing |
|
173 CountSem.Signal(); |
|
174 |
|
175 |
|
176 #ifdef TEST_WRITE_OVERHEAD |
|
177 // kill the zero writer |
|
178 StopZeroTest = ETrue; |
|
179 User::WaitForRequest( deadStatWriteZero ); |
|
180 CLOSE_AND_WAIT(writeZeroThread); |
|
181 #endif |
|
182 |
|
183 test.Printf( _L("Loops without writing = %ld"), noWriteCount ); |
|
184 |
|
185 // start write thread |
|
186 writeThread.Resume(); |
|
187 User::After(1000000); |
|
188 |
|
189 CountSem.Wait(); |
|
190 Count=0; |
|
191 CountSem.Signal(); |
|
192 |
|
193 User::After(KAverageOverInSeconds*1000000); |
|
194 |
|
195 CountSem.Wait(); |
|
196 TInt64 withWriteCount( Count ); // number of counts when writing |
|
197 CountSem.Signal(); |
|
198 |
|
199 test.Printf( _L("Loops while writing = %ld"), withWriteCount ); |
|
200 |
|
201 // tell test to stop and wait for thread to exit. |
|
202 cpuThread.Kill(KErrNone); |
|
203 StopTest = ETrue; |
|
204 User::WaitForRequest( deadStatWrite ); |
|
205 |
|
206 CLOSE_AND_WAIT(writeThread); |
|
207 CLOSE_AND_WAIT(cpuThread); |
|
208 |
|
209 |
|
210 |
|
211 TInt64 calc( withWriteCount ); |
|
212 calc = calc * 100; |
|
213 calc = calc / noWriteCount; |
|
214 |
|
215 test.Printf( _L("%% CPU used = %d"), 100 - I64LOW(calc) ); |
|
216 } |
|
217 |
|
218 |
|
219 |
|
220 LOCAL_C TInt EraseSegment( TInt aSegmentNumber ) |
|
221 /** |
|
222 * Erases a segment on Flash |
|
223 * |
|
224 * @param aSegmentNumber index of segment to erase |
|
225 * @return KErrNone or error code |
|
226 */ |
|
227 { |
|
228 TInt offset = aSegmentNumber * driveInfo().iEraseBlockSize; |
|
229 |
|
230 TInt r = drive.Format( offset, driveInfo().iEraseBlockSize ); |
|
231 test.Printf( _L("erase returns %d"), r ); |
|
232 return r; |
|
233 } |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 void Initialize() |
|
239 /** |
|
240 * Open channel to media driver |
|
241 */ |
|
242 { |
|
243 // |
|
244 // Load the media driver |
|
245 // |
|
246 #ifndef SKIP_PDD_LOAD |
|
247 test.Printf( _L("Loading %S\n"), &KLfsDriverName ); |
|
248 TInt r = User::LoadPhysicalDevice( KLfsDriverName ); |
|
249 test( KErrNone == r || KErrAlreadyExists == r ); |
|
250 #endif |
|
251 |
|
252 #ifdef UNMOUNT_DRIVE |
|
253 RFs fs; |
|
254 test( KErrNone == fs.Connect() ); |
|
255 #if 0 |
|
256 // XXX not EKA2 |
|
257 test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) ); |
|
258 #endif |
|
259 TFullName name; |
|
260 fs.FileSystemName( name, KLffsLogicalDriveNumber ); |
|
261 if( name.Length() > 0 ) |
|
262 { |
|
263 test.Printf( _L("Unmounting drive") ); |
|
264 test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) ); |
|
265 User::After( 2000000 ); |
|
266 test.Printf( _L("Drive unmounted") ); |
|
267 } |
|
268 fs.Close(); |
|
269 #endif |
|
270 |
|
271 // |
|
272 // Open a TBusLogicalDevice to it |
|
273 // |
|
274 test.Printf( _L("Opening media channel\n") ); |
|
275 TBool changedFlag = EFalse; |
|
276 test( KErrNone == drive.Connect( KDriveNumber, changedFlag ) ); |
|
277 |
|
278 // |
|
279 // Get size of Flash drive, block size, block count |
|
280 // |
|
281 drive.Caps(driveInfo); |
|
282 } |
|
283 |
|
284 |
|
285 |
|
286 TInt E32Main() |
|
287 { |
|
288 |
|
289 test.Title(); |
|
290 test.Start(_L("Testing CPU overhead")); |
|
291 |
|
292 Initialize(); |
|
293 |
|
294 test.Printf( _L("Erasing first segment") ); |
|
295 TInt r = EraseSegment( 0 ); |
|
296 test( KErrNone == r ); |
|
297 test.Printf( _L("Segment erased") ); |
|
298 |
|
299 runTest(); |
|
300 |
|
301 drive.Disconnect(); |
|
302 test.End(); |
|
303 return(KErrNone); |
|
304 } |
|
305 |