kerneltest/e32test/benchmark/rt_latency.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/benchmark/rt_latency.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,154 @@
+// Copyright (c) 2002-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:
+//
+
+#include <e32test.h>
+
+#include "bm_suite.h"
+
+class RTLatency : public BMProgram
+	{
+
+	struct Measurement
+		{
+		RBMChannel::TMode	iMode;
+		TPtrC				iName;
+		TBool				iForcePSwitch;
+
+		Measurement(RBMChannel::TMode aMode, const TDesC& aName, TBool aForcePSwitch = EFalse) : 
+			iMode(aMode), iName(aName), iForcePSwitch(aForcePSwitch) {}
+		};
+
+public :
+	RTLatency() : BMProgram(_L("Real-Time Latency"))
+		{}
+	virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount);
+
+	static TBMResult	iResults[];
+	static Measurement	iMeasurements[];
+
+	void Perform(RBMChannel::TMode, TBMResult*, TBMUInt64 aIter, TBool aForcePSwitch);
+	static TInt Child(TAny*);
+	};
+
+RTLatency::Measurement		RTLatency::iMeasurements[] =
+	{ 
+		Measurement(RBMChannel::EInterruptLatency, _L("Interrupt Latency")),
+		Measurement(RBMChannel::EKernelPreemptionLatency, _L("Kernel Thread Preemption Latency (Idle)")),
+		Measurement(RBMChannel::EKernelPreemptionLatency, _L("Kernel Thread Preemption Latency(Busy)"), ETrue),
+		Measurement(RBMChannel::EUserPreemptionLatency, _L("User Thread Preemption Latency (Idle)")),
+		Measurement(RBMChannel::EUserPreemptionLatency, _L("User Thread Preemption Latency (Busy)"), ETrue),
+		Measurement(RBMChannel::ENTimerJitter, _L("NTimer Jitter")),
+		Measurement(RBMChannel::ETimerStampOverhead, _L("Getting Time Stamp Overhead"))
+	};
+TBMResult	RTLatency::iResults[sizeof(RTLatency::iMeasurements)/sizeof(RTLatency::iMeasurements[0])];
+
+static RTLatency rtLatency;
+
+struct ChildArgs : public TBMSpawnArgs
+	{
+	RSemaphore iSem;
+	ChildArgs () : TBMSpawnArgs(RTLatency::Child, KBMPriorityLow, ETrue, sizeof(*this))
+		{
+		TInt r = KErrNone;
+		do
+			{		//"Bm_SuiteSemaphore" is created/deleted a number of times during the test.
+			if (r)	//If kernel did not clean up the previous instance, wait a sec and retry.
+				User::After(1000000);
+			r = iSem.CreateGlobal(_L("Bm_SuiteSemaphore"), 0);
+			}
+		while(KErrAlreadyExists == r);
+
+		BM_ERROR(r, r == KErrNone);
+		}
+	void ChildOpen()
+		{	
+		iSem.Duplicate(iParent);
+		}
+	~ChildArgs ()
+		{
+		iSem.Close();
+		}
+	};
+
+//
+// Child process entry point.
+//
+TInt RTLatency::Child(TAny* ptr)
+	{
+	ChildArgs* ca = (ChildArgs*) ptr;
+		// get handles to all objects shared with the parent
+	ca->ChildOpen();
+		// signal the parent that the child is ready
+	ca->iSem.Signal();
+		// loop forever
+	for(;;) {}
+	}
+
+void RTLatency::Perform(RBMChannel::TMode aMode, TBMResult* aResult, TBMUInt64 aIter, TBool aForcePSwitch)
+	{
+	ChildArgs ca;
+	MBMChild* child = NULL;
+	if (aForcePSwitch)
+		{
+			// spawn a busy running low-pririty child process
+		child = rtLatency.SpawnChild(&ca);
+		ca.iSem.Wait();
+		}
+
+	RBMChannel ch;
+	TInt r = ch.Open(aMode);
+	if(r==KErrInUse)
+		return; // Assume that resources are being used for other forms of latency testing
+	BM_ERROR(r, r == KErrNone);
+	while(aIter--) 
+		{
+			// request an interrupt
+		ch.RequestInterrupt();
+		TBMTicks ticks;
+			// wait for the result. At this point the child becomes running.
+		ch.Result(&ticks);
+		aResult->Cumulate(ticks);
+		}
+	ch.Close();
+
+	if (aForcePSwitch)
+		{
+		child->Kill();
+		child->WaitChildExit();
+		}
+	}
+
+					
+TBMResult* RTLatency::Run(TBMUInt64 aIter, TInt* aCount)
+	{
+	TInt count = sizeof(iResults)/sizeof(iResults[0]);
+
+	for (TInt i = 0; i < count; ++i)
+		{
+		iResults[i].Reset(iMeasurements[i].iName);
+		Perform(iMeasurements[i].iMode, &iResults[i], aIter, iMeasurements[i].iForcePSwitch);
+		iResults[i].Update();
+		}
+	
+	*aCount = count;
+	return iResults;
+	}
+
+void AddrtLatency()
+	{
+	BMProgram* next = bmSuite;
+	bmSuite=(BMProgram*)&rtLatency;
+	bmSuite->Next()=next;
+	}