kerneltest/e32test/benchmark/sync.cpp
changeset 0 a41df078684a
child 39 2bb754abd467
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/benchmark/sync.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,423 @@
+// 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 <e32msgqueue.h>
+
+#include "bm_suite.h"
+
+class Sync : public BMProgram
+	{
+public :
+	Sync() : BMProgram(_L("Synchronization Primitives"))
+		{}
+	virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount);
+
+	typedef void (*MeasurementFunc)(TBMResult*, TBMUInt64 aIter, TBool aRemote);
+	struct Measurement 
+		{
+		MeasurementFunc iFunc;
+		TPtrC			iName;
+		TBool			iRemote;
+
+		Measurement(MeasurementFunc aFunc, const TDesC& aName, TBool aRemote = EFalse) : 
+					iFunc(aFunc), iName(aName), iRemote(aRemote) {}
+		};
+
+	static TBMResult iResults[];
+	static Measurement iMeasurements[];
+
+	static void MutexPassing(TBMResult*, TBMUInt64 aIter, TBool aRemote);
+	static void MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
+	static TInt MutexContentionChild(TAny*);
+	static void SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
+	static TInt SemaphoreLatencyChild(TAny*);
+	static void ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
+	static TInt ThreadSemaphoreLatencyChild(TAny*);
+	};
+
+Sync::Measurement Sync::iMeasurements[] =
+	{
+	Measurement(&Sync::MutexPassing, _L("Mutex Passing Case")),
+	Measurement(&Sync::MutexContentionParent, _L("Local Mutex Contention")),
+	Measurement(&Sync::MutexContentionParent, _L("Remote Mutex Contention"), ETrue),
+	Measurement(&Sync::SemaphoreLatencyParent, _L("Local Semaphore Latency")),
+	Measurement(&Sync::SemaphoreLatencyParent, _L("Remote Semaphore Latency"), ETrue),
+	Measurement(&Sync::ThreadSemaphoreLatencyParent, _L("Local Thread Semaphore Latency")),
+	};
+TBMResult Sync::iResults[sizeof(Sync::iMeasurements)/sizeof(Sync::iMeasurements[0])];
+
+static Sync sync;
+
+void Sync::MutexPassing(TBMResult* aResult, TBMUInt64 aIter, TBool)
+	{
+	RMutex mutex;
+	mutex.CreateLocal();
+
+	TBMTimeInterval ti;
+	ti.Begin();
+	for (TBMUInt64 i = 0; i < aIter; ++i)
+		{
+		mutex.Wait();
+		mutex.Signal();
+		}
+	TBMTicks t = ti.End();
+
+	mutex.Close();
+
+	aResult->Cumulate(t, aIter);
+	}
+
+class MutexContentionArgs : public TBMSpawnArgs
+	{
+public:
+	
+	RMutex		iMutexA;
+	RMutex		iMutexB;
+	RSemaphore	iSem;
+	TBMUInt64	iIterationCount;
+
+	MutexContentionArgs(TInt aRemote, TBMUInt64 aIter);
+
+	void ChildOpen();
+	void ChildClose();
+
+	void Close();
+	};
+
+MutexContentionArgs::MutexContentionArgs(TInt aRemote, TBMUInt64 aIter) :
+		TBMSpawnArgs(Sync::MutexContentionChild, KBMPriorityLow, aRemote, sizeof(*this)),
+		iIterationCount(aIter)
+	{
+	TInt r;
+	if (aRemote)
+		{
+		r = iMutexA.CreateGlobal(_L("MutexA"));
+		BM_ERROR(r, r == KErrNone);
+		r = iMutexB.CreateGlobal(_L("MutexB"));
+		BM_ERROR(r, r == KErrNone);
+		r = iSem.CreateGlobal(_L("Semaphore"), 0);
+		BM_ERROR(r, r == KErrNone);
+		}
+	else
+		{
+		r = iMutexA.CreateLocal();
+		BM_ERROR(r, r == KErrNone);
+		r = iMutexB.CreateLocal();
+		BM_ERROR(r, r == KErrNone);
+		r = iSem.CreateLocal(0);
+		BM_ERROR(r, r == KErrNone);
+		}
+	}
+
+void MutexContentionArgs::ChildOpen()
+	{
+	if (iRemote)
+		{
+		iMutexA.Duplicate(iParent);
+		iMutexB.Duplicate(iParent);
+		iSem.Duplicate(iParent);
+		}
+	}
+
+void MutexContentionArgs::ChildClose()
+	{
+	if (iRemote)
+		{
+		iMutexA.Close();
+		iMutexB.Close();
+		iSem.Close();
+		}
+	}
+
+void MutexContentionArgs::Close()
+	{
+	iMutexA.Close();
+	iMutexB.Close();
+	iSem.Close();
+	}
+
+void Sync::MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
+	{
+	MutexContentionArgs mc(aRemote, aIter);
+
+	MBMChild* child = sync.SpawnChild(&mc);
+
+	mc.iSem.Wait();
+
+	TBMTimeInterval ti;
+	ti.Begin();
+	for (TBMUInt64 i = 0; i < aIter; ++i)
+		{
+		mc.iMutexA.Wait();
+		mc.iMutexA.Signal();
+		mc.iMutexB.Wait();
+		mc.iMutexB.Signal();
+		}	
+	TBMTicks t = ti.End();
+
+	child->WaitChildExit();
+	mc.Close();
+
+	aResult->Cumulate(t/2, aIter);
+	}
+
+TInt Sync::MutexContentionChild(TAny* ptr)
+	{
+	MutexContentionArgs* mc = (MutexContentionArgs*) ptr;
+	mc->ChildOpen();
+
+	mc->iMutexA.Wait();
+	mc->iSem.Signal();
+	for (TBMUInt64 i = 0; i < mc->iIterationCount; ++i)
+		{
+		mc->iMutexB.Wait();
+		mc->iMutexA.Signal();
+		mc->iMutexA.Wait();
+		mc->iMutexB.Signal();
+		}
+	mc->iMutexA.Signal();
+
+	mc->ChildClose();
+	return KErrNone;
+	}
+
+class SemaphoreLatencyArgs : public TBMSpawnArgs
+	{
+public:
+	
+	RSemaphore			iSem;
+	TBMUInt64			iIterationCount;
+	RMsgQueue<TBMTicks>	iSignalTimeQue;
+
+	SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter);
+
+	void ChildOpen();
+	void ChildClose();
+
+	TBMTicks SignalTime();
+	void ChildSignalTime(TBMTicks);
+
+	void Close();
+	};
+
+SemaphoreLatencyArgs::SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : 
+	TBMSpawnArgs(Sync::SemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)),
+	iIterationCount(aIter)
+	{
+	TInt r;
+	if (aRemote)
+		{
+		r = iSem.CreateGlobal(_L("BM Semaphore"), 0);
+		BM_ERROR(r, r == KErrNone);
+		}
+	else
+		{
+		r = iSem.CreateLocal(0);
+		BM_ERROR(r, r == KErrNone);
+		}
+	r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1);
+	BM_ERROR(r, r == KErrNone);
+	}	
+
+void SemaphoreLatencyArgs::ChildOpen()
+	{
+	if (iRemote)
+		{
+		iSem.Duplicate(iParent);
+		TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue"));
+		BM_ERROR(r, r == KErrNone);
+		}
+	}
+
+void SemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime)
+	{
+	TInt r = iSignalTimeQue.Send(aTime);
+	BM_ERROR(r, r == KErrNone);
+	}
+
+TBMTicks SemaphoreLatencyArgs::SignalTime()
+	{
+	TBMTicks time;
+	iSignalTimeQue.ReceiveBlocking(time);
+	return time;
+	}
+
+void SemaphoreLatencyArgs::ChildClose()
+	{
+	if (iRemote)
+		{
+		iSem.Close();
+		iSignalTimeQue.Close();
+		}
+	}
+
+void SemaphoreLatencyArgs::Close()
+	{
+	iSem.Close();
+	iSignalTimeQue.Close();
+	}
+
+void Sync::SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
+	{
+	SemaphoreLatencyArgs sl(aRemote, aIter);
+	MBMChild* child = sync.SpawnChild(&sl);
+	for (TBMUInt64 i = 0; i < aIter; ++i)
+		{
+		sl.iSem.Wait();
+		TBMTicks now;
+		::bmTimer.Stamp(&now);
+		aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now));
+		}
+	child->WaitChildExit();
+	sl.Close();
+	}
+
+TInt Sync::SemaphoreLatencyChild(TAny* ptr)
+	{
+	SemaphoreLatencyArgs* sl = (SemaphoreLatencyArgs*) ptr;
+	sl->ChildOpen();
+	for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i)
+		{
+		TBMTicks sigTime;
+		::bmTimer.Stamp(&sigTime);		
+		sl->iSem.Signal();
+		sl->ChildSignalTime(sigTime);
+		}
+	sl->ChildClose();
+	return KErrNone;
+	}
+
+class ThreadSemaphoreLatencyArgs : public TBMSpawnArgs
+	{
+public:
+	
+	TBMUInt64			iIterationCount;
+	TBMTicks			iSignalTime;
+	TRequestStatus		iStatus;
+	TRequestStatus*		iStatusPtr;
+	RMsgQueue<TBMTicks>	iSignalTimeQue;
+
+	ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter);
+
+	void ChildOpen();
+	void ChildClose();
+
+	TBMTicks SignalTime();
+	void ChildSignalTime(TBMTicks);
+
+	void Close();
+	};
+
+ThreadSemaphoreLatencyArgs::ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : 
+	TBMSpawnArgs(Sync::ThreadSemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)),
+	iIterationCount(aIter),
+	iStatusPtr(&iStatus)
+
+	{
+	TInt r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1);
+	BM_ERROR(r, r == KErrNone);
+	}
+
+void ThreadSemaphoreLatencyArgs::ChildOpen()
+	{
+	if (iRemote)
+		{
+		TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue"));
+		BM_ERROR(r, r == KErrNone);
+		}
+	}
+
+void ThreadSemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime)
+	{
+	TInt r = iSignalTimeQue.Send(aTime);
+	BM_ERROR(r, r == KErrNone);
+	}
+
+TBMTicks ThreadSemaphoreLatencyArgs::SignalTime()
+	{
+	TBMTicks time;
+	iSignalTimeQue.ReceiveBlocking(time);
+	return time;
+	}
+
+void ThreadSemaphoreLatencyArgs::ChildClose()
+	{
+	if (iRemote)
+		{
+		iSignalTimeQue.Close();
+		}
+	}
+
+void ThreadSemaphoreLatencyArgs::Close()
+	{
+	iSignalTimeQue.Close();
+	}
+
+void Sync::ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
+	{
+	ThreadSemaphoreLatencyArgs sl(aRemote, aIter);
+	MBMChild* child = sync.SpawnChild(&sl);
+	for (TBMUInt64 i = 0; i < aIter; ++i)
+		{
+		sl.iStatus = KRequestPending;
+		User::WaitForRequest(sl.iStatus);
+		BM_ASSERT(sl.iStatus == KErrNone);
+		TBMTicks now;
+		::bmTimer.Stamp(&now);
+		aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now));
+		}
+	child->WaitChildExit();
+	sl.Close();
+	}
+
+TInt Sync::ThreadSemaphoreLatencyChild(TAny* ptr)
+	{
+	ThreadSemaphoreLatencyArgs* sl = (ThreadSemaphoreLatencyArgs*) ptr;
+	sl->ChildOpen();
+	for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i)
+		{
+		TRequestStatus* sptr = sl->iStatusPtr;
+		TBMTicks sigTime;
+		::bmTimer.Stamp(&sigTime);		
+		sl->iParent.RequestComplete(sptr, KErrNone);
+		sl->ChildSignalTime(sigTime);
+		}
+	sl->ChildClose();
+	return KErrNone;
+	}
+
+						
+TBMResult* Sync::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);
+		iMeasurements[i].iFunc(&iResults[i], aIter, iMeasurements[i].iRemote);
+		iResults[i].Update();
+		}
+	
+	*aCount = count;
+	return iResults;
+	}
+
+void AddSync()
+	{
+	BMProgram* next = bmSuite;
+	bmSuite=(BMProgram*)&sync;
+	bmSuite->Next()=next;
+	}