kerneltest/e32test/lffs/bf_cpu.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// Very simple test of CPU overhead
// 
//

/**
 @file bf_cpu.cpp
*/

#include <e32std.h>
#include <e32std_private.h>
#include <e32base.h>
#include <e32base_private.h>
#include <e32test.h>
#include <e32svr.h>
#include "user_config.h"


#define TEST_WRITE_OVERHEAD
#define NON_WRITING_LOOPS

const TInt KAverageOverInSeconds=10;	///< Number of seconds to run tests for

TInt64 Count;				///< Global variable used to count number of operations completed
RSemaphore CountSem;		///< control access to Count;


RTest test(_L("BF_CPU"));



TBusLocalDrive	drive;
TLocalDriveCapsV2Buf driveInfo;

LOCAL_D TBool StopTest;		///< set to ETrue to stop the test


#ifdef TEST_WRITE_OVERHEAD
LOCAL_D TBool StopZeroTest;

LOCAL_C TInt WriteZeroThread(TAny*)
	/**
	 * Performs writes of zero length continuously
	 */
	{
#if 0
	_LIT( KPanicCat, "ZERWRTH" );
#endif
	
	TBuf8<513> buf;
	buf.SetLength(513);
	
	while( !StopZeroTest )
		{
		// Return values are bogus when doing overhead testing
		drive.Write( 513, buf );
		}
	return KErrNone;
	}
#endif


LOCAL_C TInt WriteThread(TAny*)
	/**
	 * Performs writes continuously
	 */
	{
	_LIT( KPanicCat, "WRTHRD" );
	
	TBuf8<512> buf;
	buf.SetLength(512);
	buf.Fill(0xFF);		// all 0xFF so we can repeatedly overwrite
	
	while( !StopTest )
		{
		TInt r = drive.Write( 0, buf );
		if( KErrNone != r )
			{
			User::Panic( KPanicCat, r );
			}
		}
	return KErrNone;
	}



LOCAL_C TInt CpuThread(TAny*)
	/**
	 * Just increments the counter
	 */
	{
	while( !StopTest )
		{
		CountSem.Wait();
#ifdef NON_WRITING_LOOPS
		for( volatile TInt i = 5000; i > 0; i-- );
#endif
		++Count;
		CountSem.Signal();
		}
	return KErrNone;
	}


void runTest()
	{
    RThread writeThread;
	TInt r=writeThread.Create(_L("WRITER"),WriteThread,KDefaultStackSize,&User::Heap(),NULL);
	test(r==KErrNone);

	RThread cpuThread;
	r=cpuThread.Create(_L("CPU-ER"),CpuThread,KDefaultStackSize,&User::Heap(),NULL);
	test(r==KErrNone);

#ifdef TEST_WRITE_OVERHEAD
    RThread writeZeroThread;
	r=writeZeroThread.Create(_L("WRITERZERO"),WriteZeroThread,KDefaultStackSize,&User::Heap(),NULL);
	test(r==KErrNone);
#endif

	r = CountSem.CreateLocal(1);
	test(r==KErrNone);


	StopTest = EFalse;	// allow the test to run

    TRequestStatus deadStatWrite;
    TRequestStatus deadStatCpu;
	writeThread.Logon( deadStatWrite );
	cpuThread.Logon( deadStatCpu );
	
	// make writer thread have priority over CPU usage thread
	writeThread.SetPriority( EPriorityMore );

	// make this thread highest priority
	RThread().SetPriority( EPriorityMuchMore );
	
	
    cpuThread.Resume();
	
#ifdef TEST_WRITE_OVERHEAD
    TRequestStatus deadStatWriteZero;
	writeZeroThread.Logon( deadStatWriteZero );
	// make writer thread have priority over CPU usage thread
	writeZeroThread.SetPriority( EPriorityMore );
	StopZeroTest = EFalse;
	writeZeroThread.Resume();
#endif
	
	// wait for thread to initialise
	User::After(1000000);

	CountSem.Wait();
	Count=0;
	CountSem.Signal();

    User::After(KAverageOverInSeconds*1000000);
    
	CountSem.Wait();
	TInt64 noWriteCount( Count );	// number of counts when not writing
	CountSem.Signal();

	
#ifdef TEST_WRITE_OVERHEAD
	// kill the zero writer
	StopZeroTest = ETrue;
	User::WaitForRequest( deadStatWriteZero );
	CLOSE_AND_WAIT(writeZeroThread);
#endif
    
	test.Printf( _L("Loops without writing = %ld"), noWriteCount );
	
	// start write thread
	writeThread.Resume();
	User::After(1000000);
    
	CountSem.Wait();
	Count=0;
	CountSem.Signal();

    User::After(KAverageOverInSeconds*1000000);
    
	CountSem.Wait();
	TInt64 withWriteCount( Count );	// number of counts when writing
	CountSem.Signal();

	test.Printf( _L("Loops while writing = %ld"), withWriteCount );
	
	// tell test to stop and wait for thread to exit.
	cpuThread.Kill(KErrNone);
	StopTest = ETrue;
	User::WaitForRequest( deadStatWrite );
	
	CLOSE_AND_WAIT(writeThread);
	CLOSE_AND_WAIT(cpuThread);
    


	TInt64 calc( withWriteCount );
	calc = calc * 100;
	calc = calc / noWriteCount;
		
	test.Printf( _L("%% CPU used = %d"), 100 - I64LOW(calc) );
    }



LOCAL_C TInt EraseSegment( TInt aSegmentNumber )
	/**
	 * Erases a segment on Flash
	 *
	 * @param aSegmentNumber index of segment to erase
	 * @return KErrNone or error code
	 */
	{
	TInt offset = aSegmentNumber * driveInfo().iEraseBlockSize;
	
	TInt r = drive.Format( offset, driveInfo().iEraseBlockSize );
	test.Printf( _L("erase returns %d"), r );
	return  r;
	}




void Initialize()
	/**
	 * Open channel to media driver
	 */
	{
	//
	// Load the media driver
	//
#ifndef SKIP_PDD_LOAD
	test.Printf( _L("Loading %S\n"), &KLfsDriverName );
	TInt r = User::LoadPhysicalDevice( KLfsDriverName );
	test( KErrNone == r || KErrAlreadyExists == r );
#endif

#ifdef UNMOUNT_DRIVE
	RFs fs;
	test( KErrNone == fs.Connect() );
#if 0
	// XXX not EKA2
	test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) );
#endif
	TFullName name;
	fs.FileSystemName( name, KLffsLogicalDriveNumber );
	if( name.Length() > 0 )
		{
		test.Printf( _L("Unmounting drive") );
		test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) );
		User::After( 2000000 );
		test.Printf( _L("Drive unmounted") );
		}
	fs.Close();
#endif

	//
	// Open a TBusLogicalDevice to it
	//
	test.Printf( _L("Opening media channel\n") );
	TBool changedFlag = EFalse;
	test( KErrNone == drive.Connect( KDriveNumber, changedFlag ) );
	
	//
	// Get size of Flash drive, block size, block count
	//
    drive.Caps(driveInfo);
	}



TInt E32Main()
    {

    test.Title();
    test.Start(_L("Testing CPU overhead"));

	Initialize();

	test.Printf( _L("Erasing first segment") );
	TInt r = EraseSegment( 0 );
	test( KErrNone == r );
	test.Printf( _L("Segment erased") );

	runTest();

	drive.Disconnect();
    test.End();
	return(KErrNone);
    }