kerneltest/e32test/misc/t_loadsim.cpp
branchRCL_3
changeset 44 3e88ff8f41d5
parent 43 c1f20ce4abcf
child 45 9e2d4f7f5028
--- a/kerneltest/e32test/misc/t_loadsim.cpp	Tue Aug 31 16:34:26 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2351 +0,0 @@
-// Copyright (c) 2009-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:
-// e32test\misc\t_loadsim.cpp
-// 
-//
-
-
-//-------------------------------------------------------------------------------------------
-//! @SYMTestCaseID				KBASE-t_loadsim-2705
-//! @SYMTestCaseDesc			verifying the behaviour of the load balancer
-//! @SYMPREQ					417-52765/417-58889
-//! @SYMTestPriority			Critical
-//! @SYMTestActions				
-//! 1. This test runs a variety of loads on an SMP system. Loads types are:
-//!    1.1 Cpu intensive loads
-//!    1.2 memory intensive loads (high locality)
-//!    1.3 memory intensive loads (low locality)
-//!    1.4 memory intensive loads with atomic operations
-//!    1.5 cpu intensive loads with some serialization
-//! 2. For each test, the load is first run on a single cpu locked thread as a baseline
-//!    benchmark. Then the tests are run in the following configurations:
-//!    2.1 For n = 1 to 2*Number of cpus do a run with i threads.
-//!    2.2 For h = 1 to NumCpus ; For n = h to 2*NumCpus; run with h high priorty threads and 
-//!         n standard priority threads, with high priority threads cpu locked.
-//!    2.3 For h = 1 to NumCpus ; For n = h to 2*NumCpus; run with h high priorty threads and 
-//!         n standard priority threads.
-//! @SYMTestExpectedResults 
-//!     test passed. TTest is manual:
-//! 1. For each test we expect to see that the amount of CPU time obtained by each CPU is 
-//!     balanced. That is, all standard priority threads get roughly same amount of CPU time
-//!     and all high priority threads get roughly same amount of CPU time and a higher value
-//!     than lower priority threads.
-//! 2. We also expect the relative efficiency reported by the test between the benchmark
-//!    and each test run to be >=95% on average. Values well below this are acceptable in 
-//!    test runs involving atomic operations (1.4)
-
-//-------------------------------------------------------------------------------------------
-
-#define __E32TEST_EXTENSION__
-#include <e32test.h>
-#include <e32base.h>
-#include <hal.h>
-#include <e32atomics.h>
-#include <u32hal.h>
-#include <e32svr.h>
-
-//#define	TRACE(x)	x
-#define	TRACE(x)
-
-void Panic(TInt aLine)
-	{
-	User::Panic(_L("T_LOADSIM"),aLine);
-	}
-
-#define	assert(x)		((void)((x)||(Panic(__LINE__),0)))
-
-RTest test(_L("T_LOADSIM"));
-
-const TInt KErrCouldNotStart = -99;
-
-volatile TInt STFU = 1;
-
-/******************************************************************************
- * Random Number Generation
- ******************************************************************************/
-void LFSR(TUint64& a)
-	{
-	TInt i;
-	for (i=64; i>0; --i)
-		{
-		TUint64 x = a<<1;
-		TUint64 y = x<<1;
-		x^=y;
-		a = (y>>1) | (x>>63);
-		}
-	}
-
-// Returns 256*log2(a/2^64)
-TInt Log2(TUint64 a)
-	{
-	const TUint64 KBit63 = UI64LIT(0x8000000000000000);
-	TInt n = __e32_find_ms1_64(a);
-	a <<= (63-n);
-	n -= 64;
-	TInt i;
-	for (i=0; i<8; ++i)
-		{
-		a >>= 32;
-		a *= a;
-		n <<= 1;
-		if (a & KBit63)
-			{
-			++n;
-			}
-		else
-			{
-			a <<= 1;
-			}
-		}
-	return n;
-	}
-
-TUint32 ExpRV(TUint64 aU, TUint32 aMean, TUint32 aTick)
-	{
-	TInt n = -Log2(aU);
-	TUint64 x = TUint64(n) * TUint64(aMean);
-	x *= TUint64(22713);	// 2^15 * ln2
-	TUint64 p(aTick);
-	p <<= 22;
-	x += p;
-	p += p;
-	x /= p;
-	return I64LOW(x);
-	}
-
-
-
-/******************************************************************************
- * Generic High-Resolution Timing
- ******************************************************************************/
-class TTimestamp
-	{
-public:
-	typedef void (*TSampleFunc)(TAny*);
-public:
-	void Sample();
-	void Sample(TSampleFunc aFunc, TAny* aPtr);
-	TInt64 operator-(const TTimestamp&) const;
-	static void Init();
-private:
-	TUint32		iF;		// User::FastCounter() value
-	TUint32		iN;		// User::NTickCount() value
-private:
-	static TUint32 FF;	// User::FastCounter() frequency
-	static TUint32 NP;	// User::NTickCount() period
-	static TBool FU;	// User::FastCounter() counts up
-	static TUint32 FWrapM;	// Number of nanokernel ticks for FastCounter() to wrap / 2 * 2^FWrapS
-	static TInt FWrapS;	// Shift so that 2^31<=FWrapM<2^32
-	};
-
-TUint32	TTimestamp::FF;
-TUint32	TTimestamp::NP;
-TBool	TTimestamp::FU;
-TUint32	TTimestamp::FWrapM;
-TInt	TTimestamp::FWrapS;
-
-
-void TTimestamp::Sample()
-	{
-	TUint32 n = User::NTickCount();
-	do	{
-		iN = n;
-		iF = User::FastCounter();
-		n = User::NTickCount();
-		} while (n!=iN);
-	}
-
-void TTimestamp::Sample(TSampleFunc aFunc, TAny* aPtr)
-	{
-	TUint32 n = User::NTickCount();
-	do	{
-		iN = n;
-		(*aFunc)(aPtr);
-		iF = User::FastCounter();
-		n = User::NTickCount();
-		} while (n!=iN);
-	}
-
-// return (x*a)/b
-TUint64 scale(TUint64 x, TUint32 a, TUint32 b)
-	{
-	TUint64 mask = KMaxTUint32;
-	TUint64 x0 = x & mask;
-	TUint64 x1 = x >> 32;
-	x0 *= TUint64(a);
-	x1 *= TUint64(a);
-	x1 += (x0 >> 32);
-	x0 &= mask;
-	TUint64	q1 = x1 / TUint64(b);
-	TUint64 q0 = x1 - q1*TUint64(b);
-	q0 <<= 32;
-	q0 |= x0;
-	q0 /= TUint64(b);
-	return (q1<<32)|q0;
-	}
-
-
-// Return difference between a and this in microseconds
-TInt64 TTimestamp::operator-(const TTimestamp& a) const
-	{
-	TInt sign = 1;
-	TTimestamp start;
-	TTimestamp end;
-	if (iN-a.iN >= 0x80000000u)
-		{
-		sign = -1;
-		start = *this;
-		end = a;
-		}
-	else
-		{
-		start = a;
-		end = *this;
-		}
-	TUint32 fd32 = end.iF - start.iF;
-	if (!FU)
-		fd32 = ~fd32 + 1u;
-	TUint64 nd = TUint64(end.iN) - TUint64(start.iN);
-	nd <<= 31;	// 2^31 * difference in NTickCount
-	TUint64 x = TUint64(fd32) * TUint64(FWrapM);
-	x >>= FWrapS;	// ftick difference * (FWrapM/2^FWrapS) = 2^31 * ntick difference
-	nd -= x;	// Should now be a multiple of 2^31N where N=2^32*ftickp/ntickp
-				// i.e. should be a multiple of 2^63*ftickp/ntickp
-
-	// FWrapM = 2^(31+FWrapS)*ftickp/ntickp
-	// FWrapM << (32-FWrapS) = 2^63*ftickp/ntickp
-	TUint64 m = TUint64(FWrapM) << (32-FWrapS);
-
-	nd += (m>>1);
-	nd /= m;
-
-	nd = (nd<<32) + TUint64(fd32);	// final result in fast counter ticks
-	TInt64 r = scale(nd, 1000000, FF);	// convert to microseconds
-	if (sign<0)
-		r = -r;
-	return r;
-	}
-
-void TTimestamp::Init()
-	{
-	TInt r;
-	r = HAL::Get(HAL::ENanoTickPeriod, (TInt&)NP);
-	assert(r==KErrNone);
-	r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)FF);
-	assert(r==KErrNone);
-	r = HAL::Get(HAL::EFastCounterCountsUp, (TInt&)FU);
-	assert(r==KErrNone);
-	TReal fpn = TReal(FF) * TReal(NP) / 1000000.0;	// fast counter ticks per NTick
-	TReal fwrap = 2147483648.0 / fpn;	// NTicks between fast counter wraparounds / 2
-	TInt exp = 0;
-	while (fwrap < 2147483648.0)
-		{
-		fwrap *= 2.0;
-		++exp;
-		}
-	fwrap += 0.5;
-	if (fwrap >= 4294967296.0)
-		{
-		fwrap *= 0.5;
-		--exp;
-		}
-	FWrapM = (TUint32)fwrap;
-	FWrapS = exp;	// NTicks for 2^31 fast ticks = FWrapM/2^FWrapS
-
-	test.Printf(_L("FastCounter frequency  %uHz\n"), FF);
-	if (FU)
-		test.Printf(_L("FastCounter counts     UP\n"));
-	else
-		test.Printf(_L("FastCounter counts     DOWN\n"));
-	test.Printf(_L("Nanokernel tick period %uus\n"), NP);
-	test.Printf(_L("FWrapM                 %08x\n"), FWrapM);
-	test.Printf(_L("FWrapS                 %d\n"), FWrapS);
-	}
-
-/******************************************************************************
- * CPU Usage Measurement
- ******************************************************************************/
-class TThreadCpuUsageSample
-	{
-public:
-	void Sample(RThread aThread);
-	TInt64 ElapsedTimeDelta(const TThreadCpuUsageSample& aStart) const;
-	TInt64 CpuTimeDelta(const TThreadCpuUsageSample& aStart) const;
-private:
-	static void SampleThreadCpuTime(TAny* aPtr);
-private:
-	TTimestamp	iElapsedTime;
-	TInt64		iCpuTime;
-	RThread		iThread;
-	};
-
-void TThreadCpuUsageSample::Sample(RThread aThread)
-	{
-	iThread = aThread;
-	iElapsedTime.Sample(&SampleThreadCpuTime, this);
-	}
-
-void TThreadCpuUsageSample::SampleThreadCpuTime(TAny* aPtr)
-	{
-	TThreadCpuUsageSample& me = *(TThreadCpuUsageSample*)aPtr;
-	TTimeIntervalMicroSeconds& rt = *(TTimeIntervalMicroSeconds*)&me.iCpuTime;
-	assert(me.iThread.GetCpuTime(rt) == KErrNone);
-	}
-
-TInt64 TThreadCpuUsageSample::ElapsedTimeDelta(const TThreadCpuUsageSample& aStart) const
-	{
-	return iElapsedTime - aStart.iElapsedTime;
-	}
-
-TInt64 TThreadCpuUsageSample::CpuTimeDelta(const TThreadCpuUsageSample& aStart) const
-	{
-	return iCpuTime - aStart.iCpuTime;
-	}
-
-class TCpuUsage
-	{
-public:
-	enum {EMaxCpus=8};
-public:
-	void Sample();
-	TInt64 ElapsedTimeDelta(const TCpuUsage& aStart) const;
-	TInt64 CpuTimeDelta(const TCpuUsage& aStart, TInt aCpu) const;
-	static TInt N() { return NumberOfCpus; }
-public:
-	static void Init();
-private:
-	static void SampleIdleTimes(TAny* aPtr);
-private:
-	TTimestamp	iElapsedTime;
-	TInt64		iIdleTime[EMaxCpus];
-private:
-	static TInt NumberOfCpus;
-	static RThread IdleThread[EMaxCpus];
-	};
-
-TInt TCpuUsage::NumberOfCpus = -1;
-RThread TCpuUsage::IdleThread[TCpuUsage::EMaxCpus];
-
-void TCpuUsage::Init()
-	{
-	TTimestamp::Init();
-
-	NumberOfCpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
-	test.Printf(_L("NumberOfCpus = %d\n"), NumberOfCpus);
-	assert(NumberOfCpus > 0);
-	assert(NumberOfCpus <= EMaxCpus);
-
-	TTimeIntervalMicroSeconds ms;
-	TInt r;
-	r = RThread().GetCpuTime(ms);
-	if (r != KErrNone)
-		{
-		test.Printf(_L("RThread::GetCpuTime() returned %d\n"), r);
-		test.Printf(_L("This test requires a working RThread::GetCpuTime() to run\n"));
-		test(0);
-		}
-
-	TFullName kname;
-	_LIT(KLitKernelName, "ekern.exe*");
-	_LIT(KLitNull, "::Null");
-	TFindProcess fp(KLitKernelName);
-	test_KErrNone(fp.Next(kname));
-	test.Printf(_L("Found kernel process: %S\n"), &kname);
-	kname.Append(KLitNull);
-	TInt i;
-	for (i=0; i<NumberOfCpus; ++i)
-		{
-		TFullName tname(kname);
-		TFullName tname2;
-		if (i>0)
-			tname.AppendNum(i);
-		TFindThread ft(tname);
-		test_KErrNone(ft.Next(tname2));
-		TInt r = IdleThread[i].Open(ft);
-		test_KErrNone(r);
-		IdleThread[i].FullName(tname2);
-		test.Printf(_L("Found and opened %S\n"), &tname2);
-		}
-	}
-
-void TCpuUsage::Sample()
-	{
-	iElapsedTime.Sample(&SampleIdleTimes, this);
-	}
-
-void TCpuUsage::SampleIdleTimes(TAny* aPtr)
-	{
-	TCpuUsage& me = *(TCpuUsage*)aPtr;
-	assert(NumberOfCpus > 0);
-	TInt i;
-	for (i=0; i<NumberOfCpus; ++i)
-		assert(IdleThread[i].GetCpuTime((TTimeIntervalMicroSeconds&)me.iIdleTime[i]) == KErrNone);
-	}
-
-TInt64 TCpuUsage::ElapsedTimeDelta(const TCpuUsage& aStart) const
-	{
-	return iElapsedTime - aStart.iElapsedTime;
-	}
-
-TInt64 TCpuUsage::CpuTimeDelta(const TCpuUsage& aStart, TInt aCpu) const
-	{
-	assert(TUint(aCpu) < TUint(EMaxCpus));
-	if (aCpu >= NumberOfCpus)
-		return 0;
-	TInt64 idle_time = iIdleTime[aCpu] - aStart.iIdleTime[aCpu];
-	TInt64 elapsed_time = iElapsedTime - aStart.iElapsedTime;
-	return elapsed_time - idle_time;
-	}
-
- 
- 
-/******************************************************************************
- * Generic CPU Consumer
- ******************************************************************************/
-enum TCpuEaterType
-	{
-	EEaterStd				=0,		// do CPU-intensive work with few memory references
-	EEaterMemoryLocalS		=1,		// do loads of memory references with reasonable locality, shared
-	EEaterMemoryNonLocalS	=2,		// do loads of memory references with poor locality, shared
-	EEaterMemoryLocalU		=3,		// do loads of memory references with reasonable locality, unshared
-	EEaterMemoryNonLocalU	=4,		// do loads of memory references with poor locality, unshared
-	EEaterMemoryAtomic		=5,		// do loads of atomic memory references
-	EEaterMemoryAtomic2		=6,		// do loads of atomic memory references
-	EEaterAmdahl			=7,		// do CPU-intensive work interspersed with serialized sections
-	};
-
-class CDefaultCpuEater;
-
-class REaterArray;
-class MCpuEater
-	{
-public:
-	MCpuEater();
-	virtual ~MCpuEater();
-	virtual void Eat(TInt aTime, TUint32* aWorkDone)=0;
-	virtual void Calibrate();
-	inline TBool IsCalibrated() { return iCalibration!=0; }
-protected:
-	TUint32 WorkValue(TInt aTime);
-	TUint32	iCalibration;	// work value for 2^16 microseconds
-	TUint16	iInstance;
-	TUint16	iType;
-
-	friend class REaterArray;
-	};
-
-MCpuEater::MCpuEater()
-	{
-	iCalibration = 0;			// uncalibrated
-	iInstance = KMaxTUint16;	// dummy value
-	iType = KMaxTUint16;		// dummy value
-	}
-
-MCpuEater::~MCpuEater()
-	{
-	}
-
-// Calibration is for 2^KLog2CalibrateTime microseconds
-const TInt KLog2CalibrateTime = 13;
-
-TUint32 MCpuEater::WorkValue(TInt aTime)
-	{
-	if (iCalibration == 0)
-		return aTime;
-	TUint64 x = TUint64(aTime) * TUint64(iCalibration);
-	x >>= (KLog2CalibrateTime + 2);	// Factor of 4 margin for slowdowns
-	TUint32 r = I64LOW(x);
-	if (I64HIGH(x))
-		r = KMaxTUint32;
-	if (r == 0)
-		return 1;
-	if (r > iCalibration)
-		return iCalibration;
-	return r;
-	}
-
-void MCpuEater::Calibrate()
-	{
-	iCalibration = 0;
-	TUint32 work = 1;
-	TUint64 used = 1;
-	TUint64 threshold = 1;
-	threshold <<= KLog2CalibrateTime;
-	while (work)
-		{
-		TThreadCpuUsageSample initial;
-		TThreadCpuUsageSample final;
-		initial.Sample(RThread());
-		Eat(work, 0);
-		final.Sample(RThread());
-		used = final.CpuTimeDelta(initial);
-		if (used >= threshold)
-			break;
-		work <<= 1;
-		}
-	assert(work > 0);
-	TUint64 c(work);
-	c <<= KLog2CalibrateTime;
-	c /= used;
-	if (I64HIGH(c))
-		iCalibration = KMaxTUint32;
-	else if (I64LOW(c))
-		iCalibration = I64LOW(c);
-	else
-		iCalibration = 1;
-	test.Printf(_L("MCpuEater::Calibrate() %u\n"), iCalibration);
-	}
-
-
-class REaterArray : public RPointerArray<MCpuEater>
-	{
-public:
-	REaterArray();
-	void Close();
-	MCpuEater* Find(TInt aType, TInt aInstance);
-	MCpuEater* FindOrCreateL(TInt aType, TInt aInstance);
-private:
-	MCpuEater* CreateLC(TInt aType);
-private:
-	class MDummy : public MCpuEater
-		{
-	public:
-		MDummy(TInt aType, TInt aInstance)
-			{ iType=TUint16(aType); iInstance=TUint16(aInstance); }
-		virtual ~MDummy()
-			{}
-		virtual void Eat(TInt, TUint32*)
-			{}
-		};
-private:
-	static TBool Identity(const MCpuEater& aL, const MCpuEater& aR);
-	static TInt Ordering(const MCpuEater& aL, const MCpuEater& aR);
-	};
-
-REaterArray::REaterArray()
-	:	RPointerArray<MCpuEater>(8, 2*256)
-	{
-	}
-
-void REaterArray::Close()
-	{
-	ResetAndDestroy();
-	}
-
-TBool REaterArray::Identity(const MCpuEater& aL, const MCpuEater& aR)
-	{
-	return (aL.iType==aR.iType && aL.iInstance==aR.iInstance);
-	}
-
-TInt REaterArray::Ordering(const MCpuEater& aL, const MCpuEater& aR)
-	{
-	if (aL.iType > aR.iType)
-		return 1;
-	if (aL.iType < aR.iType)
-		return -1;
-	if (aL.iInstance > aR.iInstance)
-		return 1;
-	if (aL.iInstance < aR.iInstance)
-		return -1;
-	return 0;
-	}
-
-MCpuEater* REaterArray::Find(TInt aType, TInt aInstance)
-	{
-	MDummy search(aType, aInstance);
-	TInt ix = FindInOrder(&search, &Ordering);
-	if (ix < 0)
-		return 0;
-	return (*this)[ix];
-	}
-
-MCpuEater* REaterArray::FindOrCreateL(TInt aType, TInt aInstance)
-	{
-	MCpuEater* p = Find(aType, aInstance);
-	if (p)
-		return p;
-	p = CreateLC(aType);
-	p->iType = TUint16(aType);
-	p->iInstance = TUint16(aInstance);
-	InsertInOrderL(p, &Ordering);
-	CleanupStack::Pop();
-	return p;
-	}
-
-/******************************************************************************
- * Generic zero-drift timed events
- ******************************************************************************/
-class CLoadSim;
-class MEvent
-	{
-public:
-	MEvent(CLoadSim*, TInt);
-	virtual void Start()=0;
-	virtual ~MEvent();
-	inline TBool Queued() const
-		{ return iQueued; }
-protected:
-	void QueueAt(TUint32 aTime);
-	void QueueAfter(TUint32 aInterval);
-	void Dequeue();
-	virtual TInt Event();
-	inline TUint64 Random();
-protected:
-	TUint8		iId;
-	TUint8		iQueued;
-	TUint8		iE1;
-	TUint8		iE2;
-	MEvent*		iChain;
-	CLoadSim*	iT;
-	TUint32		iNextEventTime;
-	friend class CLoadSim;
-	};
-
-class CLoadSim : public CActive
-	{
-public:
-	static CLoadSim* NewL();
-	~CLoadSim();
-	inline TInt TimerPeriod() const
-		{ return iTimerPeriod; }
-	TUint64 Random();
-private:
-	CLoadSim();
-	virtual void RunL();
-	virtual void DoCancel();
-	void StartTimer();
-private:
-	RTimer		iTimer;
-	TUint64		iSeed;
-	MEvent*		iNextEvent;
-	TUint32		iIterations;
-	TUint32		iLastTrigger;		// Last trigger time in ticks
-	TInt		iCarry;
-	TInt		iTimerPeriod;		// Timer tick period in microseconds
-	TInt		iMaxDelta;
-	TUint8		iInRunL;
-	TUint8		iTimerRunning;
-	TUint8		iTimerInit;
-	TUint8		iOffsetInit;
-	TUint32		iOffset;
-private:
-	friend class MEvent;
-	};
-
-inline TUint64 MEvent::Random()
-	{ return iT->Random(); }
-
-CLoadSim::CLoadSim()
-	: CActive(EPriorityStandard)
-	{
-	iSeed = 0xadf85458;
-	assert(HAL::Get(HAL::ENanoTickPeriod, iTimerPeriod)==KErrNone);
-	iMaxDelta = KMaxTInt / (2*iTimerPeriod);
-	}
-
-CLoadSim::~CLoadSim()
-	{
-	Cancel();
-	iTimer.Close();
-	}
-
-CLoadSim* CLoadSim::NewL()
-	{
-	CLoadSim* p = new (ELeave) CLoadSim();
-	CleanupStack::PushL(p);
-	User::LeaveIfError(p->iTimer.CreateLocal());
-	CleanupStack::Pop();
-	return p;
-	}
-
-void CLoadSim::DoCancel()
-	{
-	iTimer.Cancel();
-	iTimerRunning = 0;
-	}
-
-void CLoadSim::RunL()
-	{
-	TRACE(RDebug::Printf("!%d\n", iStatus.Int()));
-	iTimerRunning = 0;
-	iInRunL = 1;
-	TUint32 now = iLastTrigger;
-	if (iStatus == KErrNone)
-		{
-		now += iCarry;
-		iLastTrigger = now;
-		}
-	else if (iStatus == KErrArgument)
-		{
-		now += iCarry;
-		}
-	else if (iStatus == KErrCancel)
-		{
-		iLastTrigger += iCarry;	// trigger time was still updated
-		}
-	iCarry = 0;
-	MEvent* e = 0;
-	FOREVER
-		{
-		++iIterations;
-		e = iNextEvent;
-		if (!e || e->iNextEventTime>now)
-			break;
-		iNextEvent = e->iChain;
-		e->iChain = 0;
-		e->iQueued = 0;
-		e->Event();
-		}
-	if (e)
-		{
-		TInt delta = TInt(e->iNextEventTime - iLastTrigger);
-		if (delta > iMaxDelta)
-			delta = iMaxDelta;
-		if (delta < -iMaxDelta)
-			delta = -iMaxDelta;
-		iCarry = delta;
-		TInt us = delta * iTimerPeriod;
-		TRACE(RDebug::Printf("T+%d\n", us));
-		iTimer.AgainHighRes(iStatus, us);
-		SetActive();
-		iTimerRunning = 1;
-		}
-	iInRunL = 0;
-	}
-
-void CLoadSim::StartTimer()
-	{
-	if (iInRunL)
-		return;
-	if (iTimerRunning)
-		{
-		TRACE(RDebug::Printf("TC\n"));
-		iTimer.Cancel();	// will cause RunL with KErrCancel which will restart timer
-		return;
-		}
-	TInt delta = TInt(iNextEvent->iNextEventTime - iLastTrigger);
-	if (delta > iMaxDelta)
-		delta = iMaxDelta;
-	if (delta < -iMaxDelta)
-		delta = -iMaxDelta;
-	iCarry = delta;
-	TInt us = delta * iTimerPeriod;
-	if (iTimerInit)
-		{
-		TRACE(RDebug::Printf("sT+%d\n", us));
-		iTimer.AgainHighRes(iStatus, us);
-		}
-	else
-		{
-		if (!iOffsetInit)
-			iOffsetInit=1, iOffset=User::NTickCount();
-		TRACE(RDebug::Printf("sT++%d\n", us));
-		iTimer.HighRes(iStatus, us);
-		iTimerInit = 1;
-		}
-	SetActive();
-	iTimerRunning = 1;
-	}
-
-TUint64 CLoadSim::Random()
-	{
-	LFSR(iSeed);
-	TUint32 h = I64HIGH(iSeed);
-	TUint32 l = I64LOW(iSeed);
-	h *= 0x9e3779b9u;
-	l *= 0x9e3779b9u;
-	return MAKE_TUINT64(l,h);
-	}
-
-MEvent::MEvent(CLoadSim* aT, TInt aId)
-	{
-	iId = (TUint8)aId;
-	iQueued = 0;
-	iE1 = 0;
-	iE2 = 0;
-	iChain = 0;
-	iT = aT;
-	iNextEventTime = 0;
-	}
-
-MEvent::~MEvent()
-	{
-	if (iT)
-		Dequeue();
-	}
-
-void MEvent::QueueAt(TUint32 aTime)
-	{
-	TRACE(RDebug::Printf("Q%d@%u\n", iId, aTime));
-	if (iQueued)
-		Dequeue();
-	MEvent** p = &iT->iNextEvent;
-	MEvent* e = iT->iNextEvent;
-	for (; e && e->iNextEventTime <= aTime; p=&e->iChain, e=e->iChain)
-		{}
-	iChain = e;
-	*p = this;
-	iNextEventTime = aTime;
-	iQueued = 1;
-	if (iT->iNextEvent==this && !iT->iInRunL)
-		iT->StartTimer();
-	}
-
-void MEvent::QueueAfter(TUint32 aInterval)
-	{
-	TRACE(RDebug::Printf("Q%d+%u\n", iId, aInterval));
-	TUint32 now = User::NTickCount();
-	if (!iT->iTimerInit)
-		iT->iOffset=now, iT->iOffsetInit=1;
-	QueueAt(now-iT->iOffset+aInterval);
-	}
-
-void MEvent::Dequeue()
-	{
-	TRACE(RDebug::Printf("DQ%d\n", iId));
-	if (!iQueued)
-		return;
-	MEvent* e = iT->iNextEvent;
-	for (; e && e->iChain!=this; e=e->iChain)
-		{}
-	if (e)
-		{
-		e->iChain = iChain;
-		}
-	iChain = 0;
-	iQueued = 0;
-	}
-
-TInt MEvent::Event()
-	{
-	TRACE(RDebug::Printf("*%d\n", iId));
-	return iId;
-	}
-
-
-
-/******************************************************************************
- * Poisson process simulation
- ******************************************************************************/
-class MDiscretePoisson : public MEvent
-	{
-public:
-	MDiscretePoisson(CLoadSim* aT, TInt aId, TUint32 aMicroseconds);
-	~MDiscretePoisson();
-	virtual void Start();
-	virtual TInt Event();
-	virtual void PoissonEvent();
-public:
-	TUint32		iUs;
-	TBool		iContinue;
-	};
-
-MDiscretePoisson::MDiscretePoisson(CLoadSim* aT, TInt aId, TUint32 aMicroseconds)
-	:	MEvent(aT, aId)
-	{
-	iUs = aMicroseconds;
-	iContinue = EFalse;
-	}
-
-MDiscretePoisson::~MDiscretePoisson()
-	{
-	}
-
-void MDiscretePoisson::Start()
-	{
-	iContinue = ETrue;
-	TUint32 gap = ExpRV(Random(), iUs, iT->TimerPeriod());
-	TRACE(RDebug::Printf("GG%u\n", gap));
-	QueueAt(iNextEventTime + gap);
-	}
-
-TInt MDiscretePoisson::Event()
-	{
-	PoissonEvent();
-	if (iContinue)
-		Start();
-	return MEvent::Event();
-	}
-
-void MDiscretePoisson::PoissonEvent()
-	{
-	}
-
-
-
-/******************************************************************************
- * Consume a specified amount of CPU time in either a continuous
- * or 'staccato' fashion (i.e. in irregular intervals punctuated by gaps)
- ******************************************************************************/
-class CStaccatoCpuEater : public CActive, public MEvent
-	{
-public:
-	CStaccatoCpuEater(CLoadSim* aT, MCpuEater* aE, TUint32 aGranularity, TUint32 aMeanGap);
-	~CStaccatoCpuEater();
-	void EatMore(TInt64 aMicroseconds);
-	TUint32 WorkDone() const { return iWorkDone; }
-	TUint32 Invocations() const { return iInvocations; }
-private:
-	virtual void RunL();
-	virtual void DoCancel();
-	virtual void Start();
-	virtual TInt Event();
-	void StartEating();
-private:
-	MCpuEater* iE;
-	TUint32 iWorkDone;
-	TUint32 iInvocations;
-	TUint32 iGranularity;
-	TUint32 iMeanGap;
-	TBool iEating;
-	TInt64 iRemainingCpuTime;
-	TTimeIntervalMicroSeconds iInitialCpuTime;
-	TTimeIntervalMicroSeconds iFinalCpuTime;
-	TInt64 iTotalCpuTime;
-	};
-
-CStaccatoCpuEater::CStaccatoCpuEater(CLoadSim* aT, MCpuEater* aE, TUint32 aGranularity, TUint32 aMeanGap)
-	:	CActive(EPriorityIdle),
-		MEvent(aT, 0x53)
-	{
-	iE = aE;
-	iWorkDone = 0;
-	iInvocations = 0;
-	iGranularity = aGranularity;
-	iMeanGap = aMeanGap;
-	iEating = EFalse;
-	iRemainingCpuTime = 0;
-	}
-
-CStaccatoCpuEater::~CStaccatoCpuEater()
-	{
-	Cancel();
-	}
-
-void CStaccatoCpuEater::EatMore(TInt64 aMicroseconds)
-	{
-	TRACE(RDebug::Printf("E+%08x %08x\n", I64HIGH(aMicroseconds), I64LOW(aMicroseconds)));
-	iRemainingCpuTime += aMicroseconds;
-	if (!Queued() && !iEating && iRemainingCpuTime>0)
-		StartEating();
-	}
-
-void CStaccatoCpuEater::RunL()
-	{
-	TInt time = KMaxTInt;
-	if (iRemainingCpuTime < TInt64(KMaxTInt))
-		time = I64LOW(iRemainingCpuTime);
-	++iInvocations;
-	iE->Eat(time, &iWorkDone);
-	TTimeIntervalMicroSeconds ms;
-	TInt r = RThread().GetCpuTime(ms);
-	assert(r==KErrNone);
-	if (ms < iFinalCpuTime)
-		{
-		SetActive();
-		TRequestStatus* pS = &iStatus;
-		User::RequestComplete(pS, 0);
-		return;
-		}
-	iEating = EFalse;
-	TInt64 delta = ms.Int64() - iInitialCpuTime.Int64();
-	iRemainingCpuTime -= delta;
-	iTotalCpuTime += delta;
-	TRACE(RDebug::Printf("D=%8u T=%10u\n",I64LOW(delta),I64LOW(iTotalCpuTime)));
-	if (iRemainingCpuTime > 0)
-		{
-		TUint32 gap = ExpRV(Random(), iMeanGap, iT->TimerPeriod());
-		TRACE(RDebug::Printf("G%u\n", gap));
-		QueueAfter(gap);
-		}
-	}
-
-void CStaccatoCpuEater::DoCancel()
-	{
-	MEvent::Dequeue();
-	iEating = EFalse;
-	}
-
-void CStaccatoCpuEater::Start()
-	{
-	}
-
-TInt CStaccatoCpuEater::Event()
-	{
-	if (!iEating && iRemainingCpuTime>0)
-		{
-		StartEating();
-		}
-	return MEvent::Event();
-	}
-
-void CStaccatoCpuEater::StartEating()
-	{
-	iEating = ETrue;
-	TInt r = RThread().GetCpuTime(iInitialCpuTime);
-	assert(r==KErrNone);
-	if (iGranularity)
-		{
-		TInt howmuch = ExpRV(iT->Random(), iGranularity, 1);
-		TRACE(RDebug::Printf("SE+%08x\n", howmuch));
-		iFinalCpuTime = iInitialCpuTime.Int64() + TInt64(howmuch);
-		}
-	else
-		iFinalCpuTime = iInitialCpuTime.Int64() + iRemainingCpuTime;	// continuous CPU use
-	SetActive();
-	TRequestStatus* pS = &iStatus;
-	User::RequestComplete(pS, 0);
-	}
-
-
-
-/******************************************************************************
- * Consume CPU time in a bursty fashion
- ******************************************************************************/
-class CBurstyCpuEater : public CStaccatoCpuEater, public MDiscretePoisson
-	{
-public:
-	struct SParams
-		{
-		MCpuEater*	iE;
-		TUint32		iGranularity;
-		TUint32		iMeanIntraBurstGap;
-		TUint32		iMeanBurstLength;
-		TUint32		iMeanInterBurstGap;
-		};
-public:
-	CBurstyCpuEater(CLoadSim* aT, const SParams& aParams);
-	~CBurstyCpuEater();
-	virtual void Start();
-	virtual void PoissonEvent();
-public:
-	TUint32		iMeanBurstLength;
-	TUint32		iMeanInterBurstGap;
-	};
-
-CBurstyCpuEater::CBurstyCpuEater(CLoadSim* aT, const SParams& aParams)
-	:	CStaccatoCpuEater(aT, aParams.iE, aParams.iGranularity, aParams.iMeanIntraBurstGap),
-		MDiscretePoisson(aT, 0x42, aParams.iMeanInterBurstGap)
-	{
-	iMeanBurstLength = aParams.iMeanBurstLength;
-	iMeanInterBurstGap = aParams.iMeanInterBurstGap;
-	}
-
-CBurstyCpuEater::~CBurstyCpuEater()
-	{
-	}
-
-void CBurstyCpuEater::Start()
-	{
-	if (iMeanInterBurstGap > 0)
-		{
-		PoissonEvent();
-		MDiscretePoisson::Start();
-		}
-	else
-		{
-		EatMore(iMeanBurstLength);	// one single burst
-		}
-	}
-
-void CBurstyCpuEater::PoissonEvent()
-	{
-	TInt burstLen = ExpRV(CStaccatoCpuEater::Random(), iMeanBurstLength, 1);
-	EatMore(burstLen);
-	}
-
-
-
-/******************************************************************************
- * Stop the active scheduler after a certain time
- ******************************************************************************/
-class CTimedStopper : public CActive
-	{
-public:
-	static CTimedStopper* NewL();
-	~CTimedStopper();
-	void Start(TInt64 aMicroseconds);
-private:
-	CTimedStopper();
-	virtual void RunL();
-	virtual void DoCancel();
-private:
-	RTimer	iTimer;
-	};
-
-CTimedStopper::CTimedStopper()
-	:	CActive(EPriorityHigh)
-	{
-	}
-
-CTimedStopper::~CTimedStopper()
-	{
-	Cancel();
-	iTimer.Close();
-	}
-
-CTimedStopper* CTimedStopper::NewL()
-	{
-	CTimedStopper* p = new (ELeave) CTimedStopper();
-	CleanupStack::PushL(p);
-	User::LeaveIfError(p->iTimer.CreateLocal());
-	CleanupStack::Pop();
-	return p;
-	}
-
-void CTimedStopper::DoCancel()
-	{
-	iTimer.Cancel();
-	}
-
-void CTimedStopper::RunL()
-	{
-	CActiveScheduler::Stop();
-	}
-
-void CTimedStopper::Start(TInt64 aMicroseconds)
-	{
-	TInt p = (TInt)aMicroseconds;
-	iTimer.HighRes(iStatus, p);
-	SetActive();
-	}
-
-
-
-
-
-/******************************************************************************
- * Do something CPU intensive to consume CPU time
- ******************************************************************************/
-class CDefaultCpuEater : public CBase, public MCpuEater
-	{
-public:
-	CDefaultCpuEater();
-	~CDefaultCpuEater();
-	virtual void Eat(TInt aTime, TUint32* aWorkDone);
-protected:
-	TUint64 iX;
-	};
-
-CDefaultCpuEater::CDefaultCpuEater()
-	{
-	iX = 1;
-	}
-
-CDefaultCpuEater::~CDefaultCpuEater()
-	{
-	}
-
-void CDefaultCpuEater::Eat(TInt aTime, TUint32* aWorkDone)
-	{
-	const TUint64 KMagic = UI64LIT(0x9e3779b97f4a7c15);
-	TUint32 work = WorkValue(aTime);
-	if (aWorkDone)
-		*aWorkDone += work;
-	while (work--)
-		iX *= KMagic;
-	}
-
-
-
-/******************************************************************************
- * Do something CPU intensive to consume CPU time, partially serialized
- ******************************************************************************/
-class CAmdahlCpuEater : public CDefaultCpuEater
-	{
-public:
-	static CAmdahlCpuEater* NewLC();
-	~CAmdahlCpuEater();
-	virtual void Eat(TInt aTime, TUint32* aWorkDone);
-protected:
-	CAmdahlCpuEater();
-	void ConstructL();
-protected:
-	RMutex iMutex;
-	TUint32 iFactor;
-	};
-
-CAmdahlCpuEater::CAmdahlCpuEater()
-	{
-	}
-
-CAmdahlCpuEater::~CAmdahlCpuEater()
-	{
-	iMutex.Close();
-	}
-
-CAmdahlCpuEater* CAmdahlCpuEater::NewLC()
-	{
-	CAmdahlCpuEater* p = new (ELeave) CAmdahlCpuEater();
-	CleanupStack::PushL(p);
-	p->ConstructL();
-	return p;
-	}
-
-void CAmdahlCpuEater::ConstructL()
-	{
-	User::LeaveIfError(iMutex.CreateLocal());
-	iFactor = KMaxTUint32 / (4*TCpuUsage::N());
-	}
-
-void CAmdahlCpuEater::Eat(TInt aTime, TUint32* aWorkDone)
-	{
-	TUint64 t(aTime);
-	t *= TUint64(iFactor);
-	t += TUint64(0x80000000u);
-	t >>= 32;
-	TInt stime = I64LOW(t);
-	if (IsCalibrated())
-		{
-		iMutex.Wait();
-		CDefaultCpuEater::Eat(stime, aWorkDone);
-		aTime -= stime;
-		iMutex.Signal();
-		}
-	CDefaultCpuEater::Eat(aTime, aWorkDone);
-	}
-
-
-
-/******************************************************************************
- * Do something memory intensive to consume CPU time
- ******************************************************************************/
-class CMemoryBandwidthEater : public CBase, public MCpuEater
-	{
-public:
-	static CMemoryBandwidthEater* NewLC(TUint32 aSize, TUint32 aRegionSize, TUint32 aRegionOffset);
-	~CMemoryBandwidthEater();
-	virtual void Calibrate();
-protected:
-	CMemoryBandwidthEater(TUint32 aSize, TUint32 aRegionSize, TUint32 aRegionOffset);
-	void ConstructL();
-	virtual void Eat(TInt aTime, TUint32* aWorkDone);
-	TAny* At(TUint32 aRegion, TUint32 aIndex);
-	TAny* StepWithinRegion(TAny* aInitial, TUint32 aStep);
-protected:
-	volatile TUint32 iRegionAlloc;
-	TUint32 iPageSize;
-	TUint32 iSize;				// multiple of page size
-	TAny* iData;				// page aligned
-	RChunk iChunk;
-	TUint8 iLog2RegionSize;		// log2(bytes per region)
-	TUint8 iLog2RO;				// log2(offset from region n to n+1 in bytes)
-	TUint8 iLog2PageSize;
-	TUint8 iRegionBits;			// number of bits to specify region
-	TUint32 iNRgn;
-	TUint32 iRegionMask;
-	TUint32 iLowerIndexMask;
-	TUint32 iUpperIndexMask;
-	};
-
-TUint32 AtomicClearLS1(volatile TUint32* aMask)
-	{
-	TUint32 initial = *aMask;
-	TUint32 final;
-	do	{
-		final = initial & (initial-1);
-		} while(!__e32_atomic_cas_ord32(aMask, &initial, final));
-	return initial;
-	}
-
-TInt AtomicAllocBit(volatile TUint32* aMask)
-	{
-	return __e32_find_ls1_32(AtomicClearLS1(aMask));
-	}
-
-TUint32 AtomicFreeBit(volatile TUint32* aMask, TInt aBit)
-	{
-	return __e32_atomic_ior_ord32(aMask, 1u<<aBit);
-	}
-
-
-
-CMemoryBandwidthEater* CMemoryBandwidthEater::NewLC(TUint32 aSize, TUint32 aRegionSize, TUint32 aRegionOffset)
-	{
-	CMemoryBandwidthEater* p = new (ELeave) CMemoryBandwidthEater(aSize, aRegionSize, aRegionOffset);
-	CleanupStack::PushL(p);
-	p->ConstructL();
-	return p;
-	}
-
-CMemoryBandwidthEater::CMemoryBandwidthEater(TUint32 aSize, TUint32 aRegionSize, TUint32 aRegionOffset)
-	{
-	TInt r = HAL::Get(HAL::EMemoryPageSize, (TInt&)iPageSize);
-	assert(r==KErrNone);
-	iLog2PageSize = (TUint8)__e32_find_ms1_32(iPageSize);
-	assert( !(aRegionSize & (aRegionSize-1)) );
-	assert( !(aRegionOffset & (aRegionOffset-1)) );
-	iLog2RegionSize = (TUint8)__e32_find_ms1_32(aRegionSize);
-	iLog2RO = (TUint8)__e32_find_ms1_32(aRegionOffset);
-	TUint32 round = (aRegionSize>iPageSize) ? aRegionSize : iPageSize;
-	iSize = (aSize + round - 1) &~ (round - 1);
-	--iSize;
-	iSize |= (iSize>>1);
-	iSize |= (iSize>>2);
-	iSize |= (iSize>>4);
-	iSize |= (iSize>>8);
-	iSize |= (iSize>>16);
-	++iSize;
-	iNRgn = iSize >> iLog2RegionSize;
-	if (iNRgn>=32)
-		iRegionAlloc = ~0u;
-	else
-		iRegionAlloc = ~((~0u)<<iNRgn);
-	iRegionBits = TUint8(1 + __e32_find_ms1_32(iNRgn-1));
-	iLowerIndexMask = ~((~0u)<<iLog2RO);
-	iRegionMask = (~((~0u)<<iRegionBits))<<iLog2RO;
-	iUpperIndexMask = ((iSize-1)>>(iRegionBits+iLog2RO))<<(iRegionBits+iLog2RO);
-	}
-
-CMemoryBandwidthEater::~CMemoryBandwidthEater()
-	{
-	iChunk.Close();
-	}
-
-void CMemoryBandwidthEater::ConstructL()
-	{
-	TInt mask = (1<<20)-1;
-	TInt maxSize = (TInt(iSize)+mask)&~mask;
-	User::LeaveIfError(iChunk.CreateLocal(iSize, maxSize, EOwnerThread));
-	iData = iChunk.Base();
-	}
-
-void CMemoryBandwidthEater::Calibrate()
-	{
-	MCpuEater::Calibrate();
-	MCpuEater::Calibrate();
-	}
-
-TAny* CMemoryBandwidthEater::At(TUint32 aRegion, TUint32 aIndex)
-	{
-	TUint32 offset = aIndex & iLowerIndexMask;
-	offset |= (aRegion<<iLog2RO);
-	offset |= ((aIndex<<iRegionBits) & iUpperIndexMask);
-	return ((TUint8*)iData) + offset;
-	}
-
-TAny* CMemoryBandwidthEater::StepWithinRegion(TAny* aInitial, TUint32 aStep)
-	{
-	TUintPtr offset = TUintPtr(aInitial) - TUintPtr(iData);
-	TUintPtr offset2 = offset + (aStep & iLowerIndexMask);
-	if ((offset^offset2)&iRegionMask)
-		{
-		offset2 -= (iLowerIndexMask+1);
-		aStep += (iLowerIndexMask+1);
-		}
-	offset2 += ((aStep<<iRegionBits)&iUpperIndexMask);
-	offset2 &= (iSize-1);
-	return ((TUint8*)iData) + offset2;
-	}
-
-void CMemoryBandwidthEater::Eat(TInt aTime, TUint32* aWorkDone)
-	{
-	TUint32 work = WorkValue(aTime);
-	if (aWorkDone)
-		*aWorkDone += work;
-	TInt region = AtomicAllocBit(&iRegionAlloc);
-	assert(region>=0);
-	TUint32 done = 0;
-	TUint32 rgnsz = 1u << iLog2RegionSize;
-	for (; work; work-=done)
-		{
-		done = (work>rgnsz) ? rgnsz : work;
-		TUint8* p = (TUint8*)At(region,0);
-		TUint8 prev = *p;
-		TUint32 n = done;
-		do	{
-			TUint8* q = p;
-			p = (TUint8*)StepWithinRegion(p, 31);
-			*q = *p;
-			} while(--n);
-		*p = prev;
-		}
-	AtomicFreeBit(&iRegionAlloc, region);
-	}
-
-
-/******************************************************************************
- * Do lots of atomic operations to consume CPU time
- ******************************************************************************/
-class CAtomicMemoryBandwidthEater : public CMemoryBandwidthEater
-	{
-public:
-	static CAtomicMemoryBandwidthEater* NewLC(TUint32 aSize);
-	~CAtomicMemoryBandwidthEater();
-protected:
-	CAtomicMemoryBandwidthEater(TUint32 aSize);
-	void ConstructL();
-	virtual void Eat(TInt aTime, TUint32* aWorkDone);
-protected:
-	volatile TUint32 iX;
-	};
-
-CAtomicMemoryBandwidthEater* CAtomicMemoryBandwidthEater::NewLC(TUint32 aSize)
-	{
-	CAtomicMemoryBandwidthEater* p = new (ELeave) CAtomicMemoryBandwidthEater(aSize);
-	CleanupStack::PushL(p);
-	p->ConstructL();
-	return p;
-	}
-
-CAtomicMemoryBandwidthEater::CAtomicMemoryBandwidthEater(TUint32 aSize)
-	:	CMemoryBandwidthEater(aSize, aSize, aSize)
-	{
-	iX = TUint32(this) ^ RThread().Id().operator TUint();
-	iX *= 0x9e3779b9u;
-	}
-
-CAtomicMemoryBandwidthEater::~CAtomicMemoryBandwidthEater()
-	{
-	}
-
-void CAtomicMemoryBandwidthEater::ConstructL()
-	{
-	CMemoryBandwidthEater::ConstructL();
-	}
-
-TUint32 AtomicRandom(volatile TUint32* a)
-	{
-	TUint32 initial = *a;
-	TUint32 final;
-	do	{
-		final = 69069*initial + 41;
-		} while(!__e32_atomic_cas_ord32(a, &initial, final));
-	return final;
-	}
-
-void CAtomicMemoryBandwidthEater::Eat(TInt aTime, TUint32* aWorkDone)
-	{
-	TUint32 work = WorkValue(aTime);
-	if (aWorkDone)
-		*aWorkDone += work;
-	volatile TUint32* pW = (volatile TUint32*)iData;
-	const TUint32 mask = iSize/sizeof(TUint32)-1;
-	TUint32 x = AtomicRandom(&iX);
-	TUint32 n = work;
-	do	{
-		TUint32 offset = (x>>2) & mask;
-		x = 69069*x+41;
-		__e32_atomic_add_rlx32(pW+offset, 1);
-		} while(--n);
-	}
-
-
-/******************************************************************************
- *
- ******************************************************************************/
-struct SThreadResult
-	{
-	TUint64		iElapsedTime;
-	TUint64		iCpuTime;
-	TUint32		iWorkDone;
-	TUint32		iInvocations;
-	};
-
-struct SThreadParams
-	{
-	TInt64		iTestTime;
-
-	TInt		iId;
-	TUint32		iCpuAffinity;
-
-	TInt		iPriority;
-	RSemaphore	iTurnstile;
-
-	SThreadResult* iResult;
-	TInt		iGroupId;
-
-	MCpuEater*	iE;
-	TUint32		iGranularity;
-	TUint32		iMeanIntraBurstGap;
-	TUint32		iMeanBurstLength;
-	TUint32		iMeanInterBurstGap;
-	};
-
-class MThreadCompletion
-	{
-public:
-	virtual void Complete(TBool aOk, SThreadParams* aParams)=0;
-	};
-
-class CThreadI : public CBase
-	{
-public:
-	CThreadI();
-	~CThreadI();
-	static TInt ThreadFunc(TAny* aPtr);
-	TInt Run();
-	void InitL();
-public:
-	CTrapCleanup*		iCleanup;
-	CActiveScheduler*	iAS;
-	CLoadSim*			iL;
-	CBurstyCpuEater*	iB;
-	CTimedStopper*		iStopper;
-	RSemaphore			iTurnstile;
-	SThreadParams*		iParams;
-	};
-
-CThreadI::CThreadI()
-	{
-	}
-
-CThreadI::~CThreadI()
-	{
-	iTurnstile.Close();
-	delete iStopper;
-	delete iB;
-	delete iL;
-	delete iAS;
-	delete iCleanup;
-	}
-
-TInt CThreadI::ThreadFunc(TAny* aPtr)
-	{
-	CThreadI* p = new CThreadI;
-	if (!p)
-		return KErrNoMemory;
-	p->iParams = (SThreadParams*)aPtr;
-	return p->Run();
-	}
-
-void CThreadI::InitL()
-	{
-	iTurnstile = iParams->iTurnstile;
-	User::LeaveIfError(iTurnstile.Duplicate(RThread(), EOwnerThread));
-	iAS = new (ELeave) CActiveScheduler;
-	CActiveScheduler::Install(iAS);
-	iL = CLoadSim::NewL();
-	CActiveScheduler::Add(iL);
-	const CBurstyCpuEater::SParams* params = (const CBurstyCpuEater::SParams*)&iParams->iE;
-	iB = new (ELeave) CBurstyCpuEater(iL, *params);
-	CActiveScheduler::Add(iB);
-	iStopper = CTimedStopper::NewL();
-	CActiveScheduler::Add(iStopper);
-	memclr(iParams->iResult, sizeof(*iParams->iResult));
-	RThread().SetPriority(TThreadPriority(iParams->iPriority));
-	UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*)iParams->iCpuAffinity, 0);
-	}
-
-TInt CThreadI::Run()
-	{
-	iCleanup = CTrapCleanup::New();
-	if (!iCleanup)
-		return KErrNoMemory;
-	TRAPD(r,InitL());
-	if (r == KErrNone)
-		{
-		TThreadCpuUsageSample initial;
-		TThreadCpuUsageSample final;
-		RThread::Rendezvous(KErrNone);
-		iTurnstile.Wait();
-		iB->Start();
-		initial.Sample(RThread());
-		iStopper->Start(iParams->iTestTime);
-		CActiveScheduler::Start();
-		final.Sample(RThread());
-		iParams->iResult->iWorkDone = iB->WorkDone();
-		iParams->iResult->iInvocations = iB->Invocations();
-		iParams->iResult->iElapsedTime = final.ElapsedTimeDelta(initial);
-		iParams->iResult->iCpuTime = final.CpuTimeDelta(initial);
-		}
-	delete this;
-	return r;
-	}
-
-
-/******************************************************************************
- *
- ******************************************************************************/
-class CThreadX : public CActive
-	{
-public:
-	static CThreadX* NewL(SThreadParams* aParams, MThreadCompletion* aComplete);
-	static CThreadX* NewLC(SThreadParams* aParams, MThreadCompletion* aComplete);
-	CThreadX();
-	~CThreadX();
-	void ConstructL();
-	virtual void RunL();
-	virtual void DoCancel();
-public:
-	RThread				iThread;
-	RTimer				iTimer;
-	SThreadParams*		iParams;
-	MThreadCompletion*	iComplete;
-	};
-
-CThreadX::CThreadX()
-	:	CActive(EPriorityStandard)
-	{
-	}
-
-CThreadX::~CThreadX()
-	{
-	Cancel();
-	iTimer.Close();
-	iThread.Close();
-	}
-
-CThreadX* CThreadX::NewL(SThreadParams* aParams, MThreadCompletion* aComplete)
-	{
-	CThreadX* p = NewLC(aParams, aComplete);
-	CleanupStack::Pop();
-	return p;
-	}
-
-CThreadX* CThreadX::NewLC(SThreadParams* aParams, MThreadCompletion* aComplete)
-	{
-	CThreadX* p = new (ELeave) CThreadX();
-	p->iParams = aParams;
-	p->iComplete = aComplete;
-	CleanupStack::PushL(p);
-	p->ConstructL();
-	return p;
-	}
-
-const TInt KThreadHeapMin = 0x1000;
-const TInt KThreadHeapMax = 0x200000;
-void CThreadX::ConstructL()
-	{
-	CActiveScheduler::Add(this);
-	TRequestStatus s0, s1;
-	User::LeaveIfError(iTimer.CreateLocal());
-	User::LeaveIfError(iThread.Create(KNullDesC, &CThreadI::ThreadFunc, 0x1000, KThreadHeapMin, KThreadHeapMax, iParams));
-	iThread.Rendezvous(s1);
-	if (s1!=KRequestPending)
-		{
-		User::WaitForRequest(s1);
-		User::Leave(s1.Int());
-		}
-	iTimer.After(s0, 5*1000*1000);
-	iThread.Resume();
-	User::WaitForRequest(s0, s1);
-	if (s1==KRequestPending)
-		{
-		iThread.Terminate(KErrCouldNotStart);
-		User::WaitForRequest(s1);
-		User::Leave(KErrTimedOut);
-		}
-	iTimer.Cancel();
-	User::WaitForRequest(s0);
-	if (iThread.ExitType() != EExitPending)
-		{
-		User::Leave(KErrDied);
-		}
-	iThread.Logon(iStatus);
-	if (iStatus!=KRequestPending)
-		{
-		User::WaitForRequest(iStatus);
-		User::Leave(iStatus.Int());
-		}
-	SetActive();
-	User::LeaveIfError(s1.Int());
-	}
-
-void CThreadX::DoCancel()
-	{
-	iThread.Terminate(KErrCouldNotStart);
-	}
-
-void CThreadX::RunL()
-	{
-	TBool ok = ETrue;
-	if (iThread.ExitType() != EExitKill)
-		ok = EFalse;
-	if (iThread.ExitReason() != KErrNone)
-		ok = EFalse;
-	if (iComplete)
-		iComplete->Complete(ok, iParams);
-	}
-
-
-/******************************************************************************
- *
- ******************************************************************************/
-struct STestThreadDesc
-	{
-	TUint32		iCpuAffinity;
-	TInt		iPriority;
-	TInt		iGroupId;
-	TUint16		iEaterType;
-	TUint16		iEaterInstance;
-	TUint32		iGranularity;
-	TUint32		iMeanIntraBurstGap;
-	TUint32		iMeanBurstLength;
-	TUint32		iMeanInterBurstGap;
-
-	static STestThreadDesc* ContinuousL(TInt aPri = EPriorityNormal);
-	static STestThreadDesc* ContinuousLC(TInt aPri = EPriorityNormal);
-	static STestThreadDesc* StaccatoL(TUint32 aGranularity, TUint32 aMeanGap, TInt aPri = EPriorityNormal);
-	static STestThreadDesc* StaccatoLC(TUint32 aGranularity, TUint32 aMeanGap, TInt aPri = EPriorityNormal);
-	};
-
-STestThreadDesc* STestThreadDesc::ContinuousLC(TInt aPri)
-	{
-	STestThreadDesc* p = (STestThreadDesc*)User::AllocLC(sizeof(STestThreadDesc));
-	p->iCpuAffinity = 0xffffffff;
-	p->iPriority = aPri;
-	p->iGroupId = 0;
-	p->iEaterType = EEaterStd;
-	p->iEaterInstance = 0;
-	p->iGranularity = 0;
-	p->iMeanIntraBurstGap = 0;
-	p->iMeanBurstLength = KMaxTInt32;
-	p->iMeanInterBurstGap = 0;
-	return p;
-	}
-
-STestThreadDesc* STestThreadDesc::ContinuousL(TInt aPri)
-	{
-	STestThreadDesc* p = ContinuousLC(aPri);
-	CleanupStack::Pop();
-	return p;
-	}
-
-STestThreadDesc* STestThreadDesc::StaccatoLC(TUint32 aGranularity, TUint32 aMeanGap, TInt aPri)
-	{
-	STestThreadDesc* p = (STestThreadDesc*)User::AllocLC(sizeof(STestThreadDesc));
-	p->iCpuAffinity = 0xffffffff;
-	p->iPriority = aPri;
-	p->iGroupId = 0;
-	p->iEaterType = EEaterStd;
-	p->iEaterInstance = 0;
-	p->iGranularity = aGranularity;
-	p->iMeanIntraBurstGap = aMeanGap;
-	p->iMeanBurstLength = KMaxTInt32;
-	p->iMeanInterBurstGap = 0;
-	return p;
-	}
-
-STestThreadDesc* STestThreadDesc::StaccatoL(TUint32 aGranularity, TUint32 aMeanGap, TInt aPri)
-	{
-	STestThreadDesc* p = StaccatoLC(aGranularity, aMeanGap, aPri);
-	CleanupStack::Pop();
-	return p;
-	}
-
-
-class CTest : public CBase, public MThreadCompletion
-	{
-public:
-	struct SStats
-		{
-		TInt64	iTotalCpu;
-		TInt64	iMinCpu;
-		TInt64	iMaxCpu;
-		TInt64	iTotalWork;
-		TInt64	iMinWork;
-		TInt64	iMaxWork;
-		};
-public:
-	static CTest* NewL(TInt64 aTestTime, TInt aNumTypes, ...);
-	~CTest();
-	RPointerArray<SThreadParams>& Threads()
-		{ return iP; }
-	TInt Execute();
-	void PrintResults() const;
-	void GetStats(SStats& aStats, TInt aFirstThread=0, TInt aCount=KMaxTInt) const;
-	TInt64 TotalCpuAll() const;
-private:
-	CTest();
-	void ConstructL(TInt64 aTestTime, TInt aNumTypes, VA_LIST aList);
-	SThreadParams* AddThreadParamsL();
-	CThreadX* AddThreadXL(SThreadParams* aParams);
-
-	virtual void Complete(TBool aOk, SThreadParams* aParams);
-private:
-	RPointerArray<SThreadParams> iP;
-	RPointerArray<CThreadX> iTX;
-	REaterArray iEaters;
-	RSemaphore iTurnstile;
-	TInt iCompleteCount;
-	TCpuUsage iInitialCpuUsage;
-	TCpuUsage iFinalCpuUsage;
-	};
-
-CTest::CTest()
-	:	iP(32),
-		iTX(32)
-	{
-	}
-
-CTest::~CTest()
-	{
-	iTX.ResetAndDestroy();
-
-	TInt i;
-	TInt c = iP.Count();
-	for (i=0; i<c; ++i)
-		{
-		SThreadParams* p = iP[i];
-		iP[i] = 0;
-		if (p)
-			{
-			User::Free(p->iResult);
-			User::Free(p);
-			}
-		}
-	iP.Close();
-	iEaters.Close();
-	iTurnstile.Close();
-	}
-
-CTest* CTest::NewL(TInt64 aTestTime, TInt aNumTypes, ...)
-	{
-	VA_LIST list;
-	VA_START(list, aNumTypes);
-	CTest* p = new (ELeave) CTest;
-	CleanupStack::PushL(p);
-	p->ConstructL(aTestTime, aNumTypes, list);
-	CleanupStack::Pop();
-	return p;
-	}
-
-SThreadParams* CTest::AddThreadParamsL()
-	{
-	SThreadResult* tr = (SThreadResult*)User::AllocLC(sizeof(SThreadResult));
-	SThreadParams* tp = (SThreadParams*)User::AllocLC(sizeof(SThreadParams));
-	memclr(tr, sizeof(SThreadResult));
-	tp->iResult = tr;
-	iP.AppendL(tp);
-	CleanupStack::Pop(2);
-	tp->iTurnstile = iTurnstile;
-	return tp;
-	}
-
-CThreadX* CTest::AddThreadXL(SThreadParams* aP)
-	{
-	if (aP->iGranularity==0 && aP->iMeanInterBurstGap==0)
-		{
-		// continuous use thread
-		if (TInt64(aP->iMeanBurstLength) >= aP->iTestTime)
-			aP->iMeanBurstLength = I64LOW(aP->iTestTime) + (I64LOW(aP->iTestTime)>>1);
-		}
-	CThreadX* tx = CThreadX::NewLC(aP, this);
-	iTX.AppendL(tx);
-	CleanupStack::Pop();
-	return tx;
-	}
-
-void CTest::Complete(TBool aOk, SThreadParams*)
-	{
-	if (!aOk || --iCompleteCount==0)
-		CActiveScheduler::Stop();
-	}
-
-
-void CTest::ConstructL(TInt64 aTestTime, TInt aNumTypes, VA_LIST aList)
-	{
-	typedef const STestThreadDesc* TTestThreadDescPtrC;
-
-	User::LeaveIfError(iTurnstile.CreateLocal(0));
-	TInt tt;
-	TInt tid = 0;
-	for (tt=0; tt<aNumTypes; ++tt)
-		{
-		TInt nThreads = VA_ARG(aList, TInt);
-		TInt inc = 0;
-		const TTestThreadDescPtrC* ppttd = 0;
-		TTestThreadDescPtrC pttd = 0;
-		if (nThreads < 0)
-			{
-			ppttd = VA_ARG(aList, const TTestThreadDescPtrC*);
-			nThreads = -nThreads;
-			inc = 1;
-			}
-		else
-			{
-			pttd = VA_ARG(aList, TTestThreadDescPtrC);
-			ppttd = &pttd;
-			}
-		TInt k;
-		for (k=0; k<nThreads; ++k, ++tid)
-			{
-			const STestThreadDesc& ttd = **ppttd;
-			ppttd += inc;
-			SThreadParams* tp = AddThreadParamsL();
-			tp->iId = tid;
-			tp->iTestTime = aTestTime;
-			tp->iCpuAffinity = ttd.iCpuAffinity;
-			tp->iPriority = ttd.iPriority;
-			tp->iGroupId = ttd.iGroupId;
-			tp->iE = iEaters.FindOrCreateL(ttd.iEaterType, ttd.iEaterInstance);
-			tp->iGranularity = ttd.iGranularity;
-			tp->iMeanIntraBurstGap = ttd.iMeanIntraBurstGap;
-			tp->iMeanBurstLength = ttd.iMeanBurstLength;
-			tp->iMeanInterBurstGap = ttd.iMeanInterBurstGap;
-			AddThreadXL(tp);
-			}
-		}
-	}
-
-TInt CTest::Execute()
-	{
-	iCompleteCount = iP.Count();
-	iInitialCpuUsage.Sample();
-	iTurnstile.Signal(iCompleteCount);
-	CActiveScheduler::Start();
-	iFinalCpuUsage.Sample();
-	return iCompleteCount ? KErrGeneral : KErrNone;
-	}
-
-void CTest::GetStats(SStats& a, TInt aFirstThread, TInt aCount) const
-	{
-	a.iTotalCpu = 0;
-	a.iMinCpu = KMaxTInt64;
-	a.iMaxCpu = KMinTInt64;
-	a.iTotalWork = 0;
-	a.iMinWork = KMaxTInt64;
-	a.iMaxWork = KMinTInt64;
-	TInt nt = iP.Count();
-	if (aFirstThread > nt)
-		aFirstThread = nt;
-	if (aCount > nt - aFirstThread)
-		aCount = nt - aFirstThread;
-	TInt i = aFirstThread;
-	for (; i<aFirstThread+aCount; ++i)
-		{
-		SThreadResult* tr = iP[i]->iResult;
-		TInt64 cpu = tr->iCpuTime;
-		TInt64 work = tr->iWorkDone;
-		a.iTotalCpu += cpu;
-		a.iTotalWork += work;
-		if (cpu < a.iMinCpu)
-			a.iMinCpu = cpu;
-		if (cpu > a.iMaxCpu)
-			a.iMaxCpu = cpu;
-		if (work < a.iMinWork)
-			a.iMinWork = work;
-		if (work > a.iMaxWork)
-			a.iMaxWork = work;
-		}
-	}
-
-TInt64 CTest::TotalCpuAll() const
-	{
-	TInt i;
-	TInt nc = TCpuUsage::N();
-	TInt64 totalCpuAll = 0;
-	for (i=0; i<nc; ++i)
-		{
-		TInt64 u = iFinalCpuUsage.CpuTimeDelta(iInitialCpuUsage, i);
-		totalCpuAll += u;
-		}
-	return totalCpuAll;
-	}
-
-void CTest::PrintResults() const
-	{
-	TInt i;
-	TInt nt = iP.Count();
-	TInt nc = TCpuUsage::N();
-	TInt64 totalCpuAll = 0;
-	TInt64 totalCpu = 0;
-	TInt64 totalWork = 0;
-	for (i=0; i<nt; ++i)
-		{
-		SThreadResult* tr = iP[i]->iResult;
-		test.Printf(_L("%2u: E=%10u     C=%10u     I=%10u     W=%10u\n"),
-			i, I64LOW(tr->iElapsedTime), I64LOW(tr->iCpuTime), tr->iInvocations, tr->iWorkDone );
-		totalCpu += tr->iCpuTime;
-		totalWork += TInt64(tr->iWorkDone);
-		}
-	test.Printf(_L("Total              C=%12Lu                    W=%12Lu\n"), totalCpu, totalWork);
-	for (i=0; i<nc; ++i)
-		{
-		TInt64 u = iFinalCpuUsage.CpuTimeDelta(iInitialCpuUsage, i);
-		totalCpuAll += u;
-		test.Printf(_L("Cpu%1u: %10u "), i, I64LOW(u));
-		}
-	test.Printf(_L("\n"));
-	test.Printf(_L("Total %12Lu\n"), totalCpuAll);
-	}
-
-
-
-MCpuEater* REaterArray::CreateLC(TInt aType)
-	{
-	switch (aType)
-		{
-		case EEaterStd:
-			{
-			CDefaultCpuEater* p = new (ELeave) CDefaultCpuEater();
-			CleanupStack::PushL(p);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryLocalS:
-			{
-			CMemoryBandwidthEater* p = CMemoryBandwidthEater::NewLC(0x8000, 0x0800, 0x0800);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryNonLocalS:
-			{
-			CMemoryBandwidthEater* p = CMemoryBandwidthEater::NewLC(0x100000, 0x10000, 0x4);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryLocalU:
-			{
-			CMemoryBandwidthEater* p = CMemoryBandwidthEater::NewLC(0x4000, 0x4000, 0x4000);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryNonLocalU:
-			{
-			CMemoryBandwidthEater* p = CMemoryBandwidthEater::NewLC(0x80000, 0x80000, 0x80000);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryAtomic:
-			{
-			CAtomicMemoryBandwidthEater* p = CAtomicMemoryBandwidthEater::NewLC(0x1000);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterMemoryAtomic2:
-			{
-			CAtomicMemoryBandwidthEater* p = CAtomicMemoryBandwidthEater::NewLC(0x8000);
-			p->Calibrate();
-			return p;
-			}
-		case EEaterAmdahl:
-			{
-			CAmdahlCpuEater* p = CAmdahlCpuEater::NewLC();
-			p->Calibrate();
-			return p;
-			}
-		default:
-			User::Leave(KErrNotSupported);
-		}
-	return 0;
-	}
-
-
-
-/******************************************************************************
- *
- ******************************************************************************/
-
-void RunBenchmarkL(CTest::SStats& aB, STestThreadDesc* aT, TInt aLength)
-	{
-	const TInt NC = TCpuUsage::N();
-	CTest* p;
-	TUint32 saved_aff = aT->iCpuAffinity;
-	aT->iCpuAffinity = NC-1;
-	p = CTest::NewL(aLength, 1, 1, aT);
-	TInt r = p->Execute();
-	test_KErrNone(r);
-	p->PrintResults();
-	p->GetStats(aB);
-	delete p;
-	aT->iCpuAffinity = saved_aff;
-	}
-
-void CompareToBenchmark(const CTest::SStats& aS, const CTest::SStats& aB)
-	{
-	TReal bCpu = (TReal)aB.iTotalCpu;
-	TReal bWork = (TReal)aB.iTotalWork;
-	TReal bEff = bWork/bCpu*1000000.0;
-	TReal tCpu = (TReal)aS.iTotalCpu;
-	TReal tWork = (TReal)aS.iTotalWork;
-	TReal tEff = tWork/tCpu*1000000.0;
-	TReal mCpu = (TReal)aS.iMinCpu;
-	TReal MCpu = (TReal)aS.iMaxCpu;
-	TReal mWork = (TReal)aS.iMinWork;
-	TReal MWork = (TReal)aS.iMaxWork;
-	test.Printf(_L("Total CPU usage %6.1f%% of benchmark\n"), 100.0*tCpu/bCpu);
-	test.Printf(_L("Total work done %6.1f%% of benchmark\n"), 100.0*tWork/bWork);
-	test.Printf(_L("Max/min ratio   %6.1f%% (CPU) %6.1f%% (Work)\n"), 100.0*MCpu/mCpu, 100.0*MWork/mWork);
-	test.Printf(_L("Work/sec bench: %10.1f test: %10.1f  Relative Efficiency %6.1f%%\n"), bEff, tEff, tEff/bEff*100.0);
-	}
-
-void ContinuousTestL(TInt aLength, TUint32 aWhich)
-	{
-	aLength *= 1000;
-	const TInt NC = TCpuUsage::N();
-	TInt r = 0;
-	TInt i = 0;
-	CTest::SStats benchmark;
-	CTest::SStats st;
-	CTest::SStats stm;
-	CTest* p = 0;
-	TUint et = aWhich >> 28;
-	TBool separate = (aWhich & 0x08000000u);
-	TInt instance = 0;
-	STestThreadDesc* td[2*TCpuUsage::EMaxCpus] = {0};
-	STestThreadDesc* tdm[TCpuUsage::EMaxCpus] = {0};
-	STestThreadDesc* tdl[TCpuUsage::EMaxCpus] = {0};
-	for (i=0; i<2*NC; ++i)
-		{
-		td[i] = STestThreadDesc::ContinuousLC();
-		td[i]->iEaterType = (TUint16)et;
-		td[i]->iEaterInstance = (TUint16)(separate ? (instance++) : 0);
-		if (i<NC)
-			{
-			tdm[i] = STestThreadDesc::ContinuousLC(EPriorityMore);
-			tdm[i]->iEaterType = (TUint16)et;
-			tdm[i]->iEaterInstance = (TUint16)(separate ? (instance++) : 0);
-			tdl[i] = STestThreadDesc::ContinuousLC();
-			tdl[i]->iCpuAffinity = i;
-			tdl[i]->iEaterType = (TUint16)et;
-			tdl[i]->iEaterInstance = (TUint16)(separate ? (instance++) : 0);
-			}
-		}
-
-	test.Printf(_L("\nTesting a single continuous CPU-locked thread\n"));
-	RunBenchmarkL(benchmark, tdl[NC-1], aLength);
-
-	TInt n;
-
-	if (aWhich & 1)
-		{
-		for (n=1; n<=2*NC; ++n)
-			{
-			test.Printf(_L("\nTesting %d continuous thread(s) ...\n"), n);
-			p = CTest::NewL(aLength, 1, -n, td);
-			r = p->Execute();
-			test_KErrNone(r);
-			p->PrintResults();
-			p->GetStats(st);
-			delete p;
-			CompareToBenchmark(st, benchmark);
-			}
-		}
-
-	TInt h;
-	if (aWhich & 2)
-		{
-		for (h=1; h<NC; ++h)
-			{
-			for (n=h; n<=2*NC; ++n)
-				{
-				TInt l = n - h;
-				test.Printf(_L("\nTesting %d continuous thread(s) (%d higher priority) CPU-locked...\n"), n, h);
-				p = CTest::NewL(aLength, 2, -h, tdl, l, tdl[h]);
-				r = p->Execute();
-				test_KErrNone(r);
-				p->PrintResults();
-				p->GetStats(st, h, l);
-				p->GetStats(stm, 0, h);
-				delete p;
-				CompareToBenchmark(stm, benchmark);
-				if (l>0)
-					CompareToBenchmark(st, benchmark);
-				}
-			}
-		}
-
-	if (aWhich & 4)
-		{
-		for (h=1; h<NC; ++h)
-			{
-			for (n=h; n<=2*NC; ++n)
-				{
-				TInt l = n - h;
-				test.Printf(_L("\nTesting %d continuous thread(s) (%d higher priority)...\n"), n, h);
-				p = CTest::NewL(aLength, 2, -h, tdm, -l, td);
-				r = p->Execute();
-				test_KErrNone(r);
-				p->PrintResults();
-				p->GetStats(st, h, l);
-				p->GetStats(stm, 0, h);
-				delete p;
-				CompareToBenchmark(stm, benchmark);
-				if (l>0)
-					CompareToBenchmark(st, benchmark);
-				}
-			}
-		}
-
-	CleanupStack::PopAndDestroy(NC*4);
-	}
-
-
-void TestWithOneSpecialL(const TDesC& aTitle, TInt aLength, const CTest::SStats& aB1, const CTest::SStats& aB0, STestThreadDesc* aT1, STestThreadDesc* aT0)
-	{
-	const TInt NC = TCpuUsage::N();
-	CTest::SStats st;
-	CTest::SStats sti;
-	CTest* p = 0;
-	TInt n;
-	TInt r;
-	for (n=1; n<=2*NC-1; ++n)
-		{
-		test.Printf(_L("\nTesting %d continuous thread(s) plus %S ...\n"), n, &aTitle);
-		p = CTest::NewL(aLength, 2, 1, aT1, n, aT0);
-		r = p->Execute();
-		test_KErrNone(r);
-		p->PrintResults();
-		p->GetStats(st, 1, n);
-		p->GetStats(sti, 0, 1);
-		delete p;
-		CompareToBenchmark(sti, aB1);
-		CompareToBenchmark(st, aB0);
-
-		test.Printf(_L("\nTesting %d continuous thread(s) plus %Sh ...\n"), n, &aTitle);
-		TInt orig_pri = aT1->iPriority;
-		aT1->iPriority = EPriorityMore;
-		p = CTest::NewL(aLength, 2, 1, aT1, n, aT0);
-		r = p->Execute();
-		test_KErrNone(r);
-		p->PrintResults();
-		p->GetStats(st, 1, n);
-		p->GetStats(sti, 0, 1);
-		delete p;
-		CompareToBenchmark(sti, aB1);
-		CompareToBenchmark(st, aB0);
-		aT1->iPriority = orig_pri;
-		}
-	}
-
-void ContinuousPlusIntermittentTestL(TInt aLength, TUint32 aWhich)
-	{
-	aLength *= 1000;
-	const TInt NC = TCpuUsage::N();
-	TInt i = 0;
-	CTest::SStats bmc, bmilc, bmilf, bmihc, bmihf;
-	STestThreadDesc* td = STestThreadDesc::ContinuousLC();
-	STestThreadDesc* tdl[TCpuUsage::EMaxCpus] = {0};
-	STestThreadDesc* tdilc[TCpuUsage::EMaxCpus] = {0};	// light load, coarse grained
-	STestThreadDesc* tdilf[TCpuUsage::EMaxCpus] = {0};	// light load, fine grained
-	STestThreadDesc* tdihc[TCpuUsage::EMaxCpus] = {0};	// heavy load, coarse grained
-	STestThreadDesc* tdihf[TCpuUsage::EMaxCpus] = {0};	// heavy load, fine grained
-	for (i=0; i<NC; ++i)
-		{
-		tdl[i] = STestThreadDesc::ContinuousLC();
-		tdl[i]->iCpuAffinity = i;
-		tdilc[i] = STestThreadDesc::StaccatoLC(45000, 500000);
-		tdilf[i] = STestThreadDesc::StaccatoLC(1000, 50000);
-		tdihc[i] = STestThreadDesc::StaccatoLC(400000, 500000);
-		tdihf[i] = STestThreadDesc::StaccatoLC(3000, 5000);
-		}
-
-	test.Printf(_L("\nTesting a single continuous CPU-locked thread\n"));
-	RunBenchmarkL(bmc, tdl[NC-1], aLength);
-
-	if (aWhich & 1)
-		{
-		test.Printf(_L("\nTesting a single ILC CPU-locked thread\n"));
-		RunBenchmarkL(bmilc, tdilc[NC-1], aLength);
-		}
-
-	if (aWhich & 2)
-		{
-		test.Printf(_L("\nTesting a single ILF CPU-locked thread\n"));
-		RunBenchmarkL(bmilf, tdilf[NC-1], aLength);
-		}
-
-	if (aWhich & 4)
-		{
-		test.Printf(_L("\nTesting a single IHC CPU-locked thread\n"));
-		RunBenchmarkL(bmihc, tdihc[NC-1], aLength);
-		}
-
-	if (aWhich & 8)
-		{
-		test.Printf(_L("\nTesting a single IHF CPU-locked thread\n"));
-		RunBenchmarkL(bmihf, tdihf[NC-1], aLength);
-		}
-
-	if (aWhich & 1)
-		{
-		TestWithOneSpecialL(_L("ILC"), aLength, bmilc, bmc, tdilc[0], td);
-		}
-	if (aWhich & 2)
-		{
-		TestWithOneSpecialL(_L("ILF"), aLength, bmilf, bmc, tdilf[0], td);
-		}
-	if (aWhich & 4)
-		{
-		TestWithOneSpecialL(_L("IHC"), aLength, bmihc, bmc, tdihc[0], td);
-		}
-	if (aWhich & 8)
-		{
-		TestWithOneSpecialL(_L("IHF"), aLength, bmihf, bmc, tdihf[0], td);
-		}
-	CleanupStack::PopAndDestroy(5*NC+1);
-	}
-
-
-TInt E32Main()
-	{
-	RThread().SetPriority(EPriorityAbsoluteHigh);
-	test.Title();
-	User::SetCritical(User::ESystemCritical);
-	TCpuUsage::Init();
-	TInt r = 0;
-
-	CTrapCleanup* cln = CTrapCleanup::New();
-	test_NotNull(cln);
-	CActiveScheduler* as = new CActiveScheduler;
-	test_NotNull(as);
-	CActiveScheduler::Install(as);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with CPU intensive loads...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4));
-	test_KErrNone(r);
-	TRAP(r, ContinuousPlusIntermittentTestL(10000, 15));
-	test_KErrNone(r);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with memory intensive loads, good locality...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4+0x08000000u+(EEaterMemoryLocalU<<28)));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4+0x08000000u+(EEaterMemoryLocalU<<28)));
-	test_KErrNone(r);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with memory intensive loads, poor locality...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4+0x08000000u+(EEaterMemoryNonLocalU<<28)));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4+0x08000000u+(EEaterMemoryNonLocalU<<28)));
-	test_KErrNone(r);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with memory intensive loads, atomic operations...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4+(EEaterMemoryAtomic<<28)));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4+(EEaterMemoryAtomic<<28)));
-	test_KErrNone(r);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with memory intensive loads, atomic operations 2...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4+(EEaterMemoryAtomic2<<28)));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4+(EEaterMemoryAtomic2<<28)));
-	test_KErrNone(r);
-
-	test.Printf(_L("\n************************************************************************\n"));
-	test.Printf(_L("* Testing with CPU intensive loads with some serialization...\n"));
-	test.Printf(_L("************************************************************************\n"));
-	TRAP(r, ContinuousTestL(3000, 1+4+(EEaterAmdahl<<28)));
-	test_KErrNone(r);
-	TRAP(r, ContinuousTestL(10000, 1+4+(EEaterAmdahl<<28)));
-	test_KErrNone(r);
-
-	delete as;
-	delete cln;
-	return r;
-	}
-