os/kernelhwsrv/kerneltest/e32test/misc/t_svr6.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-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\misc\t_svr6.cpp
    15 // 
    16 //
    17 
    18 #define __E32TEST_EXTENSION__
    19 #include <e32base.h>
    20 #include <e32base_private.h>
    21 #include <e32test.h>
    22 #include <e32svr.h>
    23 #include "u32std.h"
    24 #include "../misc/prbs.h"
    25 #include "../mmu/freeram.h"
    26 
    27 const TInt KStackSize=0x1000;
    28 const TInt KHeapMaxSize=0x100000;
    29 const TInt KMajorVersionNumber=1;
    30 const TInt KMinorVersionNumber=0;
    31 const TInt KBuildVersionNumber=1;
    32 const TInt KNumMessageSlots=10;
    33 
    34 _LIT(KServerName,"StressSvr");
    35 
    36 LOCAL_D RTest test(_L("T_SVR6"));
    37 
    38 class CMySession : public CSession2
    39 	{
    40 public:
    41 	CMySession();
    42 	virtual void ServiceL(const RMessage2& aMessage);			 //pure virtual fns.
    43 	void Process(const RMessage2& aMessage);
    44 public:
    45 	TInt iOutstanding;
    46 	TUint iSeed[2];
    47 	};
    48 
    49 class CMyServer : public CServer2
    50 	{
    51 public:
    52 	enum {ETest};
    53 public:
    54 	CMyServer(TInt aPriority);
    55 	static CMyServer* New(TInt aPriority);
    56 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2&) const;//Overloading
    57 	};
    58 
    59 class CMyActiveScheduler : public CActiveScheduler
    60 	{
    61 public:
    62 	virtual void Error(TInt anError) const;  //Overloading pure virtual function
    63 	};
    64 
    65 class RStressSvr : public RSessionBase
    66 	{
    67 public:
    68 	TInt Connect();
    69 	TInt Test();
    70 	void Test(TRequestStatus& aStatus);
    71 	TVersion Version();
    72 	};
    73 
    74 class CThread : public CActive
    75 	{
    76 public:
    77 	CThread(TInt aPriority);
    78 	~CThread();
    79 	virtual void RunL();
    80 	virtual void DoCancel();
    81 	virtual void DisplayStats()=0;
    82 	virtual TBool PanicBadHandleAllowed();
    83 	virtual void RegisterAllowedPanic();
    84 	virtual void Cleanup();
    85 	virtual TInt ProcessStartError(TInt anError);
    86 	TInt Start();
    87 public:
    88 	virtual TInt StartThread()=0;
    89 public:
    90 	RThread iThread;
    91 	TInt iExitCount;
    92 	TInt iServerTerminatedCount;
    93 	TInt iTerminateCount;
    94 	};
    95 
    96 class CServerThread : public CThread
    97 	{
    98 public:
    99 	static void NewL();
   100 	CServerThread();
   101 	virtual TInt StartThread();
   102 	virtual void DisplayStats();
   103 public:
   104 	TInt iMessagesReceived;
   105 	};
   106 
   107 class CClientThread : public CThread
   108 	{
   109 public:
   110 	static void NewL(TInt anId, TInt aPrimaryId);
   111 	CClientThread(TInt anId);
   112 	virtual TInt StartThread();
   113 	virtual void DisplayStats();
   114 	virtual TBool PanicBadHandleAllowed();
   115 	virtual void RegisterAllowedPanic();
   116 	virtual void Cleanup();
   117 	virtual TInt ProcessStartError(TInt anError);
   118 public:
   119 	TInt iId;
   120 	TInt iCloses;
   121 	CClientThread* iPrimary;
   122 	RStressSvr iSession;
   123 	TBool iConnected;
   124 	TBool iWaitingToRestart;
   125 	};
   126 
   127 class CRandomTimer : public CActive
   128 	{
   129 public:
   130 	static void NewL();
   131 	CRandomTimer(TInt aPriority);
   132 	~CRandomTimer();
   133 	virtual void RunL();
   134 	virtual void DoCancel();
   135 	void Start();
   136 public:
   137 	RTimer iTimer;
   138 	TUint iSeed[2];
   139 	TInt iCount;
   140 	};
   141 
   142 class CStatsTimer : public CActive
   143 	{
   144 public:
   145 	static void NewL();
   146 	CStatsTimer(TInt aPriority);
   147 	~CStatsTimer();
   148 	virtual void RunL();
   149 	virtual void DoCancel();
   150 	void Start();
   151 public:
   152 	RTimer iTimer;
   153 	TInt iInitFreeRam;
   154 	TInt iMaxDelta;
   155 	TInt iCount;
   156 	};
   157 
   158 const TInt KNumPrimaryClients=3;
   159 const TInt KNumSecondariesPerPrimary=3;
   160 const TInt KNumClients=KNumPrimaryClients*KNumSecondariesPerPrimary;
   161 LOCAL_D CServerThread* TheServer;
   162 LOCAL_D CClientThread* TheClients[KNumClients];
   163 LOCAL_D CRandomTimer* TheRandomTimer;
   164 
   165 CMySession::CMySession()
   166 //
   167 // Constructor
   168 //
   169 	{
   170 	iSeed[0]=User::TickCount();
   171 	}
   172 
   173 CMyServer* CMyServer::New(TInt aPriority)
   174 //
   175 // Create a new CMyServer.
   176 //
   177 	{
   178 
   179 	return new CMyServer(aPriority);
   180 	}
   181 
   182 CMyServer::CMyServer(TInt aPriority)
   183 //
   184 // Constructor.
   185 //
   186 	: CServer2(aPriority, ESharableSessions)
   187 	{}
   188 
   189 CSession2* CMyServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const
   190 //
   191 // Create a new client for this server.
   192 //
   193 	{
   194 
   195 	TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
   196 	if (!User::QueryVersionSupported(v,aVersion))
   197 		User::Leave(KErrNotSupported);
   198 	return new(ELeave) CMySession;
   199 	}
   200 
   201 void CMySession::ServiceL(const RMessage2& aMessage)
   202 //
   203 // Handle messages for this server.
   204 //
   205 	{
   206 
   207 	++TheServer->iMessagesReceived;
   208 	switch (aMessage.Function())
   209 		{
   210 		case CMyServer::ETest:
   211 			if (iOutstanding==KNumMessageSlots-1)
   212 				Process(aMessage);
   213 			else
   214 				++iOutstanding;
   215 			break;
   216 		default:
   217 			aMessage.Complete(KErrNotSupported);
   218 			break;
   219 		}
   220 	}
   221 
   222 void CMySession::Process(const RMessage2& aMessage)
   223 	{
   224 	TUint x=Random(iSeed)&16383;
   225 	if (x==0)
   226 		User::Exit(0);			// exit the server
   227 	else if (x<8)
   228 		aMessage.Terminate(0);	// terminate the client
   229 	else
   230 		aMessage.Complete(KErrNone);
   231 	}
   232 
   233 void CMyActiveScheduler::Error(TInt anError) const
   234 //
   235 // Called if any Run() method leaves.
   236 //
   237 	{
   238 
   239 	User::Panic(_L("Server Error"),anError);
   240 	}
   241 
   242 TInt RStressSvr::Connect()
   243 //
   244 // Connect to the server
   245 //
   246 	{
   247 
   248 	TInt r=CreateSession(KServerName,Version(),KNumMessageSlots);
   249 	if (r==KErrNone)
   250 		r=ShareAuto();
   251 	return r;
   252 	}
   253 
   254 TInt RStressSvr::Test()
   255 //
   256 // Send a message and wait for completion.
   257 //
   258 	{
   259 
   260 	return SendReceive(CMyServer::ETest);
   261 	}
   262 
   263 void RStressSvr::Test(TRequestStatus& aStatus)
   264 //
   265 // Send a message asynchronously
   266 //
   267 	{
   268 
   269 	SendReceive(CMyServer::ETest,aStatus);
   270 	}
   271 
   272 TVersion RStressSvr::Version()
   273 //
   274 // Return the current version.
   275 //
   276 	{
   277 
   278 	TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
   279 	return(v);
   280 	}
   281 
   282 LOCAL_C TInt ServerThread(TAny*)
   283 	{
   284 
   285 	CMyActiveScheduler* pR=new CMyActiveScheduler;
   286 	if (!pR)
   287 		return KErrNoMemory;
   288 	CActiveScheduler::Install(pR);
   289 	CMyServer* pS=CMyServer::New(0);
   290 	if (!pS)
   291 		return KErrNoMemory;
   292 	TInt r=pS->Start(KServerName);
   293 	if (r!=KErrNone)
   294 		return r;
   295 
   296 	CActiveScheduler::Start();
   297 
   298 	delete pS;
   299 	delete pR;
   300 	return KErrNone;
   301 	}
   302 
   303 LOCAL_C TInt ClientThread(TAny* aPtr)
   304 	{
   305 	CClientThread* pT=(CClientThread*)aPtr;
   306 	CClientThread* pP=pT->iPrimary;
   307 	TBool primary=(pP==pT);
   308 	RStressSvr& d=pP->iSession;
   309 	TUint seed[2];
   310 	seed[0]=User::TickCount();
   311 	seed[1]=0;
   312 	TInt r=KErrNone;
   313 	TInt i;
   314 	if (primary)
   315 		{
   316 		FOREVER
   317 			{
   318 			FOREVER
   319 				{
   320 				r=d.Connect();
   321 				if (r!=KErrNotFound)
   322 					break;
   323 				User::After(50000);
   324 				}
   325 			if (r!=KErrNone)
   326 				return r;
   327 			pT->iConnected=ETrue;
   328 			TRequestStatus s[KNumMessageSlots];
   329 			for (i=0; i<KNumMessageSlots-1; i++)
   330 				d.Test(s[i]);
   331 			TInt n=Random(seed)&16383;
   332 			for (i=0; i<n && r==KErrNone; i++)
   333 				r=d.Test();
   334 			pT->iConnected=EFalse;
   335 			d.Close();
   336 			++pT->iCloses;
   337 			}
   338 		}
   339 	else
   340 		{
   341 		TRequestStatus s[KNumMessageSlots];
   342 		for (i=0; i<KNumMessageSlots-1; i++)
   343 			d.Test(s[i]);
   344 		FOREVER
   345 			{
   346 			if (pP->iConnected)
   347 				{
   348 				RStressSvr dd;
   349 				dd.SetHandle(pP->iSession.Handle());
   350 				TInt n=Random(seed)&16383;
   351 				for (i=0; i<n && r==KErrNone; i++)
   352 					r=dd.Test();
   353 				}
   354 			TInt ms=(Random(seed)&7)+1;
   355 			User::AfterHighRes(ms*1000);
   356 			}
   357 		}
   358 	}
   359 
   360 CThread::CThread(TInt aPriority)
   361 	: CActive(aPriority)
   362 	{
   363 	}
   364 
   365 CThread::~CThread()
   366 	{
   367 	Cancel();
   368 	iThread.Kill(0);
   369 	iThread.Close();
   370 	}
   371 
   372 _LIT(KLitKernExec,"KERN-EXEC");
   373 void CThread::RunL()
   374 	{
   375 	TExitType exitType=iThread.ExitType();
   376 	TInt exitReason=iThread.ExitReason();
   377 	TBuf<32> exitCat=iThread.ExitCategory();
   378 	TBool bad=EFalse;
   379 	if (exitType==EExitKill)
   380 		{
   381 		if (exitReason!=KErrNone && exitReason!=KErrServerTerminated)
   382 			bad=ETrue;
   383 		}
   384 	else if (exitType==EExitPanic)
   385 		{
   386 		if (!PanicBadHandleAllowed() || exitCat!=KLitKernExec || exitReason!=EBadHandle)
   387 			bad=ETrue;
   388 		else
   389 			RegisterAllowedPanic();
   390 		}
   391 	if (bad)
   392 		{
   393 		TFullName n(iThread.FullName());
   394 		test.Printf(_L("Thread %S exited %d,%d,%S\n"),&n,exitType,exitReason,&exitCat);
   395 		CActiveScheduler::Stop();
   396 		return;
   397 		}
   398 	Cleanup();
   399 	iThread.Close();
   400 	if (exitType==EExitTerminate)
   401 		++iTerminateCount;
   402 	else if (exitType==EExitKill && exitReason==KErrNone)
   403 		++iExitCount;
   404 	else if (exitReason==KErrServerTerminated)
   405 		++iServerTerminatedCount;
   406 	TInt r=Start();
   407 	if (r!=KErrNone)
   408 		{
   409 		test.Printf(_L("Start thread error %d\n"),r);
   410 		CActiveScheduler::Stop();
   411 		}
   412 	}
   413 
   414 void CThread::DoCancel()
   415 	{
   416 	iThread.LogonCancel(iStatus);
   417 	}
   418 
   419 const TInt KThreadStartAttempts=3;
   420 TInt CThread::Start()
   421 	{
   422 	TInt r=KErrNone;
   423 	TInt n=KThreadStartAttempts;
   424 	while(n--)
   425 		{
   426 		r=StartThread();
   427 		if (r==KErrNone)
   428 			break;
   429 		if (r!=KErrAlreadyExists)
   430 			break;
   431 		User::After(100000);
   432 		}
   433 	if (r==KErrNone)
   434 		{
   435 		iThread.Logon(iStatus);
   436 		SetActive();
   437 		}
   438 	return ProcessStartError(r);
   439 	}
   440 
   441 TBool CThread::PanicBadHandleAllowed()
   442 	{
   443 	return EFalse;
   444 	}
   445 
   446 void CThread::RegisterAllowedPanic()
   447 	{
   448 	}
   449 
   450 void CThread::Cleanup()
   451 	{
   452 	}
   453 
   454 TInt CThread::ProcessStartError(TInt anError)
   455 	{
   456 	return anError;
   457 	}
   458 
   459 CServerThread::CServerThread()
   460 	: CThread(0)
   461 	{
   462 	}
   463 
   464 TInt CServerThread::StartThread()
   465 	{
   466 	TUint seed[2];
   467 	seed[1]=0;
   468 	seed[0]=User::TickCount();
   469 	TInt heapMin=TInt(Random(seed)&0x0f)+1;
   470 	heapMin<<=12;
   471 	TInt r=iThread.Create(KNullDesC(),ServerThread,KStackSize,heapMin,KHeapMaxSize,this);	// use unnamed thread
   472 	if (r!=KErrNone)
   473 		return r;
   474 	iThread.Resume();
   475 	return KErrNone;
   476 	}
   477 
   478 void CServerThread::NewL()
   479 	{
   480 	CServerThread* pT=new (ELeave) CServerThread;
   481 	TheServer=pT;
   482 	CActiveScheduler::Add(pT);
   483 	User::LeaveIfError(pT->Start());
   484 	}
   485 
   486 void CServerThread::DisplayStats()
   487 	{
   488 	test.Printf(_L("Svr  : X:%9d ST:%9d T:%9d RX:%9d\n"),iExitCount,iServerTerminatedCount,iTerminateCount,iMessagesReceived);
   489 	}
   490 
   491 CClientThread::CClientThread(TInt anId)
   492 	: CThread(0), iId(anId)
   493 	{
   494 	}
   495 
   496 TInt CClientThread::StartThread()
   497 	{
   498 	TInt r=iThread.Create(KNullDesC(),ClientThread,KStackSize,NULL,this);	// use unnamed threads
   499 	if (r!=KErrNone)
   500 		return r;
   501 	iSession.SetHandle(0);
   502 	iThread.Resume();
   503 	return KErrNone;
   504 	}
   505 
   506 void CClientThread::NewL(TInt anId, TInt aPrimaryId)
   507 	{
   508 	CClientThread* pT=new (ELeave) CClientThread(anId);
   509 	TheClients[anId]=pT;
   510 	pT->iPrimary=TheClients[aPrimaryId];
   511 	CActiveScheduler::Add(pT);
   512 	User::LeaveIfError(pT->Start());
   513 	}
   514 
   515 void CClientThread::DisplayStats()
   516 	{
   517 	test.Printf(_L("Cli %1d: X:%9d ST:%9d T:%9d CL:%9d\n"),iId,iExitCount,iServerTerminatedCount,iTerminateCount,iCloses);
   518 	}
   519 
   520 TBool CClientThread::PanicBadHandleAllowed()
   521 	{
   522 	return (iPrimary!=this);
   523 	}
   524 
   525 void CClientThread::RegisterAllowedPanic()
   526 	{
   527 	++iCloses;
   528 	}
   529 
   530 void CClientThread::Cleanup()
   531 	{
   532 	TInt r=KErrNone;
   533 	if (iPrimary==this)
   534 		{
   535 		if (!IsLocalHandle(iSession.Handle()))	// don't close if not shared yet
   536 			iSession.Close();
   537 		CClientThread* pS1=TheClients[iId+1];
   538 		CClientThread* pS2=TheClients[iId+2];
   539 		if (pS1->iWaitingToRestart)
   540 			r=pS1->Start();
   541 		if (r==KErrNone && pS2->iWaitingToRestart)
   542 			r=pS2->Start();
   543 		if (r!=KErrNone)
   544 			{
   545 			test.Printf(_L("Start thread error %d\n"),r);
   546 			CActiveScheduler::Stop();
   547 			}
   548 		}
   549 	}
   550 
   551 TInt CClientThread::ProcessStartError(TInt anError)
   552 	{
   553 	if (anError==KErrAlreadyExists && iPrimary!=this && !iWaitingToRestart)
   554 		{
   555 		iWaitingToRestart=ETrue;
   556 		return KErrNone;
   557 		}
   558 	iWaitingToRestart=EFalse;
   559 	return anError;
   560 	}
   561 
   562 void CRandomTimer::NewL()
   563 	{
   564 	CRandomTimer* pR=new (ELeave) CRandomTimer(20);
   565 	User::LeaveIfError(pR->iTimer.CreateLocal());
   566 	CActiveScheduler::Add(pR);
   567 	TheRandomTimer=pR;
   568 	pR->Start();
   569 	}
   570 
   571 CRandomTimer::CRandomTimer(TInt aPriority)
   572 	: CActive(aPriority)
   573 	{
   574 	iSeed[0]=User::TickCount();
   575 	}
   576 
   577 CRandomTimer::~CRandomTimer()
   578 	{
   579 	Cancel();
   580 	iTimer.Close();
   581 	}
   582 
   583 void CRandomTimer::RunL()
   584 	{
   585 	++iCount;
   586 	TUint x=Random(iSeed)&15;
   587 	CThread* pT=NULL;
   588 	if (x==0)
   589 		pT=TheServer;
   590 	else if (x<10)
   591 		{
   592 		pT=TheClients[x-1];
   593 		if (((CClientThread*)pT)->iWaitingToRestart)
   594 			pT=NULL;
   595 		}
   596 	if (pT)
   597 		pT->iThread.Kill(0);
   598 	Start();
   599 	}
   600 
   601 void CRandomTimer::Start()
   602 	{
   603 	TUint x=Random(iSeed)&63;
   604 	x+=64;
   605 	iTimer.HighRes(iStatus, x*1000);
   606 	SetActive();
   607 	}
   608 
   609 void CRandomTimer::DoCancel()
   610 	{
   611 	iTimer.Cancel();
   612 	}
   613 
   614 void CStatsTimer::NewL()
   615 	{
   616 	CStatsTimer* pT=new (ELeave) CStatsTimer(-10);
   617 	User::LeaveIfError(pT->iTimer.CreateLocal());
   618 	CActiveScheduler::Add(pT);
   619 	pT->Start();
   620 	}
   621 
   622 CStatsTimer::CStatsTimer(TInt aPriority)
   623 	: CActive(aPriority)
   624 	{
   625 	iInitFreeRam = FreeRam();
   626 	}
   627 
   628 CStatsTimer::~CStatsTimer()
   629 	{
   630 	Cancel();
   631 	iTimer.Close();
   632 	}
   633 
   634 void CStatsTimer::RunL()
   635 	{
   636 	TheServer->DisplayStats();
   637 	TInt i;
   638 	for (i=0; i<KNumClients; i++)
   639 		TheClients[i]->DisplayStats();
   640 	test.Printf(_L("RndTm: %9d\n"),TheRandomTimer->iCount);
   641 	TInt free_ram = FreeRam();
   642 	TInt delta_ram = iInitFreeRam - free_ram;
   643 	if (delta_ram > iMaxDelta)
   644 		iMaxDelta = delta_ram;
   645 	if (++iCount==10)
   646 		{
   647 		test.Printf(_L("Max RAM delta %dK Free RAM %08x\n"), iMaxDelta/1024, free_ram);
   648 		iCount=0;
   649 		}
   650 	Start();
   651 	}
   652 
   653 void CStatsTimer::Start()
   654 	{
   655 	iTimer.After(iStatus, 1000000);
   656 	SetActive();
   657 	}
   658 
   659 void CStatsTimer::DoCancel()
   660 	{
   661 	iTimer.Cancel();
   662 	}
   663 
   664 void InitialiseL()
   665 	{
   666 	CActiveScheduler* pA=new (ELeave) CActiveScheduler;
   667 	CActiveScheduler::Install(pA);
   668 	CServerThread::NewL();
   669 	TInt p;
   670 	TInt s;
   671 	TInt id=0;
   672 	for (p=0; p<KNumClients; p+=KNumSecondariesPerPrimary)
   673 		{
   674 		for (s=0; s<KNumSecondariesPerPrimary; s++)
   675 			{
   676 			CClientThread::NewL(id,p);
   677 			id++;
   678 			}
   679 		}
   680 	CRandomTimer::NewL();
   681 	CStatsTimer::NewL();
   682 	}
   683 
   684 GLDEF_C TInt E32Main()
   685 //
   686 // Test timers.
   687 //
   688 	{
   689 
   690 	test.Title();
   691 
   692 	User::SetCritical(User::ESystemCritical);
   693 	RThread().SetPriority(EPriorityMore);
   694 	User::SetJustInTime(EFalse);	// prevent the debugger picking up expected thread panics.
   695 
   696 	TRAPD(r,InitialiseL());
   697 	test(r==KErrNone);
   698 
   699 	CActiveScheduler::Start();
   700 
   701 	test(0);
   702 
   703 	return(0);
   704 	}
   705 
   706 // Override heap creation for this process
   707 // This function runs at the beginning of every thread
   708 // Initial heap is shared but subsequent heaps are single threaded
   709 TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
   710 	{
   711 	TInt r = KErrNone;
   712 	if (!aInfo.iAllocator && aInfo.iHeapInitialSize>0)
   713 		{
   714 		// new heap required
   715 		RHeap* pH = NULL;
   716 		r = CreateThreadHeap(aInfo, pH, 0, aNotFirst);
   717 		}
   718 	else if (aInfo.iAllocator)
   719 		{
   720 		// sharing a heap
   721 		RAllocator* pA = aInfo.iAllocator;
   722 		pA->Open();
   723 		User::SwitchAllocator(pA);
   724 		}
   725 	return r;
   726 	}
   727