os/kernelhwsrv/kerneltest/e32test/benchmark/sync.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include <e32test.h>
    17 #include <e32msgqueue.h>
    18 
    19 #include "bm_suite.h"
    20 
    21 class Sync : public BMProgram
    22 	{
    23 public :
    24 	Sync() : BMProgram(_L("Synchronization Primitives"))
    25 		{}
    26 	virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount);
    27 
    28 	typedef void (*MeasurementFunc)(TBMResult*, TBMUInt64 aIter, TBool aRemote);
    29 	struct Measurement 
    30 		{
    31 		MeasurementFunc iFunc;
    32 		TPtrC			iName;
    33 		TBool			iRemote;
    34 
    35 		Measurement(MeasurementFunc aFunc, const TDesC& aName, TBool aRemote = EFalse) : 
    36 					iFunc(aFunc), iName(aName), iRemote(aRemote) {}
    37 		};
    38 
    39 	static TBMResult iResults[];
    40 	static Measurement iMeasurements[];
    41 
    42 	static void MutexPassing(TBMResult*, TBMUInt64 aIter, TBool aRemote);
    43 	static void MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
    44 	static TInt MutexContentionChild(TAny*);
    45 	static void SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
    46 	static TInt SemaphoreLatencyChild(TAny*);
    47 	static void ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote);
    48 	static TInt ThreadSemaphoreLatencyChild(TAny*);
    49 	};
    50 
    51 Sync::Measurement Sync::iMeasurements[] =
    52 	{
    53 	Measurement(&Sync::MutexPassing, _L("Mutex Passing Case")),
    54 	Measurement(&Sync::MutexContentionParent, _L("Local Mutex Contention")),
    55 	Measurement(&Sync::MutexContentionParent, _L("Remote Mutex Contention"), ETrue),
    56 	Measurement(&Sync::SemaphoreLatencyParent, _L("Local Semaphore Latency")),
    57 	Measurement(&Sync::SemaphoreLatencyParent, _L("Remote Semaphore Latency"), ETrue),
    58 	Measurement(&Sync::ThreadSemaphoreLatencyParent, _L("Local Thread Semaphore Latency")),
    59 	};
    60 TBMResult Sync::iResults[sizeof(Sync::iMeasurements)/sizeof(Sync::iMeasurements[0])];
    61 
    62 static Sync sync;
    63 
    64 void Sync::MutexPassing(TBMResult* aResult, TBMUInt64 aIter, TBool)
    65 	{
    66 	RMutex mutex;
    67 	mutex.CreateLocal();
    68 
    69 	TBMTimeInterval ti;
    70 	ti.Begin();
    71 	for (TBMUInt64 i = 0; i < aIter; ++i)
    72 		{
    73 		mutex.Wait();
    74 		mutex.Signal();
    75 		}
    76 	TBMTicks t = ti.End();
    77 
    78 	mutex.Close();
    79 
    80 	aResult->Cumulate(t, aIter);
    81 	}
    82 
    83 class MutexContentionArgs : public TBMSpawnArgs
    84 	{
    85 public:
    86 	
    87 	RMutex		iMutexA;
    88 	RMutex		iMutexB;
    89 	RSemaphore	iSem;
    90 	TBMUInt64	iIterationCount;
    91 
    92 	MutexContentionArgs(TInt aRemote, TBMUInt64 aIter);
    93 
    94 	void ChildOpen();
    95 	void ChildClose();
    96 
    97 	void Close();
    98 	};
    99 
   100 MutexContentionArgs::MutexContentionArgs(TInt aRemote, TBMUInt64 aIter) :
   101 		TBMSpawnArgs(Sync::MutexContentionChild, KBMPriorityLow, aRemote, sizeof(*this)),
   102 		iIterationCount(aIter)
   103 	{
   104 	TInt r;
   105 	if (aRemote)
   106 		{
   107 		r = iMutexA.CreateGlobal(_L("MutexA"));
   108 		BM_ERROR(r, r == KErrNone);
   109 		r = iMutexB.CreateGlobal(_L("MutexB"));
   110 		BM_ERROR(r, r == KErrNone);
   111 		r = iSem.CreateGlobal(_L("Semaphore"), 0);
   112 		BM_ERROR(r, r == KErrNone);
   113 		}
   114 	else
   115 		{
   116 		r = iMutexA.CreateLocal();
   117 		BM_ERROR(r, r == KErrNone);
   118 		r = iMutexB.CreateLocal();
   119 		BM_ERROR(r, r == KErrNone);
   120 		r = iSem.CreateLocal(0);
   121 		BM_ERROR(r, r == KErrNone);
   122 		}
   123 	}
   124 
   125 void MutexContentionArgs::ChildOpen()
   126 	{
   127 	if (iRemote)
   128 		{
   129 		iMutexA.Duplicate(iParent);
   130 		iMutexB.Duplicate(iParent);
   131 		iSem.Duplicate(iParent);
   132 		}
   133 	}
   134 
   135 void MutexContentionArgs::ChildClose()
   136 	{
   137 	if (iRemote)
   138 		{
   139 		iMutexA.Close();
   140 		iMutexB.Close();
   141 		iSem.Close();
   142 		}
   143 	}
   144 
   145 void MutexContentionArgs::Close()
   146 	{
   147 	iMutexA.Close();
   148 	iMutexB.Close();
   149 	iSem.Close();
   150 	}
   151 
   152 void Sync::MutexContentionParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
   153 	{
   154 	MutexContentionArgs mc(aRemote, aIter);
   155 
   156 	MBMChild* child = sync.SpawnChild(&mc);
   157 
   158 	mc.iSem.Wait();
   159 
   160 	TBMTimeInterval ti;
   161 	ti.Begin();
   162 	for (TBMUInt64 i = 0; i < aIter; ++i)
   163 		{
   164 		mc.iMutexA.Wait();
   165 		mc.iMutexA.Signal();
   166 		mc.iMutexB.Wait();
   167 		mc.iMutexB.Signal();
   168 		}	
   169 	TBMTicks t = ti.End();
   170 
   171 	child->WaitChildExit();
   172 	mc.Close();
   173 
   174 	aResult->Cumulate(t/2, aIter);
   175 	}
   176 
   177 TInt Sync::MutexContentionChild(TAny* ptr)
   178 	{
   179 	MutexContentionArgs* mc = (MutexContentionArgs*) ptr;
   180 	mc->ChildOpen();
   181 
   182 	mc->iMutexA.Wait();
   183 	mc->iSem.Signal();
   184 	for (TBMUInt64 i = 0; i < mc->iIterationCount; ++i)
   185 		{
   186 		mc->iMutexB.Wait();
   187 		mc->iMutexA.Signal();
   188 		mc->iMutexA.Wait();
   189 		mc->iMutexB.Signal();
   190 		}
   191 	mc->iMutexA.Signal();
   192 
   193 	mc->ChildClose();
   194 	return KErrNone;
   195 	}
   196 
   197 class SemaphoreLatencyArgs : public TBMSpawnArgs
   198 	{
   199 public:
   200 	
   201 	RSemaphore			iSem;
   202 	TBMUInt64			iIterationCount;
   203 	RMsgQueue<TBMTicks>	iSignalTimeQue;
   204 
   205 	SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter);
   206 
   207 	void ChildOpen();
   208 	void ChildClose();
   209 
   210 	TBMTicks SignalTime();
   211 	void ChildSignalTime(TBMTicks);
   212 
   213 	void Close();
   214 	};
   215 
   216 SemaphoreLatencyArgs::SemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : 
   217 	TBMSpawnArgs(Sync::SemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)),
   218 	iIterationCount(aIter)
   219 	{
   220 	TInt r;
   221 	if (aRemote)
   222 		{
   223 		r = iSem.CreateGlobal(_L("BM Semaphore"), 0);
   224 		BM_ERROR(r, r == KErrNone);
   225 		}
   226 	else
   227 		{
   228 		r = iSem.CreateLocal(0);
   229 		BM_ERROR(r, r == KErrNone);
   230 		}
   231 	r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1);
   232 	BM_ERROR(r, r == KErrNone);
   233 	}	
   234 
   235 void SemaphoreLatencyArgs::ChildOpen()
   236 	{
   237 	if (iRemote)
   238 		{
   239 		iSem.Duplicate(iParent);
   240 		TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue"));
   241 		BM_ERROR(r, r == KErrNone);
   242 		}
   243 	}
   244 
   245 void SemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime)
   246 	{
   247 	TInt r = iSignalTimeQue.Send(aTime);
   248 	BM_ERROR(r, r == KErrNone);
   249 	}
   250 
   251 TBMTicks SemaphoreLatencyArgs::SignalTime()
   252 	{
   253 	TBMTicks time;
   254 	iSignalTimeQue.ReceiveBlocking(time);
   255 	return time;
   256 	}
   257 
   258 void SemaphoreLatencyArgs::ChildClose()
   259 	{
   260 	if (iRemote)
   261 		{
   262 		iSem.Close();
   263 		iSignalTimeQue.Close();
   264 		}
   265 	}
   266 
   267 void SemaphoreLatencyArgs::Close()
   268 	{
   269 	iSem.Close();
   270 	iSignalTimeQue.Close();
   271 	}
   272 
   273 void Sync::SemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
   274 	{
   275 	SemaphoreLatencyArgs sl(aRemote, aIter);
   276 	MBMChild* child = sync.SpawnChild(&sl);
   277 	for (TBMUInt64 i = 0; i < aIter; ++i)
   278 		{
   279 		sl.iSem.Wait();
   280 		TBMTicks now;
   281 		::bmTimer.Stamp(&now);
   282 		aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now));
   283 		}
   284 	child->WaitChildExit();
   285 	sl.Close();
   286 	}
   287 
   288 TInt Sync::SemaphoreLatencyChild(TAny* ptr)
   289 	{
   290 	SemaphoreLatencyArgs* sl = (SemaphoreLatencyArgs*) ptr;
   291 	sl->ChildOpen();
   292 	for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i)
   293 		{
   294 		TBMTicks sigTime;
   295 		::bmTimer.Stamp(&sigTime);		
   296 		sl->iSem.Signal();
   297 		sl->ChildSignalTime(sigTime);
   298 		}
   299 	sl->ChildClose();
   300 	return KErrNone;
   301 	}
   302 
   303 class ThreadSemaphoreLatencyArgs : public TBMSpawnArgs
   304 	{
   305 public:
   306 	
   307 	TBMUInt64			iIterationCount;
   308 	TBMTicks			iSignalTime;
   309 	TRequestStatus		iStatus;
   310 	TRequestStatus*		iStatusPtr;
   311 	RMsgQueue<TBMTicks>	iSignalTimeQue;
   312 
   313 	ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter);
   314 
   315 	void ChildOpen();
   316 	void ChildClose();
   317 
   318 	TBMTicks SignalTime();
   319 	void ChildSignalTime(TBMTicks);
   320 
   321 	void Close();
   322 	};
   323 
   324 ThreadSemaphoreLatencyArgs::ThreadSemaphoreLatencyArgs(TInt aRemote, TBMUInt64 aIter) : 
   325 	TBMSpawnArgs(Sync::ThreadSemaphoreLatencyChild, KBMPriorityLow, aRemote, sizeof(*this)),
   326 	iIterationCount(aIter),
   327 	iStatusPtr(&iStatus)
   328 
   329 	{
   330 	TInt r = iSignalTimeQue.CreateGlobal(_L("BM Queue"), 1);
   331 	BM_ERROR(r, r == KErrNone);
   332 	}
   333 
   334 void ThreadSemaphoreLatencyArgs::ChildOpen()
   335 	{
   336 	if (iRemote)
   337 		{
   338 		TInt r = iSignalTimeQue.OpenGlobal(_L("BM Queue"));
   339 		BM_ERROR(r, r == KErrNone);
   340 		}
   341 	}
   342 
   343 void ThreadSemaphoreLatencyArgs::ChildSignalTime(TBMTicks aTime)
   344 	{
   345 	TInt r = iSignalTimeQue.Send(aTime);
   346 	BM_ERROR(r, r == KErrNone);
   347 	}
   348 
   349 TBMTicks ThreadSemaphoreLatencyArgs::SignalTime()
   350 	{
   351 	TBMTicks time;
   352 	iSignalTimeQue.ReceiveBlocking(time);
   353 	return time;
   354 	}
   355 
   356 void ThreadSemaphoreLatencyArgs::ChildClose()
   357 	{
   358 	if (iRemote)
   359 		{
   360 		iSignalTimeQue.Close();
   361 		}
   362 	}
   363 
   364 void ThreadSemaphoreLatencyArgs::Close()
   365 	{
   366 	iSignalTimeQue.Close();
   367 	}
   368 
   369 void Sync::ThreadSemaphoreLatencyParent(TBMResult* aResult, TBMUInt64 aIter, TBool aRemote)
   370 	{
   371 	ThreadSemaphoreLatencyArgs sl(aRemote, aIter);
   372 	MBMChild* child = sync.SpawnChild(&sl);
   373 	for (TBMUInt64 i = 0; i < aIter; ++i)
   374 		{
   375 		sl.iStatus = KRequestPending;
   376 		User::WaitForRequest(sl.iStatus);
   377 		BM_ASSERT(sl.iStatus == KErrNone);
   378 		TBMTicks now;
   379 		::bmTimer.Stamp(&now);
   380 		aResult->Cumulate(TBMTicksDelta(sl.SignalTime(), now));
   381 		}
   382 	child->WaitChildExit();
   383 	sl.Close();
   384 	}
   385 
   386 TInt Sync::ThreadSemaphoreLatencyChild(TAny* ptr)
   387 	{
   388 	ThreadSemaphoreLatencyArgs* sl = (ThreadSemaphoreLatencyArgs*) ptr;
   389 	sl->ChildOpen();
   390 	for (TBMUInt64 i = 0; i < sl->iIterationCount; ++i)
   391 		{
   392 		TRequestStatus* sptr = sl->iStatusPtr;
   393 		TBMTicks sigTime;
   394 		::bmTimer.Stamp(&sigTime);		
   395 		sl->iParent.RequestComplete(sptr, KErrNone);
   396 		sl->ChildSignalTime(sigTime);
   397 		}
   398 	sl->ChildClose();
   399 	return KErrNone;
   400 	}
   401 
   402 						
   403 TBMResult* Sync::Run(TBMUInt64 aIter, TInt* aCount)
   404 	{
   405 	TInt count = sizeof(iResults)/sizeof(iResults[0]);
   406 
   407 	for (TInt i = 0; i < count; ++i)
   408 		{
   409 		iResults[i].Reset(iMeasurements[i].iName);
   410 		iMeasurements[i].iFunc(&iResults[i], aIter, iMeasurements[i].iRemote);
   411 		iResults[i].Update();
   412 		}
   413 	
   414 	*aCount = count;
   415 	return iResults;
   416 	}
   417 
   418 void AddSync()
   419 	{
   420 	BMProgram* next = bmSuite;
   421 	bmSuite=(BMProgram*)&sync;
   422 	bmSuite->Next()=next;
   423 	}