|
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 // e32test\pccd\t_pccdbm.cpp |
|
15 // |
|
16 // |
|
17 #include "../mmu/d_sharedchunk.h" |
|
18 #include <hal.h> |
|
19 #include <e32test.h> |
|
20 #include <e32svr.h> |
|
21 #include <e32hal.h> |
|
22 #include <e32uid.h> |
|
23 |
|
24 const TInt K1K = 1024; |
|
25 const TInt K4K = 4096; |
|
26 const TInt K1MB = K1K*K1K; |
|
27 const TInt KMaxTestSize = K1MB; // Redefine to increase test length |
|
28 const TInt KVeryLongRdWrBufLen=((KMaxTestSize*2)+K4K); // Double Max Test size + 4K |
|
29 |
|
30 LOCAL_D TPtr8 DataBuf(NULL, KVeryLongRdWrBufLen,KVeryLongRdWrBufLen); |
|
31 LOCAL_D HBufC8* wrBufH = NULL; |
|
32 |
|
33 LOCAL_D TInt DriveNumber; |
|
34 LOCAL_D TBusLocalDrive TheDrive; |
|
35 LOCAL_D TBool IsReadOnly; |
|
36 |
|
37 LOCAL_D RSharedChunkLdd Ldd; |
|
38 LOCAL_D RChunk TheChunk; |
|
39 const TUint ChunkSize = KVeryLongRdWrBufLen; |
|
40 |
|
41 const TTimeIntervalMicroSeconds32 KFloatingPointTestTime = 10000000; // 10 seconds |
|
42 LOCAL_D TInt gFastCounterFreq; |
|
43 LOCAL_D TBool ChangeFlag; |
|
44 |
|
45 RTest test(_L("Local Drive BenchMark Test")); |
|
46 |
|
47 ///// Buffer Allocation |
|
48 void AllocateBuffers() |
|
49 { |
|
50 test.Next(_L("Allocate Buffers")); |
|
51 |
|
52 wrBufH = HBufC8::New(KVeryLongRdWrBufLen); |
|
53 test(wrBufH != NULL); |
|
54 } |
|
55 |
|
56 void AllocateSharedBuffers(TBool Fragmented, TBool Caching) |
|
57 { |
|
58 // Setup SharedMemory Buffers |
|
59 test.Next(_L("Allocate Shared Memory\n")); |
|
60 |
|
61 RLoader l; |
|
62 test(l.Connect()==KErrNone); |
|
63 test(l.CancelLazyDllUnload()==KErrNone); |
|
64 l.Close(); |
|
65 |
|
66 test.Printf(_L("Initialise\n")); |
|
67 TInt PageSize = 0; |
|
68 TInt r = UserHal::PageSizeInBytes(PageSize); |
|
69 test(r==KErrNone); |
|
70 |
|
71 test.Printf(_L("Loading test driver\n")); |
|
72 r = User::LoadLogicalDevice(KSharedChunkLddName); |
|
73 test(r==KErrNone || r==KErrAlreadyExists); |
|
74 |
|
75 test.Printf(_L("Opening channel\n")); |
|
76 r = Ldd.Open(); |
|
77 test(r==KErrNone); |
|
78 |
|
79 test.Printf(_L("Create chunk\n")); |
|
80 |
|
81 TUint aCreateFlags = EMultiple|EOwnsMemory; |
|
82 |
|
83 if (Caching) |
|
84 { |
|
85 test.Printf(_L("Chunk Type:Caching\n")); |
|
86 aCreateFlags |= ECached; |
|
87 } |
|
88 else |
|
89 test.Printf(_L("Chunk Type:Fully Blocking\n")); |
|
90 |
|
91 TCommitType aCommitType = EContiguous; |
|
92 |
|
93 TUint TotalChunkSize = ChunkSize; // rounded to nearest Page Size |
|
94 |
|
95 TUint ChunkAttribs = TotalChunkSize|aCreateFlags; |
|
96 r = Ldd.CreateChunk(ChunkAttribs); |
|
97 test(r==KErrNone); |
|
98 |
|
99 if(Fragmented) |
|
100 { |
|
101 test.Printf(_L("Commit Fragmented Memory\n")); |
|
102 |
|
103 // Allocate Pages in reverse order to maximise memory fragmentation |
|
104 TUint i = ChunkSize; |
|
105 do |
|
106 { |
|
107 i-=PageSize; |
|
108 test.Printf(_L("Commit %d\n"), i); |
|
109 r = Ldd.CommitMemory(aCommitType|i,PageSize); |
|
110 test(r==KErrNone); |
|
111 }while (i>0); |
|
112 } |
|
113 else |
|
114 { |
|
115 test.Printf(_L("Commit Contigouos Memory\n")); |
|
116 r = Ldd.CommitMemory(aCommitType,TotalChunkSize); |
|
117 test(r==KErrNone); |
|
118 } |
|
119 |
|
120 test.Printf(_L("Open user handle\n")); |
|
121 r = Ldd.GetChunkHandle(TheChunk); |
|
122 test(r==KErrNone); |
|
123 |
|
124 } |
|
125 |
|
126 void DeAllocateBuffers() |
|
127 { |
|
128 delete wrBufH; |
|
129 } |
|
130 |
|
131 void DeAllocareSharedMemory() |
|
132 { |
|
133 // destory chunk |
|
134 test.Printf(_L("Shared Memory\n")); |
|
135 test.Printf(_L("Close user chunk handle\n")); |
|
136 TheChunk.Close(); |
|
137 |
|
138 test.Printf(_L("Close kernel chunk handle\n")); |
|
139 TInt r = Ldd.CloseChunk(); // 1==DObject::EObjectDeleted |
|
140 test(r==1); |
|
141 |
|
142 test.Printf(_L("Check chunk is destroyed\n")); |
|
143 r = Ldd.IsDestroyed(); |
|
144 test(r==1); |
|
145 |
|
146 test.Printf(_L("Close test driver\n")); |
|
147 Ldd.Close(); |
|
148 } |
|
149 |
|
150 // end Buffer allocation |
|
151 |
|
152 |
|
153 LOCAL_C void FillRegion(TInt aBlockSize) |
|
154 /** |
|
155 * Fill media starting at pos 0, |
|
156 * with a pattern of 2*aBlockSize in length |
|
157 */ |
|
158 { |
|
159 test.Printf(_L("Fill Region with Data!\n")); |
|
160 DataBuf.SetLength(aBlockSize); |
|
161 |
|
162 //fill up buffer |
|
163 for (TInt i=0;i<(aBlockSize);i++) |
|
164 { |
|
165 DataBuf[i]=(TUint8)(0xFF-i); |
|
166 } |
|
167 |
|
168 TInt r = TheDrive.Write(0, DataBuf); |
|
169 test (r == KErrNone); |
|
170 } |
|
171 |
|
172 LOCAL_C void DoTestRead(TInt aBlockSize) |
|
173 // |
|
174 // Multiple Read operations of aBlockSize are performed for 10 seconds. |
|
175 // Average is then displayed. |
|
176 // |
|
177 { |
|
178 DataBuf.SetLength(aBlockSize); |
|
179 |
|
180 TUint functionCalls = 0; |
|
181 TUint initTicks = 0; |
|
182 TUint finalTicks = 0; |
|
183 |
|
184 RTimer timer; |
|
185 timer.CreateLocal(); |
|
186 TRequestStatus reqStat; |
|
187 |
|
188 TInt pos = 0; |
|
189 |
|
190 timer.After(reqStat, KFloatingPointTestTime); |
|
191 initTicks = User::FastCounter(); |
|
192 |
|
193 for (TInt i = 0; reqStat==KRequestPending; i++) |
|
194 { |
|
195 TInt r = TheDrive.Read(pos, aBlockSize, DataBuf); |
|
196 |
|
197 test (r == KErrNone); |
|
198 |
|
199 pos += aBlockSize; |
|
200 if (pos > KVeryLongRdWrBufLen-aBlockSize) |
|
201 pos = 0; |
|
202 |
|
203 functionCalls++; |
|
204 } |
|
205 |
|
206 finalTicks = User::FastCounter(); |
|
207 timer.Close(); |
|
208 |
|
209 TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ; |
|
210 |
|
211 TInt dataTransferred = functionCalls * aBlockSize; |
|
212 TReal transferRate = TReal32(dataTransferred) / |
|
213 TReal(duration.Int64()) * TReal(1000000) / TReal(K1K); // KB/s |
|
214 |
|
215 test.Printf(_L("Read %7d bytes in %7d byte blocks:\t%11.3f KBytes/s\n"), |
|
216 dataTransferred, aBlockSize, transferRate); |
|
217 |
|
218 return; |
|
219 } |
|
220 |
|
221 |
|
222 LOCAL_C void TestRead() |
|
223 /** |
|
224 * Repeat read test for values between 1Byte and KMaxTestSize, in steps of power of 2 |
|
225 */ |
|
226 { |
|
227 FillRegion(KVeryLongRdWrBufLen); |
|
228 |
|
229 for (TInt i = 1; i<=KMaxTestSize; i*=2) |
|
230 { |
|
231 DoTestRead(i); |
|
232 } |
|
233 } |
|
234 |
|
235 LOCAL_C void DoTestWrite(TInt aBlockSize) |
|
236 // |
|
237 // Multiple Write operations of aBlockSize are performed for 10 seconds. |
|
238 // Average is then displayed. |
|
239 // |
|
240 { |
|
241 DataBuf.SetLength(aBlockSize); |
|
242 |
|
243 //fill up buffer |
|
244 for (TInt i=0;i<aBlockSize;i++) |
|
245 { |
|
246 DataBuf[i]=(TUint8)(0xFF-i); |
|
247 } |
|
248 |
|
249 TUint functionCalls = 0; |
|
250 TUint initTicks = 0; |
|
251 TUint finalTicks = 0; |
|
252 |
|
253 RTimer timer; |
|
254 timer.CreateLocal(); |
|
255 TRequestStatus reqStat; |
|
256 |
|
257 TInt pos = 0; |
|
258 |
|
259 timer.After(reqStat, KFloatingPointTestTime); |
|
260 initTicks = User::FastCounter(); |
|
261 |
|
262 for (TInt j = 0; reqStat==KRequestPending; j++) |
|
263 { |
|
264 TInt r = TheDrive.Write(pos, DataBuf); |
|
265 |
|
266 test (r == KErrNone); |
|
267 |
|
268 pos += aBlockSize; |
|
269 if (pos > KVeryLongRdWrBufLen-aBlockSize) |
|
270 pos = 0; |
|
271 |
|
272 functionCalls++; |
|
273 } |
|
274 |
|
275 finalTicks = User::FastCounter(); |
|
276 timer.Close(); |
|
277 |
|
278 TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ; |
|
279 |
|
280 TInt dataTransferred = functionCalls * aBlockSize; |
|
281 TReal transferRate = TReal32(dataTransferred) / |
|
282 TReal(duration.Int64()) * TReal(1000000) / TReal(K1K); // KB/s |
|
283 |
|
284 test.Printf(_L("Write %7d bytes in %7d byte blocks:\t%11.3f KBytes/s\n"), |
|
285 dataTransferred, aBlockSize, transferRate); |
|
286 |
|
287 return; |
|
288 } |
|
289 |
|
290 LOCAL_C void TestWrite() |
|
291 /** |
|
292 * Repeat write test for values between 1Byte and KMaxTestSize, in steps of power of 2 |
|
293 */ |
|
294 { |
|
295 for (TInt i = 1; i<=KMaxTestSize; i*=2) |
|
296 { |
|
297 DoTestWrite(i); |
|
298 } |
|
299 } |
|
300 |
|
301 TBool TestDriveInfo() |
|
302 { |
|
303 test.Next( _L("Test drive info") ); |
|
304 |
|
305 TLocalDriveCapsV6Buf DriveCaps; |
|
306 TheDrive.Caps( DriveCaps ); |
|
307 |
|
308 test.Printf( _L("Caps V1:\n\tiSize=0x%lx\n\tiType=%d\n\tiBattery=%d\n\tiDriveAtt=0x%x\n\tiMediaAtt=0x%x\n\tiBaseAddress=0x%x\n\tiFileSystemId=0x%x\n\tiPartitionType=0x%x\n"), |
|
309 DriveCaps().iSize, |
|
310 DriveCaps().iType, |
|
311 DriveCaps().iBattery, |
|
312 DriveCaps().iDriveAtt, |
|
313 DriveCaps().iMediaAtt, |
|
314 DriveCaps().iBaseAddress, |
|
315 DriveCaps().iFileSystemId, |
|
316 DriveCaps().iPartitionType ); |
|
317 |
|
318 test.Printf( _L("Caps V2:\n\tiHiddenSectors=0x%x\n\tiEraseBlockSize=0x%x\nCaps V3:\n\tiExtraInfo=%x\n\tiMaxBytesPerFormat=0x%x\n"), |
|
319 DriveCaps().iHiddenSectors, |
|
320 DriveCaps().iEraseBlockSize, |
|
321 DriveCaps().iExtraInfo, |
|
322 DriveCaps().iMaxBytesPerFormat ); |
|
323 |
|
324 test.Printf( _L("Format info:\n\tiCapacity=0x%lx\n\tiSectorsPerCluster=0x%x\n\tiSectorsPerTrack=0x%x\n\tiNumberOfSides=0x%x\n\tiFatBits=%d\n"), |
|
325 DriveCaps().iFormatInfo.iCapacity, |
|
326 DriveCaps().iFormatInfo.iSectorsPerCluster, |
|
327 DriveCaps().iFormatInfo.iSectorsPerTrack, |
|
328 DriveCaps().iFormatInfo.iNumberOfSides, |
|
329 DriveCaps().iFormatInfo.iFATBits ); |
|
330 |
|
331 test.Printf( _L("Caps V4:\n")); |
|
332 test.Printf(_L("\tiNumberOfSectors: %d\r\n"),DriveCaps().iNumberOfSectors); |
|
333 test.Printf(_L("\tiNumPagesPerBlock: %d\r\n"),DriveCaps().iNumPagesPerBlock); |
|
334 test.Printf(_L("\tiSectorSizeInBytes: %d\r\n"),DriveCaps().iSectorSizeInBytes); |
|
335 test.Printf(_L("\tiNumBytesSpare: %d\r\n"),DriveCaps().iNumBytesSpare); |
|
336 test.Printf(_L("\tiEffectiveBlks: %d\r\n"),DriveCaps().iEffectiveBlks); |
|
337 test.Printf(_L("\tiStartPage: %d\r\n"),DriveCaps().iStartPage); |
|
338 test.Printf(_L("\tMediaSizeInBytes: %ld\r\n"),DriveCaps().MediaSizeInBytes()); |
|
339 |
|
340 test.Printf( _L("Caps V5:\n")); |
|
341 if(DriveCaps().iSerialNumLength > 0) |
|
342 { |
|
343 test.Printf( _L("\tiSerialNum : ") ); |
|
344 TBuf8<2*KMaxSerialNumLength> snBuf; |
|
345 TUint i; |
|
346 for (i=0; i<DriveCaps().iSerialNumLength; i++) |
|
347 { |
|
348 snBuf.AppendNumFixedWidth( DriveCaps().iSerialNum[i], EHex, 2 ); |
|
349 test.Printf( _L("%02x"), DriveCaps().iSerialNum[i]); |
|
350 } |
|
351 test.Printf( _L("\n") ); |
|
352 } |
|
353 else |
|
354 { |
|
355 test.Printf( _L("\tiSerialNum : Not Supported") ); |
|
356 } |
|
357 |
|
358 test.Printf(_L("Caps V6:\n")); |
|
359 test.Printf(_L("\tiBlockSize: %d\r\n"),DriveCaps().iBlockSize); |
|
360 |
|
361 TBool isReadOnly = DriveCaps().iMediaAtt & KMediaAttWriteProtected; |
|
362 return(isReadOnly); |
|
363 } |
|
364 |
|
365 |
|
366 |
|
367 void ParseCommandLineArgs() |
|
368 { |
|
369 TBuf<0x100> buf; |
|
370 |
|
371 TChar driveToTest; |
|
372 |
|
373 // Get the list of drives |
|
374 TDriveInfoV1Buf diBuf; |
|
375 UserHal::DriveInfo(diBuf); |
|
376 TDriveInfoV1 &di=diBuf(); |
|
377 TInt driveCount = di.iTotalSupportedDrives; |
|
378 |
|
379 // Parse command line arguments for the drive to test |
|
380 User::CommandLine(buf); |
|
381 TLex lex(buf); |
|
382 TPtrC token=lex.NextToken(); |
|
383 TFileName thisfile=RProcess().FileName(); |
|
384 if (token.MatchF(thisfile)==0) |
|
385 { |
|
386 token.Set(lex.NextToken()); |
|
387 } |
|
388 |
|
389 if(token.Length()!=0) |
|
390 { |
|
391 driveToTest=token[0]; |
|
392 } |
|
393 else |
|
394 { |
|
395 //Print the list of usable drives |
|
396 test.Printf(_L("\nDRIVES USED AT PRESENT :\r\n")); |
|
397 |
|
398 for (TInt i=0; i < driveCount; i++) |
|
399 { |
|
400 TBool flag=EFalse; |
|
401 RLocalDrive d; |
|
402 TInt r=d.Connect(i,flag); |
|
403 //Not all the drives are used at present |
|
404 if (r == KErrNotSupported) |
|
405 continue; |
|
406 |
|
407 test.Printf(_L("%d : DRIVE NAME :%- 16S\r\n"), i, &di.iDriveName[i]); |
|
408 } |
|
409 |
|
410 test.Printf(_L("\r\nWarning - all data on drive will be lost.\r\n")); |
|
411 test.Printf(_L("<<<Hit drive number to continue>>>\r\n")); |
|
412 |
|
413 driveToTest=(TUint)test.Getch(); |
|
414 } |
|
415 |
|
416 DriveNumber=((TUint)driveToTest) - '0'; |
|
417 test(DriveNumber >= 1 && DriveNumber < di.iTotalSupportedDrives); |
|
418 } |
|
419 |
|
420 GLDEF_C TInt E32Main() |
|
421 { |
|
422 test.Title(); |
|
423 test.Start(_L("Benchmark Testing for Local Media Drivers")); |
|
424 |
|
425 ParseCommandLineArgs(); |
|
426 |
|
427 AllocateBuffers(); |
|
428 |
|
429 test.Printf(_L("Connect to local drive (%d)\n"),DriveNumber); |
|
430 |
|
431 ChangeFlag=EFalse; |
|
432 test(TheDrive.Connect(DriveNumber,ChangeFlag)==KErrNone); |
|
433 |
|
434 TInt r = HAL::Get(HAL::EFastCounterFrequency, gFastCounterFreq); |
|
435 test(r == KErrNone); |
|
436 |
|
437 IsReadOnly = TestDriveInfo(); |
|
438 |
|
439 if (IsReadOnly) |
|
440 { |
|
441 test.Printf(_L("Drive is read only - can't run test!!\n")); |
|
442 DeAllocateBuffers(); |
|
443 test.End(); |
|
444 return(0); |
|
445 } |
|
446 |
|
447 // Heap Memory |
|
448 DataBuf.Set(wrBufH->Des()); |
|
449 test.Next(_L("Read Benchmark - Heap Memory")); |
|
450 TestRead(); |
|
451 test.Next(_L("Write Benchmark - Heap Memory")); |
|
452 TestWrite(); |
|
453 DeAllocateBuffers(); |
|
454 |
|
455 // Contiguous Shared Chunk |
|
456 AllocateSharedBuffers(EFalse, EFalse); |
|
457 DataBuf.Set(TheChunk.Base(),KVeryLongRdWrBufLen, KVeryLongRdWrBufLen); |
|
458 test.Next(_L("Read Benchmark - Shared Contiguous Memory")); |
|
459 TestRead(); |
|
460 test.Next(_L("Write Benchmark - Shared Contiguous Memory")); |
|
461 TestWrite(); |
|
462 DeAllocareSharedMemory(); |
|
463 |
|
464 // Fragmented Shared Chunk |
|
465 AllocateSharedBuffers(ETrue, EFalse); |
|
466 DataBuf.Set(TheChunk.Base(),KVeryLongRdWrBufLen, KVeryLongRdWrBufLen); |
|
467 test.Next(_L("Read Benchmark - Shared Fragmented Memory")); |
|
468 TestRead(); |
|
469 test.Next(_L("Write Benchmark - Shared Fragmented Memory")); |
|
470 TestWrite(); |
|
471 DeAllocareSharedMemory(); |
|
472 |
|
473 test.End(); |
|
474 |
|
475 return(0); |
|
476 } |
|
477 |