os/kernelhwsrv/kerneltest/e32test/realtime/t_lat2.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1999-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 // e32test\realtime\t_lat2.cpp
    15 // 
    16 //
    17 
    18 #include <e32test.h>
    19 #include <e32svr.h>
    20 #include <e32property.h>
    21 #include <e32atomics.h>
    22 #include "runtests.h"
    23 #include "d_latncy.h"
    24 
    25 _LIT(KLatencyLddFileName,"D_LATNCY");
    26 _LIT(KThreadName,"LatencyThreadU");
    27 
    28 RTest test(_L("Latency"));
    29 RThread Main;
    30 TUint TicksPerMs;
    31 
    32 struct SFullLatencyResults : public SLatencyResults
    33 	{
    34 	TUint iKernRetAddr;
    35 	TUint iUserRetAddr;
    36 	TInt64 iCount;
    37 	TInt64 iSumIntTicks;
    38 	TInt64 iSumKernTicks;
    39 	TInt64 iSumUserTicks;
    40 	TUint iIntCpsr;
    41 	TUint iKernCpsr;
    42 	TUint iKernR14;
    43 	TUint iUserCpsr;
    44 	TUint iUserR14;
    45 
    46 	void Update(SLatencyResults& aResults);
    47 	};
    48 
    49 SFullLatencyResults Latencies;
    50 volatile TUint32 UpdateCount=0;
    51 
    52 TUint TimerToMicroseconds(TUint aTimerValue)
    53 	{
    54 	return (aTimerValue*1000+TicksPerMs-1)/TicksPerMs;
    55 	}
    56 
    57 void SFullLatencyResults::Update(SLatencyResults& aResults)
    58 	{
    59 	__e32_atomic_add_acq32(&UpdateCount, 1);
    60 
    61 	// memory barrier
    62 
    63 	if (aResults.iIntTicks>iIntTicks)
    64 		{
    65 		iIntTicks=aResults.iIntTicks;
    66 		iIntRetAddr=aResults.iIntRetAddr;
    67 #ifdef __CAPTURE_EXTRAS
    68 		iIntCpsr=aResults.iIntSpsr;
    69 		iIntR14=aResults.iIntR14;
    70 #endif
    71 		}
    72 	if (aResults.iKernThreadTicks>iKernThreadTicks)
    73 		{
    74 		iKernThreadTicks=aResults.iKernThreadTicks;
    75 		iKernRetAddr=aResults.iIntRetAddr;
    76 #ifdef __CAPTURE_EXTRAS
    77 		iKernCpsr=aResults.iIntSpsr;
    78 		iKernR14=aResults.iIntR14;
    79 #endif
    80 		}
    81 	if (aResults.iUserThreadTicks>iUserThreadTicks)
    82 		{
    83 		iUserThreadTicks=aResults.iUserThreadTicks;
    84 		iUserRetAddr=aResults.iIntRetAddr;
    85 #ifdef __CAPTURE_EXTRAS
    86 		iUserCpsr=aResults.iIntSpsr;
    87 		iUserR14=aResults.iIntR14;
    88 #endif
    89 		}
    90 	iSumIntTicks+=aResults.iIntTicks;
    91 	iSumKernTicks+=aResults.iKernThreadTicks;
    92 	iSumUserTicks+=aResults.iUserThreadTicks;
    93 	++iCount;
    94 
    95 	// memory barrier
    96 
    97 	__e32_atomic_add_rel32(&UpdateCount, 1);
    98 	}
    99 
   100 TInt LatencyThread(TAny* aStatus)
   101 	{
   102 	TRequestStatus* pS=(TRequestStatus*)aStatus;
   103 	RLatency l;
   104 	TInt r=l.Open();
   105 	if (r!=KErrNone)
   106 		return r;
   107 	TicksPerMs=l.TicksPerMs();
   108 	Mem::FillZ(&Latencies,sizeof(Latencies));
   109 	Main.RequestComplete(pS,0);
   110 	SLatencyResults results;
   111 
   112 	l.Start();
   113 	FOREVER
   114 		{
   115 		User::WaitForAnyRequest();
   116 		l.GetResults(results);
   117 		Latencies.Update(results);
   118 		}
   119 	return r;
   120 	}
   121 
   122 void GetLatencies(SFullLatencyResults& aResults)
   123 	{
   124 	FOREVER
   125 		{
   126 		TUint32 u1 = UpdateCount;
   127 		__e32_memory_barrier();
   128 		aResults=Latencies;
   129 		__e32_memory_barrier();
   130 		TUint32 u2 = UpdateCount;
   131 		if (u1==u2 && !(u1&1))	// no good if it changed partway through or was changing when we started
   132 			break;
   133 		}
   134 	}
   135 
   136 _LIT(KPrefixRuntests, "RUNTESTS: RT");
   137 void DisplayMaxValues(const TDesC& aPrefix)
   138 	{
   139 	SFullLatencyResults v;
   140 	GetLatencies(v);
   141 	TUint i=TimerToMicroseconds(v.iIntTicks);
   142 	TUint k=TimerToMicroseconds(v.iKernThreadTicks);
   143 	TUint u=TimerToMicroseconds(v.iUserThreadTicks);
   144 	TUint ia=v.iIntRetAddr;
   145 	TUint ka=v.iKernRetAddr;
   146 	TUint ua=v.iUserRetAddr;
   147 	test.Printf(_L("%SMAX: Int %4d %08x Kern %4d %08x User %4d %08x\n"),&aPrefix,i,ia,k,ka,u,ua);
   148 	}
   149 
   150 void DisplayAvgValues(const TDesC& aPrefix)
   151 	{
   152 	SFullLatencyResults v;
   153 	GetLatencies(v);
   154 	TUint i=TimerToMicroseconds(I64LOW(v.iSumIntTicks/v.iCount));
   155 	TUint k=TimerToMicroseconds(I64LOW(v.iSumKernTicks/v.iCount));
   156 	TUint u=TimerToMicroseconds(I64LOW(v.iSumUserTicks/v.iCount));
   157 	test.Printf(_L("%SAVG: Int %4d Kern %4d User %4d Count %Ld\n"),&aPrefix,i,k,u,v.iCount);
   158 	}
   159 
   160 #ifdef __CAPTURE_EXTRAS
   161 void DisplayExtras(const TDesC& aPrefix)
   162 	{
   163 	SFullLatencyResults v;
   164 	GetLatencies(v);
   165 	test.Printf(_L("%SInt : Cpsr %08x R14 %08x\n"),&aPrefix,v.iIntCpsr,v.iIntR14);
   166 	test.Printf(_L("%SKern: Cpsr %08x R14 %08x\n"),&aPrefix,v.iKernCpsr,v.iKernR14);
   167 	test.Printf(_L("%SUser: Cpsr %08x R14 %08x\n"),&aPrefix,v.iUserCpsr,v.iUserR14);
   168 	}
   169 #endif
   170 
   171 void ClearMaxValues()
   172 	{
   173 	Mem::FillZ(&Latencies,6*sizeof(TUint));
   174 	}
   175 
   176 void ClearAvgValues()
   177 	{
   178 	Mem::FillZ(&Latencies.iCount,4*sizeof(TInt64));
   179 	}
   180 
   181 _LIT_SECURITY_POLICY_PASS(KPersistencePropReadPolicy);
   182 _LIT_SECURITY_POLICY_PASS(KPersistencePropWritePolicy);
   183 void AnnouncePersistence()
   184 	{
   185 	TInt r = RProperty::Define(KRuntestsIntentionalPersistenceKey, RProperty::EInt, KPersistencePropReadPolicy, KPersistencePropWritePolicy);
   186 	test(r==KErrNone || r==KErrAlreadyExists);
   187 	r = RProperty::Set(RProcess().SecureId(), KRuntestsIntentionalPersistenceKey, KRuntestsIntentionalPersistenceValue);
   188 	test(r==KErrNone);
   189 	}
   190 
   191 class CConsoleReader : public CActive
   192 	{
   193 public:
   194 	CConsoleReader();
   195 	static void New();
   196 	void Start();
   197 	virtual void RunL();
   198 	virtual void DoCancel();
   199 public:
   200 	CConsoleBase* iConsole;
   201 	};
   202 
   203 CConsoleReader::CConsoleReader()
   204 	:	CActive(0)
   205 	{
   206 	}
   207 
   208 void CConsoleReader::RunL()
   209 	{
   210 	TKeyCode k = iConsole->KeyCode();
   211 	switch(k)
   212 		{
   213 		case '1':
   214 			test.Printf(_L("Clearing Maximum Values\n"));
   215 			ClearMaxValues();
   216 			break;
   217 		case '2':
   218 			DisplayMaxValues(KNullDesC);
   219 			break;
   220 		case '3':
   221 			test.Printf(_L("Clearing Average Values\n"));
   222 			ClearAvgValues();
   223 			break;
   224 		case '4':
   225 			DisplayAvgValues(KNullDesC);
   226 			break;
   227 #ifdef __CAPTURE_EXTRAS
   228 		case '5':
   229 			DisplayExtras(KNullDesC);
   230 			break;
   231 #endif
   232 		case 'x':
   233 		case 'X':
   234 			CActiveScheduler::Stop();
   235 			return;
   236 		default:
   237 			break;
   238 		}
   239 	Start();
   240 	}
   241 
   242 void CConsoleReader::DoCancel()
   243 	{
   244 	iConsole->ReadCancel();
   245 	}
   246 
   247 void CConsoleReader::New()
   248 	{
   249 	CConsoleReader* crdr = new CConsoleReader;
   250 	test(crdr != NULL);
   251 	crdr->iConsole = test.Console();
   252 	CActiveScheduler::Add(crdr);
   253 	crdr->Start();
   254 	}
   255 
   256 void CConsoleReader::Start()
   257 	{
   258 	iConsole->Read(iStatus);
   259 	SetActive();
   260 	}
   261 
   262 class CPubSubWatcher : public CActive
   263 	{
   264 public:
   265 	CPubSubWatcher();
   266 	static void New();
   267 	void Start();
   268 	virtual ~CPubSubWatcher();
   269 	virtual void RunL();
   270 	virtual void DoCancel();
   271 public:
   272 	RProperty iProperty;
   273 	};
   274 
   275 CPubSubWatcher::CPubSubWatcher()
   276 	:	CActive(0)
   277 	{
   278 	}
   279 
   280 void CPubSubWatcher::RunL()
   281 	{
   282 	Start();
   283 	DisplayMaxValues(KPrefixRuntests);
   284 	DisplayAvgValues(KPrefixRuntests);
   285 	}
   286 
   287 void CPubSubWatcher::DoCancel()
   288 	{
   289 	iProperty.Cancel();
   290 	}
   291 
   292 void CPubSubWatcher::New()
   293 	{
   294 	CPubSubWatcher* psw = new CPubSubWatcher;
   295 	test(psw != NULL);
   296 	TInt r = psw->iProperty.Attach(KRuntestsCategory, KRuntestsCurrentTestKey, EOwnerThread);
   297 	test(r==KErrNone);
   298 	CActiveScheduler::Add(psw);
   299 	psw->Start();
   300 	}
   301 
   302 void CPubSubWatcher::Start()
   303 	{
   304 	iProperty.Subscribe(iStatus);
   305 	SetActive();
   306 	}
   307 
   308 CPubSubWatcher::~CPubSubWatcher()
   309 	{
   310 	iProperty.Close();
   311 	}
   312 
   313 GLDEF_C TInt E32Main()
   314 	{
   315 #ifdef _DEBUG
   316 	// Don't run automatically on debug builds
   317 	TUint32 creator_sid = User::CreatorSecureId();
   318 	if (creator_sid == TUint32(KRuntestsCategoryValue))
   319 		return KErrNone;
   320 #endif
   321 	// disable anything which will interfere, e.g. plat sec diagnostics
   322 	User::SetDebugMask(UserSvr::DebugMask(2)|4, 2);
   323 
   324 	test.Title();
   325 	
   326 	test.Printf(_L("*** Please note ***\n"));
   327 	test.Printf(_L("\n"));
   328 	test.Printf(_L("t_lat2 runs in the backgroud to measure latency while other tests are\n"));
   329 	test.Printf(_L("running.  It should not be run as a standalone test, only as part of a\n"));
   330 	test.Printf(_L("test run coordinated by runtests.  If run on its owm, it will simply wait\n"));
   331 	test.Printf(_L("forever.\n"));
   332 	test.Printf(_L("\n"));
   333 	
   334 	test.Start(_L("Load LDD"));
   335 	TInt r=User::LoadLogicalDevice(KLatencyLddFileName);
   336 	test(r==KErrNone || r==KErrAlreadyExists);
   337 
   338 	test.Next(_L("Duplicate handle"));
   339 	r=Main.Duplicate(RThread());
   340 	test(r==KErrNone);
   341 
   342 	test.Next(_L("Create thread"));
   343 	RThread t;
   344 	TRequestStatus sx;
   345 	TRequestStatus sc;
   346 	r=t.Create(KThreadName,LatencyThread,0x1000,NULL,&sc);
   347 	test(r==KErrNone);
   348 	t.Logon(sx);
   349 	t.Resume();
   350 	User::WaitForRequest(sx,sc);
   351 	if (sx!=KRequestPending)
   352 		{
   353 		if (t.ExitType()==EExitKill && t.ExitReason()==KErrAlreadyExists)
   354 			{
   355 			test.Printf(_L("T_LAT2 already running.\n"));
   356 			test.End();
   357 			return 0;
   358 			}
   359 		test.Printf(_L("Initialisation failed, error %d\n"),sx.Int());
   360 		test(0);
   361 		}
   362 	test(sc==KErrNone);
   363 
   364 	CTrapCleanup* tcln = CTrapCleanup::New();
   365 	test(tcln != NULL);
   366 	CActiveScheduler* as = new CActiveScheduler;
   367 	test(as != NULL);
   368 	CActiveScheduler::Install(as);
   369 	CConsoleReader::New();
   370 	CPubSubWatcher::New();
   371 	AnnouncePersistence();
   372 	RProcess::Rendezvous(KErrNone);
   373 
   374 	CActiveScheduler::Start();
   375 
   376 	// latency test over
   377 	User::SetDebugMask(UserSvr::DebugMask(2)&~4, 2);
   378 
   379 	test.End();
   380 	return 0;
   381 	}