sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Very simple test of CPU overhead sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file bf_cpu.cpp sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "user_config.h" sl@0: sl@0: sl@0: #define TEST_WRITE_OVERHEAD sl@0: #define NON_WRITING_LOOPS sl@0: sl@0: const TInt KAverageOverInSeconds=10; ///< Number of seconds to run tests for sl@0: sl@0: TInt64 Count; ///< Global variable used to count number of operations completed sl@0: RSemaphore CountSem; ///< control access to Count; sl@0: sl@0: sl@0: RTest test(_L("BF_CPU")); sl@0: sl@0: sl@0: sl@0: TBusLocalDrive drive; sl@0: TLocalDriveCapsV2Buf driveInfo; sl@0: sl@0: LOCAL_D TBool StopTest; ///< set to ETrue to stop the test sl@0: sl@0: sl@0: #ifdef TEST_WRITE_OVERHEAD sl@0: LOCAL_D TBool StopZeroTest; sl@0: sl@0: LOCAL_C TInt WriteZeroThread(TAny*) sl@0: /** sl@0: * Performs writes of zero length continuously sl@0: */ sl@0: { sl@0: #if 0 sl@0: _LIT( KPanicCat, "ZERWRTH" ); sl@0: #endif sl@0: sl@0: TBuf8<513> buf; sl@0: buf.SetLength(513); sl@0: sl@0: while( !StopZeroTest ) sl@0: { sl@0: // Return values are bogus when doing overhead testing sl@0: drive.Write( 513, buf ); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: #endif sl@0: sl@0: sl@0: LOCAL_C TInt WriteThread(TAny*) sl@0: /** sl@0: * Performs writes continuously sl@0: */ sl@0: { sl@0: _LIT( KPanicCat, "WRTHRD" ); sl@0: sl@0: TBuf8<512> buf; sl@0: buf.SetLength(512); sl@0: buf.Fill(0xFF); // all 0xFF so we can repeatedly overwrite sl@0: sl@0: while( !StopTest ) sl@0: { sl@0: TInt r = drive.Write( 0, buf ); sl@0: if( KErrNone != r ) sl@0: { sl@0: User::Panic( KPanicCat, r ); sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: LOCAL_C TInt CpuThread(TAny*) sl@0: /** sl@0: * Just increments the counter sl@0: */ sl@0: { sl@0: while( !StopTest ) sl@0: { sl@0: CountSem.Wait(); sl@0: #ifdef NON_WRITING_LOOPS sl@0: for( volatile TInt i = 5000; i > 0; i-- ); sl@0: #endif sl@0: ++Count; sl@0: CountSem.Signal(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void runTest() sl@0: { sl@0: RThread writeThread; sl@0: TInt r=writeThread.Create(_L("WRITER"),WriteThread,KDefaultStackSize,&User::Heap(),NULL); sl@0: test(r==KErrNone); sl@0: sl@0: RThread cpuThread; sl@0: r=cpuThread.Create(_L("CPU-ER"),CpuThread,KDefaultStackSize,&User::Heap(),NULL); sl@0: test(r==KErrNone); sl@0: sl@0: #ifdef TEST_WRITE_OVERHEAD sl@0: RThread writeZeroThread; sl@0: r=writeZeroThread.Create(_L("WRITERZERO"),WriteZeroThread,KDefaultStackSize,&User::Heap(),NULL); sl@0: test(r==KErrNone); sl@0: #endif sl@0: sl@0: r = CountSem.CreateLocal(1); sl@0: test(r==KErrNone); sl@0: sl@0: sl@0: StopTest = EFalse; // allow the test to run sl@0: sl@0: TRequestStatus deadStatWrite; sl@0: TRequestStatus deadStatCpu; sl@0: writeThread.Logon( deadStatWrite ); sl@0: cpuThread.Logon( deadStatCpu ); sl@0: sl@0: // make writer thread have priority over CPU usage thread sl@0: writeThread.SetPriority( EPriorityMore ); sl@0: sl@0: // make this thread highest priority sl@0: RThread().SetPriority( EPriorityMuchMore ); sl@0: sl@0: sl@0: cpuThread.Resume(); sl@0: sl@0: #ifdef TEST_WRITE_OVERHEAD sl@0: TRequestStatus deadStatWriteZero; sl@0: writeZeroThread.Logon( deadStatWriteZero ); sl@0: // make writer thread have priority over CPU usage thread sl@0: writeZeroThread.SetPriority( EPriorityMore ); sl@0: StopZeroTest = EFalse; sl@0: writeZeroThread.Resume(); sl@0: #endif sl@0: sl@0: // wait for thread to initialise sl@0: User::After(1000000); sl@0: sl@0: CountSem.Wait(); sl@0: Count=0; sl@0: CountSem.Signal(); sl@0: sl@0: User::After(KAverageOverInSeconds*1000000); sl@0: sl@0: CountSem.Wait(); sl@0: TInt64 noWriteCount( Count ); // number of counts when not writing sl@0: CountSem.Signal(); sl@0: sl@0: sl@0: #ifdef TEST_WRITE_OVERHEAD sl@0: // kill the zero writer sl@0: StopZeroTest = ETrue; sl@0: User::WaitForRequest( deadStatWriteZero ); sl@0: CLOSE_AND_WAIT(writeZeroThread); sl@0: #endif sl@0: sl@0: test.Printf( _L("Loops without writing = %ld"), noWriteCount ); sl@0: sl@0: // start write thread sl@0: writeThread.Resume(); sl@0: User::After(1000000); sl@0: sl@0: CountSem.Wait(); sl@0: Count=0; sl@0: CountSem.Signal(); sl@0: sl@0: User::After(KAverageOverInSeconds*1000000); sl@0: sl@0: CountSem.Wait(); sl@0: TInt64 withWriteCount( Count ); // number of counts when writing sl@0: CountSem.Signal(); sl@0: sl@0: test.Printf( _L("Loops while writing = %ld"), withWriteCount ); sl@0: sl@0: // tell test to stop and wait for thread to exit. sl@0: cpuThread.Kill(KErrNone); sl@0: StopTest = ETrue; sl@0: User::WaitForRequest( deadStatWrite ); sl@0: sl@0: CLOSE_AND_WAIT(writeThread); sl@0: CLOSE_AND_WAIT(cpuThread); sl@0: sl@0: sl@0: sl@0: TInt64 calc( withWriteCount ); sl@0: calc = calc * 100; sl@0: calc = calc / noWriteCount; sl@0: sl@0: test.Printf( _L("%% CPU used = %d"), 100 - I64LOW(calc) ); sl@0: } sl@0: sl@0: sl@0: sl@0: LOCAL_C TInt EraseSegment( TInt aSegmentNumber ) sl@0: /** sl@0: * Erases a segment on Flash sl@0: * sl@0: * @param aSegmentNumber index of segment to erase sl@0: * @return KErrNone or error code sl@0: */ sl@0: { sl@0: TInt offset = aSegmentNumber * driveInfo().iEraseBlockSize; sl@0: sl@0: TInt r = drive.Format( offset, driveInfo().iEraseBlockSize ); sl@0: test.Printf( _L("erase returns %d"), r ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void Initialize() sl@0: /** sl@0: * Open channel to media driver sl@0: */ sl@0: { sl@0: // sl@0: // Load the media driver sl@0: // sl@0: #ifndef SKIP_PDD_LOAD sl@0: test.Printf( _L("Loading %S\n"), &KLfsDriverName ); sl@0: TInt r = User::LoadPhysicalDevice( KLfsDriverName ); sl@0: test( KErrNone == r || KErrAlreadyExists == r ); sl@0: #endif sl@0: sl@0: #ifdef UNMOUNT_DRIVE sl@0: RFs fs; sl@0: test( KErrNone == fs.Connect() ); sl@0: #if 0 sl@0: // XXX not EKA2 sl@0: test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) ); sl@0: #endif sl@0: TFullName name; sl@0: fs.FileSystemName( name, KLffsLogicalDriveNumber ); sl@0: if( name.Length() > 0 ) sl@0: { sl@0: test.Printf( _L("Unmounting drive") ); sl@0: test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) ); sl@0: User::After( 2000000 ); sl@0: test.Printf( _L("Drive unmounted") ); sl@0: } sl@0: fs.Close(); sl@0: #endif sl@0: sl@0: // sl@0: // Open a TBusLogicalDevice to it sl@0: // sl@0: test.Printf( _L("Opening media channel\n") ); sl@0: TBool changedFlag = EFalse; sl@0: test( KErrNone == drive.Connect( KDriveNumber, changedFlag ) ); sl@0: sl@0: // sl@0: // Get size of Flash drive, block size, block count sl@0: // sl@0: drive.Caps(driveInfo); sl@0: } sl@0: sl@0: sl@0: sl@0: TInt E32Main() sl@0: { sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Testing CPU overhead")); sl@0: sl@0: Initialize(); sl@0: sl@0: test.Printf( _L("Erasing first segment") ); sl@0: TInt r = EraseSegment( 0 ); sl@0: test( KErrNone == r ); sl@0: test.Printf( _L("Segment erased") ); sl@0: sl@0: runTest(); sl@0: sl@0: drive.Disconnect(); sl@0: test.End(); sl@0: return(KErrNone); sl@0: } sl@0: