--- /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;
+ }