diff -r 000000000000 -r a41df078684a kerneltest/e32test/benchmark/sync.cpp --- /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 +#include + +#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 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 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; + }