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