sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "bm_suite.h" sl@0: sl@0: class Sync : public BMProgram sl@0: { sl@0: public : sl@0: Sync() : BMProgram(_L("Synchronization Primitives")) sl@0: {} sl@0: virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount); sl@0: sl@0: typedef void (*MeasurementFunc)(TBMResult*, TBMUInt64 aIter, TBool aRemote); sl@0: struct Measurement sl@0: { sl@0: MeasurementFunc iFunc; sl@0: TPtrC iName; sl@0: TBool iRemote; sl@0: sl@0: Measurement(MeasurementFunc aFunc, const TDesC& aName, TBool aRemote = EFalse) : sl@0: iFunc(aFunc), iName(aName), iRemote(aRemote) {} sl@0: }; sl@0: sl@0: static TBMResult iResults[]; sl@0: static Measurement iMeasurements[]; sl@0: sl@0: static void MutexPassing(TBMResult*, TBMUInt64 aIter, TBool aRemote); sl@0: static void MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote); sl@0: static TInt MutexContentionChild(TAny*); sl@0: static void SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote); sl@0: static TInt SemaphoreLatencyChild(TAny*); sl@0: static void ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote); sl@0: static TInt ThreadSemaphoreLatencyChild(TAny*); sl@0: }; sl@0: sl@0: Sync::Measurement Sync::iMeasurements[] = sl@0: { sl@0: Measurement(&Sync::MutexPassing, _L("Mutex Passing Case")), sl@0: Measurement(&Sync::MutexContentionParent, _L("Local Mutex Contention")), sl@0: Measurement(&Sync::MutexContentionParent, _L("Remote Mutex Contention"), ETrue), sl@0: Measurement(&Sync::SemaphoreLatencyParent, _L("Local Semaphore Latency")), sl@0: Measurement(&Sync::SemaphoreLatencyParent, _L("Remote Semaphore Latency"), ETrue), sl@0: Measurement(&Sync::ThreadSemaphoreLatencyParent, _L("Local Thread Semaphore Latency")), sl@0: }; sl@0: TBMResult Sync::iResults[sizeof(Sync::iMeasurements)/sizeof(Sync::iMeasurements[0])]; sl@0: sl@0: static Sync sync; sl@0: sl@0: void Sync::MutexPassing(TBMResult* aResult, TBMUInt64 aIter, TBool) sl@0: { sl@0: RMutex mutex; sl@0: mutex.CreateLocal(); sl@0: sl@0: TBMTimeInterval ti; sl@0: ti.Begin(); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: mutex.Wait(); sl@0: mutex.Signal(); sl@0: } sl@0: TBMTicks t = ti.End(); sl@0: sl@0: mutex.Close(); sl@0: sl@0: aResult->Cumulate(t, aIter); sl@0: } sl@0: sl@0: class MutexContentionArgs : public TBMSpawnArgs sl@0: { sl@0: public: sl@0: sl@0: RMutex iMutexA; sl@0: RMutex iMutexB; sl@0: RSemaphore iSem; sl@0: TBMUInt64 iIterationCount; sl@0: sl@0: MutexContentionArgs(TInt aRemote, TBMUInt64 aIter); sl@0: sl@0: void ChildOpen(); sl@0: void ChildClose(); sl@0: sl@0: void Close(); sl@0: }; sl@0: sl@0: MutexContentionArgs::MutexContentionArgs(TInt aRemote, TBMUInt64 aIter) : sl@0: TBMSpawnArgs(Sync::MutexContentionChild, KBMPriorityLow, aRemote, sizeof(*this)), sl@0: iIterationCount(aIter) sl@0: { sl@0: TInt r; sl@0: if (aRemote) sl@0: { sl@0: r = iMutexA.CreateGlobal(_L("MutexA")); sl@0: BM_ERROR(r, r == KErrNone); sl@0: r = iMutexB.CreateGlobal(_L("MutexB")); sl@0: BM_ERROR(r, r == KErrNone); sl@0: r = iSem.CreateGlobal(_L("Semaphore"), 0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: else sl@0: { sl@0: r = iMutexA.CreateLocal(); sl@0: BM_ERROR(r, r == KErrNone); sl@0: r = iMutexB.CreateLocal(); sl@0: BM_ERROR(r, r == KErrNone); sl@0: r = iSem.CreateLocal(0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: } sl@0: sl@0: void MutexContentionArgs::ChildOpen() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: iMutexA.Duplicate(iParent); sl@0: iMutexB.Duplicate(iParent); sl@0: iSem.Duplicate(iParent); sl@0: } sl@0: } sl@0: sl@0: void MutexContentionArgs::ChildClose() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: iMutexA.Close(); sl@0: iMutexB.Close(); sl@0: iSem.Close(); sl@0: } sl@0: } sl@0: sl@0: void MutexContentionArgs::Close() sl@0: { sl@0: iMutexA.Close(); sl@0: iMutexB.Close(); sl@0: iSem.Close(); sl@0: } sl@0: sl@0: void Sync::MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote) sl@0: { sl@0: MutexContentionArgs mc(aRemote, aIter); sl@0: sl@0: MBMChild* child = sync.SpawnChild(&mc); sl@0: sl@0: mc.iSem.Wait(); sl@0: sl@0: TBMTimeInterval ti; sl@0: ti.Begin(); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: mc.iMutexA.Wait(); sl@0: mc.iMutexA.Signal(); sl@0: mc.iMutexB.Wait(); sl@0: mc.iMutexB.Signal(); sl@0: } sl@0: TBMTicks t = ti.End(); sl@0: sl@0: child->WaitChildExit(); sl@0: mc.Close(); sl@0: sl@0: aResult->Cumulate(t/2, aIter); sl@0: } sl@0: sl@0: TInt Sync::MutexContentionChild(TAny* ptr) sl@0: { sl@0: MutexContentionArgs* mc = (MutexContentionArgs*) ptr; sl@0: mc->ChildOpen(); sl@0: sl@0: mc->iMutexA.Wait(); sl@0: mc->iSem.Signal(); sl@0: for (TBMUInt64 i = 0; i < mc->iIterationCount; ++i) sl@0: { sl@0: mc->iMutexB.Wait(); sl@0: mc->iMutexA.Signal(); sl@0: mc->iMutexA.Wait(); sl@0: mc->iMutexB.Signal(); sl@0: } sl@0: mc->iMutexA.Signal(); sl@0: sl@0: mc->ChildClose(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: class SemaphoreLatencyArgs : public TBMSpawnArgs sl@0: { sl@0: public: sl@0: sl@0: RSemaphore iSem; sl@0: TBMUInt64 iIterationCount; sl@0: RMsgQueue iSignalTimeQue; sl@0: sl@0: SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter); sl@0: sl@0: void ChildOpen(); sl@0: void ChildClose(); sl@0: sl@0: TBMTicks SignalTime(); sl@0: void ChildSignalTime(TBMTicks); sl@0: sl@0: void Close(); sl@0: }; sl@0: sl@0: SemaphoreLatencyArgs::SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : sl@0: TBMSpawnArgs(Sync::SemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)), sl@0: iIterationCount(aIter) sl@0: { sl@0: TInt r; sl@0: if (aRemote) sl@0: { sl@0: r = iSem.CreateGlobal(_L("BM Semaphore"), 0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: else sl@0: { sl@0: r = iSem.CreateLocal(0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: sl@0: void SemaphoreLatencyArgs::ChildOpen() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: iSem.Duplicate(iParent); sl@0: TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue")); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: } sl@0: sl@0: void SemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime) sl@0: { sl@0: TInt r = iSignalTimeQue.Send(aTime); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: sl@0: TBMTicks SemaphoreLatencyArgs::SignalTime() sl@0: { sl@0: TBMTicks time; sl@0: iSignalTimeQue.ReceiveBlocking(time); sl@0: return time; sl@0: } sl@0: sl@0: void SemaphoreLatencyArgs::ChildClose() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: iSem.Close(); sl@0: iSignalTimeQue.Close(); sl@0: } sl@0: } sl@0: sl@0: void SemaphoreLatencyArgs::Close() sl@0: { sl@0: iSem.Close(); sl@0: iSignalTimeQue.Close(); sl@0: } sl@0: sl@0: void Sync::SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote) sl@0: { sl@0: SemaphoreLatencyArgs sl(aRemote, aIter); sl@0: MBMChild* child = sync.SpawnChild(&sl); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: sl.iSem.Wait(); sl@0: TBMTicks now; sl@0: ::bmTimer.Stamp(&now); sl@0: aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now)); sl@0: } sl@0: child->WaitChildExit(); sl@0: sl.Close(); sl@0: } sl@0: sl@0: TInt Sync::SemaphoreLatencyChild(TAny* ptr) sl@0: { sl@0: SemaphoreLatencyArgs* sl = (SemaphoreLatencyArgs*) ptr; sl@0: sl->ChildOpen(); sl@0: for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i) sl@0: { sl@0: TBMTicks sigTime; sl@0: ::bmTimer.Stamp(&sigTime); sl@0: sl->iSem.Signal(); sl@0: sl->ChildSignalTime(sigTime); sl@0: } sl@0: sl->ChildClose(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: class ThreadSemaphoreLatencyArgs : public TBMSpawnArgs sl@0: { sl@0: public: sl@0: sl@0: TBMUInt64 iIterationCount; sl@0: TBMTicks iSignalTime; sl@0: TRequestStatus iStatus; sl@0: TRequestStatus* iStatusPtr; sl@0: RMsgQueue iSignalTimeQue; sl@0: sl@0: ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter); sl@0: sl@0: void ChildOpen(); sl@0: void ChildClose(); sl@0: sl@0: TBMTicks SignalTime(); sl@0: void ChildSignalTime(TBMTicks); sl@0: sl@0: void Close(); sl@0: }; sl@0: sl@0: ThreadSemaphoreLatencyArgs::ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : sl@0: TBMSpawnArgs(Sync::ThreadSemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)), sl@0: iIterationCount(aIter), sl@0: iStatusPtr(&iStatus) sl@0: sl@0: { sl@0: TInt r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: sl@0: void ThreadSemaphoreLatencyArgs::ChildOpen() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue")); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: } sl@0: sl@0: void ThreadSemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime) sl@0: { sl@0: TInt r = iSignalTimeQue.Send(aTime); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: sl@0: TBMTicks ThreadSemaphoreLatencyArgs::SignalTime() sl@0: { sl@0: TBMTicks time; sl@0: iSignalTimeQue.ReceiveBlocking(time); sl@0: return time; sl@0: } sl@0: sl@0: void ThreadSemaphoreLatencyArgs::ChildClose() sl@0: { sl@0: if (iRemote) sl@0: { sl@0: iSignalTimeQue.Close(); sl@0: } sl@0: } sl@0: sl@0: void ThreadSemaphoreLatencyArgs::Close() sl@0: { sl@0: iSignalTimeQue.Close(); sl@0: } sl@0: sl@0: void Sync::ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote) sl@0: { sl@0: ThreadSemaphoreLatencyArgs sl(aRemote, aIter); sl@0: MBMChild* child = sync.SpawnChild(&sl); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: sl.iStatus = KRequestPending; sl@0: User::WaitForRequest(sl.iStatus); sl@0: BM_ASSERT(sl.iStatus == KErrNone); sl@0: TBMTicks now; sl@0: ::bmTimer.Stamp(&now); sl@0: aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now)); sl@0: } sl@0: child->WaitChildExit(); sl@0: sl.Close(); sl@0: } sl@0: sl@0: TInt Sync::ThreadSemaphoreLatencyChild(TAny* ptr) sl@0: { sl@0: ThreadSemaphoreLatencyArgs* sl = (ThreadSemaphoreLatencyArgs*) ptr; sl@0: sl->ChildOpen(); sl@0: for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i) sl@0: { sl@0: TRequestStatus* sptr = sl->iStatusPtr; sl@0: TBMTicks sigTime; sl@0: ::bmTimer.Stamp(&sigTime); sl@0: sl->iParent.RequestComplete(sptr, KErrNone); sl@0: sl->ChildSignalTime(sigTime); sl@0: } sl@0: sl->ChildClose(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TBMResult* Sync::Run(TBMUInt64 aIter, TInt* aCount) sl@0: { sl@0: TInt count = sizeof(iResults)/sizeof(iResults[0]); sl@0: sl@0: for (TInt i = 0; i < count; ++i) sl@0: { sl@0: iResults[i].Reset(iMeasurements[i].iName); sl@0: iMeasurements[i].iFunc(&iResults[i], aIter, iMeasurements[i].iRemote); sl@0: iResults[i].Update(); sl@0: } sl@0: sl@0: *aCount = count; sl@0: return iResults; sl@0: } sl@0: sl@0: void AddSync() sl@0: { sl@0: BMProgram* next = bmSuite; sl@0: bmSuite=(BMProgram*)&sync; sl@0: bmSuite->Next()=next; sl@0: }