os/kernelhwsrv/kerneltest/e32test/misc/cpumeter.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) 1996-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
// e32test\misc\cpumeter.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#define __E32TEST_EXTENSION__
sl@0
    19
sl@0
    20
#include <e32test.h>
sl@0
    21
#include <e32hal.h>
sl@0
    22
#include <e32svr.h>
sl@0
    23
#include "u32std.h"
sl@0
    24
sl@0
    25
RTest test(_L("CPU METER"));
sl@0
    26
sl@0
    27
TBool CpuTimeSupported()
sl@0
    28
	{
sl@0
    29
	TTimeIntervalMicroSeconds time;
sl@0
    30
	TInt err = RThread().GetCpuTime(time);
sl@0
    31
	test(err == KErrNone || err == KErrNotSupported);
sl@0
    32
	return err == KErrNone;
sl@0
    33
	}
sl@0
    34
sl@0
    35
TInt NumberOfCpus()
sl@0
    36
	{
sl@0
    37
	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
sl@0
    38
	test(r>0);
sl@0
    39
	return r;
sl@0
    40
	}
sl@0
    41
sl@0
    42
class CCpuMeter : public CBase
sl@0
    43
	{
sl@0
    44
public:
sl@0
    45
	CCpuMeter();
sl@0
    46
	~CCpuMeter();
sl@0
    47
	static CCpuMeter* New();
sl@0
    48
	TInt Construct();
sl@0
    49
	void Measure();
sl@0
    50
	void Display(TInt aInterval);
sl@0
    51
public:
sl@0
    52
	TInt iNumCpus;
sl@0
    53
	TInt iNextMeas;
sl@0
    54
	RThread* iNullThreads;
sl@0
    55
	TTimeIntervalMicroSeconds* iMeas[2];
sl@0
    56
	TInt* iDelta;
sl@0
    57
	};
sl@0
    58
sl@0
    59
CCpuMeter::CCpuMeter()
sl@0
    60
	{
sl@0
    61
	}
sl@0
    62
sl@0
    63
CCpuMeter::~CCpuMeter()
sl@0
    64
	{
sl@0
    65
	TInt i;
sl@0
    66
	if (iNullThreads)
sl@0
    67
		{
sl@0
    68
		for (i=0; i<iNumCpus; ++i)
sl@0
    69
			iNullThreads[i].Close();
sl@0
    70
		User::Free(iNullThreads);
sl@0
    71
		}
sl@0
    72
	User::Free(iMeas[0]);
sl@0
    73
	User::Free(iMeas[1]);
sl@0
    74
	User::Free(iDelta);
sl@0
    75
	}
sl@0
    76
sl@0
    77
TInt CCpuMeter::Construct()
sl@0
    78
	{
sl@0
    79
	iNumCpus = NumberOfCpus();
sl@0
    80
	iNullThreads = (RThread*)User::AllocZ(iNumCpus*sizeof(RThread));
sl@0
    81
	iDelta = (TInt*)User::AllocZ(iNumCpus*sizeof(TInt));
sl@0
    82
	iMeas[0] = (TTimeIntervalMicroSeconds*)User::AllocZ(iNumCpus*sizeof(TTimeIntervalMicroSeconds));
sl@0
    83
	iMeas[1] = (TTimeIntervalMicroSeconds*)User::AllocZ(iNumCpus*sizeof(TTimeIntervalMicroSeconds));
sl@0
    84
	if (!iNullThreads || !iDelta || !iMeas[0] || !iMeas[1])
sl@0
    85
		return KErrNoMemory;
sl@0
    86
	TFullName kname;
sl@0
    87
	_LIT(KLitKernelName, "ekern.exe*");
sl@0
    88
	_LIT(KLitNull, "::Null");
sl@0
    89
	TFindProcess fp(KLitKernelName);
sl@0
    90
	test_KErrNone(fp.Next(kname));
sl@0
    91
	test.Printf(_L("Found kernel process: %S\n"), &kname);
sl@0
    92
	kname.Append(KLitNull);
sl@0
    93
	TInt i;
sl@0
    94
	for (i=0; i<iNumCpus; ++i)
sl@0
    95
		{
sl@0
    96
		TFullName tname(kname);
sl@0
    97
		TFullName tname2;
sl@0
    98
		if (i>0)
sl@0
    99
			tname.AppendNum(i);
sl@0
   100
		TFindThread ft(tname);
sl@0
   101
		test_KErrNone(ft.Next(tname2));
sl@0
   102
		TInt r = iNullThreads[i].Open(ft);
sl@0
   103
		test_KErrNone(r);
sl@0
   104
		iNullThreads[i].FullName(tname2);
sl@0
   105
		test.Printf(_L("Found and opened %S\n"), &tname2);
sl@0
   106
		}
sl@0
   107
	for (i=0; i<iNumCpus; ++i)
sl@0
   108
		iNullThreads[i].GetCpuTime(iMeas[0][i]);
sl@0
   109
	iNextMeas = 1;
sl@0
   110
	return KErrNone;
sl@0
   111
	}
sl@0
   112
sl@0
   113
CCpuMeter* CCpuMeter::New()
sl@0
   114
	{
sl@0
   115
	CCpuMeter* p = new CCpuMeter;
sl@0
   116
	if (!p)
sl@0
   117
		return 0;
sl@0
   118
	TInt r = p->Construct();
sl@0
   119
	if (r!=KErrNone)
sl@0
   120
		{
sl@0
   121
		delete p;
sl@0
   122
		return 0;
sl@0
   123
		}
sl@0
   124
	return p;
sl@0
   125
	}
sl@0
   126
sl@0
   127
void CCpuMeter::Measure()
sl@0
   128
	{
sl@0
   129
	TInt i;
sl@0
   130
	for (i=0; i<iNumCpus; ++i)
sl@0
   131
		iNullThreads[i].GetCpuTime(iMeas[iNextMeas][i]);
sl@0
   132
	TInt prev = 1 - iNextMeas;
sl@0
   133
	for (i=0; i<iNumCpus; ++i)
sl@0
   134
		iDelta[i] = TInt(iMeas[iNextMeas][i].Int64() - iMeas[prev][i].Int64());
sl@0
   135
	iNextMeas = prev;
sl@0
   136
	}
sl@0
   137
sl@0
   138
void CCpuMeter::Display(TInt aInterval)
sl@0
   139
	{
sl@0
   140
	TBuf<80> buf;
sl@0
   141
	TInt i;
sl@0
   142
	for (i=0; i<iNumCpus; ++i)
sl@0
   143
		{
sl@0
   144
		TInt dv = (1000*(aInterval - iDelta[i]))/aInterval;
sl@0
   145
		if (dv<0)
sl@0
   146
			dv=0;
sl@0
   147
		if (dv>1000)
sl@0
   148
			dv=1000;
sl@0
   149
		buf.AppendFormat(_L(" %4d"),dv);
sl@0
   150
		}
sl@0
   151
	buf.Append(TChar('\n'));
sl@0
   152
	test.Printf(buf);
sl@0
   153
	}
sl@0
   154
sl@0
   155
void UseKernelCpuTime()
sl@0
   156
	{
sl@0
   157
	test.Start(_L("Create CCpuMeter"));
sl@0
   158
	CCpuMeter* m = CCpuMeter::New();
sl@0
   159
	test_NotNull(m);
sl@0
   160
	TInt iv = 1000500;	// on average 1000.5 ms
sl@0
   161
	TRequestStatus s;
sl@0
   162
	CConsoleBase* console = test.Console();
sl@0
   163
	console->Read(s);
sl@0
   164
	FOREVER
sl@0
   165
		{
sl@0
   166
		User::AfterHighRes(1000000);
sl@0
   167
		m->Measure();
sl@0
   168
		m->Display(iv);
sl@0
   169
		while (s!=KRequestPending)
sl@0
   170
			{
sl@0
   171
			User::WaitForRequest(s);
sl@0
   172
			TKeyCode k = console->KeyCode();
sl@0
   173
			if (k == EKeyEscape)
sl@0
   174
				{
sl@0
   175
				delete m;
sl@0
   176
				return;
sl@0
   177
				}
sl@0
   178
			console->Read(s);
sl@0
   179
			}
sl@0
   180
		}
sl@0
   181
	}
sl@0
   182
sl@0
   183
sl@0
   184
sl@0
   185
TUint32 NopCount=0;
sl@0
   186
TUint MaxCycles;
sl@0
   187
_LIT(KLitThreadName,"IdleThread");
sl@0
   188
extern TInt CountNops(TAny*);
sl@0
   189
sl@0
   190
void MeasureByNOPs()
sl@0
   191
	{
sl@0
   192
	test.Start(_L("Create thread"));
sl@0
   193
	RThread t;
sl@0
   194
	TInt r=t.Create(KLitThreadName,CountNops,0x1000,NULL,NULL);
sl@0
   195
	test(r==KErrNone);
sl@0
   196
	t.SetPriority(EPriorityAbsoluteVeryLow);
sl@0
   197
	t.Resume();
sl@0
   198
sl@0
   199
	test.Next(_L("Get processor clock frequency"));
sl@0
   200
	TMachineInfoV2Buf buf;
sl@0
   201
	TMachineInfoV2& info=buf();
sl@0
   202
	r=UserHal::MachineInfo(buf);
sl@0
   203
	test(r==KErrNone);
sl@0
   204
	MaxCycles=info.iProcessorClockInKHz*1000;
sl@0
   205
	test.Printf(_L("Clock frequency %dHz\n"),MaxCycles);
sl@0
   206
	TRequestStatus s;
sl@0
   207
	CConsoleBase* console=test.Console();
sl@0
   208
	console->Read(s);
sl@0
   209
#ifdef __WINS__
sl@0
   210
	TInt timerperiod = 5;
sl@0
   211
	UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"TimerResolution",&timerperiod);
sl@0
   212
#endif
sl@0
   213
sl@0
   214
	FOREVER
sl@0
   215
		{
sl@0
   216
		TUint32 init_count=NopCount;
sl@0
   217
		TUint32 init_ms=User::NTickCount();
sl@0
   218
		User::After(1000000);
sl@0
   219
		TUint32 final_count=NopCount;
sl@0
   220
		TUint32 final_ms=User::NTickCount();
sl@0
   221
		TUint32 cycles=final_count-init_count;
sl@0
   222
		TUint32 ms=final_ms-init_ms;
sl@0
   223
#ifdef __WINS__
sl@0
   224
		ms*=timerperiod;
sl@0
   225
#endif
sl@0
   226
		while (s!=KRequestPending)
sl@0
   227
			{
sl@0
   228
			User::WaitForRequest(s);
sl@0
   229
			TKeyCode k=console->KeyCode();
sl@0
   230
			if (k==EKeyTab)
sl@0
   231
				{
sl@0
   232
				// calibrate
sl@0
   233
				TInt64 inst64 = MAKE_TINT64(0, cycles);
sl@0
   234
				inst64*=1000;
sl@0
   235
				inst64/=MAKE_TINT64(0,ms);
sl@0
   236
				MaxCycles=I64LOW(inst64);
sl@0
   237
				test.Printf(_L("NOPs per second %u\n"),MaxCycles);
sl@0
   238
				}
sl@0
   239
			else if (k==EKeyEscape)
sl@0
   240
				return;
sl@0
   241
			console->Read(s);
sl@0
   242
			}
sl@0
   243
		TInt64 used64=MAKE_TINT64(0, MaxCycles);
sl@0
   244
sl@0
   245
		used64-=MAKE_TINT64(0,cycles);
sl@0
   246
		used64*=1000000;
sl@0
   247
		used64/=MAKE_TINT64(0,ms);
sl@0
   248
		used64/=MAKE_TINT64(0, MaxCycles);
sl@0
   249
		test.Printf(_L("%4d\n"),I64INT(used64));
sl@0
   250
		}
sl@0
   251
	}
sl@0
   252
sl@0
   253
sl@0
   254
GLDEF_C TInt E32Main()
sl@0
   255
	{
sl@0
   256
	test.SetLogged(EFalse);
sl@0
   257
	test.Title();
sl@0
   258
	RThread().SetPriority(EPriorityAbsoluteHigh);
sl@0
   259
sl@0
   260
	if (CpuTimeSupported())
sl@0
   261
		{
sl@0
   262
		UseKernelCpuTime();
sl@0
   263
		}
sl@0
   264
	if (NumberOfCpus()>1)
sl@0
   265
		{
sl@0
   266
		test.Printf(_L("Needs RThread::GetCpuTime() on SMP systems\n"));
sl@0
   267
		}
sl@0
   268
	else
sl@0
   269
		MeasureByNOPs();
sl@0
   270
sl@0
   271
	return 0;
sl@0
   272
	}
sl@0
   273