diff -r 000000000000 -r a41df078684a kerneltest/e32test/misc/t_svr6.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/misc/t_svr6.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,727 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\misc\t_svr6.cpp +// +// + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include +#include "u32std.h" +#include "../misc/prbs.h" +#include "../mmu/freeram.h" + +const TInt KStackSize=0x1000; +const TInt KHeapMaxSize=0x100000; +const TInt KMajorVersionNumber=1; +const TInt KMinorVersionNumber=0; +const TInt KBuildVersionNumber=1; +const TInt KNumMessageSlots=10; + +_LIT(KServerName,"StressSvr"); + +LOCAL_D RTest test(_L("T_SVR6")); + +class CMySession : public CSession2 + { +public: + CMySession(); + virtual void ServiceL(const RMessage2& aMessage); //pure virtual fns. + void Process(const RMessage2& aMessage); +public: + TInt iOutstanding; + TUint iSeed[2]; + }; + +class CMyServer : public CServer2 + { +public: + enum {ETest}; +public: + CMyServer(TInt aPriority); + static CMyServer* New(TInt aPriority); + virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2&) const;//Overloading + }; + +class CMyActiveScheduler : public CActiveScheduler + { +public: + virtual void Error(TInt anError) const; //Overloading pure virtual function + }; + +class RStressSvr : public RSessionBase + { +public: + TInt Connect(); + TInt Test(); + void Test(TRequestStatus& aStatus); + TVersion Version(); + }; + +class CThread : public CActive + { +public: + CThread(TInt aPriority); + ~CThread(); + virtual void RunL(); + virtual void DoCancel(); + virtual void DisplayStats()=0; + virtual TBool PanicBadHandleAllowed(); + virtual void RegisterAllowedPanic(); + virtual void Cleanup(); + virtual TInt ProcessStartError(TInt anError); + TInt Start(); +public: + virtual TInt StartThread()=0; +public: + RThread iThread; + TInt iExitCount; + TInt iServerTerminatedCount; + TInt iTerminateCount; + }; + +class CServerThread : public CThread + { +public: + static void NewL(); + CServerThread(); + virtual TInt StartThread(); + virtual void DisplayStats(); +public: + TInt iMessagesReceived; + }; + +class CClientThread : public CThread + { +public: + static void NewL(TInt anId, TInt aPrimaryId); + CClientThread(TInt anId); + virtual TInt StartThread(); + virtual void DisplayStats(); + virtual TBool PanicBadHandleAllowed(); + virtual void RegisterAllowedPanic(); + virtual void Cleanup(); + virtual TInt ProcessStartError(TInt anError); +public: + TInt iId; + TInt iCloses; + CClientThread* iPrimary; + RStressSvr iSession; + TBool iConnected; + TBool iWaitingToRestart; + }; + +class CRandomTimer : public CActive + { +public: + static void NewL(); + CRandomTimer(TInt aPriority); + ~CRandomTimer(); + virtual void RunL(); + virtual void DoCancel(); + void Start(); +public: + RTimer iTimer; + TUint iSeed[2]; + TInt iCount; + }; + +class CStatsTimer : public CActive + { +public: + static void NewL(); + CStatsTimer(TInt aPriority); + ~CStatsTimer(); + virtual void RunL(); + virtual void DoCancel(); + void Start(); +public: + RTimer iTimer; + TInt iInitFreeRam; + TInt iMaxDelta; + TInt iCount; + }; + +const TInt KNumPrimaryClients=3; +const TInt KNumSecondariesPerPrimary=3; +const TInt KNumClients=KNumPrimaryClients*KNumSecondariesPerPrimary; +LOCAL_D CServerThread* TheServer; +LOCAL_D CClientThread* TheClients[KNumClients]; +LOCAL_D CRandomTimer* TheRandomTimer; + +CMySession::CMySession() +// +// Constructor +// + { + iSeed[0]=User::TickCount(); + } + +CMyServer* CMyServer::New(TInt aPriority) +// +// Create a new CMyServer. +// + { + + return new CMyServer(aPriority); + } + +CMyServer::CMyServer(TInt aPriority) +// +// Constructor. +// + : CServer2(aPriority, ESharableSessions) + {} + +CSession2* CMyServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const +// +// Create a new client for this server. +// + { + + TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + if (!User::QueryVersionSupported(v,aVersion)) + User::Leave(KErrNotSupported); + return new(ELeave) CMySession; + } + +void CMySession::ServiceL(const RMessage2& aMessage) +// +// Handle messages for this server. +// + { + + ++TheServer->iMessagesReceived; + switch (aMessage.Function()) + { + case CMyServer::ETest: + if (iOutstanding==KNumMessageSlots-1) + Process(aMessage); + else + ++iOutstanding; + break; + default: + aMessage.Complete(KErrNotSupported); + break; + } + } + +void CMySession::Process(const RMessage2& aMessage) + { + TUint x=Random(iSeed)&16383; + if (x==0) + User::Exit(0); // exit the server + else if (x<8) + aMessage.Terminate(0); // terminate the client + else + aMessage.Complete(KErrNone); + } + +void CMyActiveScheduler::Error(TInt anError) const +// +// Called if any Run() method leaves. +// + { + + User::Panic(_L("Server Error"),anError); + } + +TInt RStressSvr::Connect() +// +// Connect to the server +// + { + + TInt r=CreateSession(KServerName,Version(),KNumMessageSlots); + if (r==KErrNone) + r=ShareAuto(); + return r; + } + +TInt RStressSvr::Test() +// +// Send a message and wait for completion. +// + { + + return SendReceive(CMyServer::ETest); + } + +void RStressSvr::Test(TRequestStatus& aStatus) +// +// Send a message asynchronously +// + { + + SendReceive(CMyServer::ETest,aStatus); + } + +TVersion RStressSvr::Version() +// +// Return the current version. +// + { + + TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + return(v); + } + +LOCAL_C TInt ServerThread(TAny*) + { + + CMyActiveScheduler* pR=new CMyActiveScheduler; + if (!pR) + return KErrNoMemory; + CActiveScheduler::Install(pR); + CMyServer* pS=CMyServer::New(0); + if (!pS) + return KErrNoMemory; + TInt r=pS->Start(KServerName); + if (r!=KErrNone) + return r; + + CActiveScheduler::Start(); + + delete pS; + delete pR; + return KErrNone; + } + +LOCAL_C TInt ClientThread(TAny* aPtr) + { + CClientThread* pT=(CClientThread*)aPtr; + CClientThread* pP=pT->iPrimary; + TBool primary=(pP==pT); + RStressSvr& d=pP->iSession; + TUint seed[2]; + seed[0]=User::TickCount(); + seed[1]=0; + TInt r=KErrNone; + TInt i; + if (primary) + { + FOREVER + { + FOREVER + { + r=d.Connect(); + if (r!=KErrNotFound) + break; + User::After(50000); + } + if (r!=KErrNone) + return r; + pT->iConnected=ETrue; + TRequestStatus s[KNumMessageSlots]; + for (i=0; iiConnected=EFalse; + d.Close(); + ++pT->iCloses; + } + } + else + { + TRequestStatus s[KNumMessageSlots]; + for (i=0; iiConnected) + { + RStressSvr dd; + dd.SetHandle(pP->iSession.Handle()); + TInt n=Random(seed)&16383; + for (i=0; i exitCat=iThread.ExitCategory(); + TBool bad=EFalse; + if (exitType==EExitKill) + { + if (exitReason!=KErrNone && exitReason!=KErrServerTerminated) + bad=ETrue; + } + else if (exitType==EExitPanic) + { + if (!PanicBadHandleAllowed() || exitCat!=KLitKernExec || exitReason!=EBadHandle) + bad=ETrue; + else + RegisterAllowedPanic(); + } + if (bad) + { + TFullName n(iThread.FullName()); + test.Printf(_L("Thread %S exited %d,%d,%S\n"),&n,exitType,exitReason,&exitCat); + CActiveScheduler::Stop(); + return; + } + Cleanup(); + iThread.Close(); + if (exitType==EExitTerminate) + ++iTerminateCount; + else if (exitType==EExitKill && exitReason==KErrNone) + ++iExitCount; + else if (exitReason==KErrServerTerminated) + ++iServerTerminatedCount; + TInt r=Start(); + if (r!=KErrNone) + { + test.Printf(_L("Start thread error %d\n"),r); + CActiveScheduler::Stop(); + } + } + +void CThread::DoCancel() + { + iThread.LogonCancel(iStatus); + } + +const TInt KThreadStartAttempts=3; +TInt CThread::Start() + { + TInt r=KErrNone; + TInt n=KThreadStartAttempts; + while(n--) + { + r=StartThread(); + if (r==KErrNone) + break; + if (r!=KErrAlreadyExists) + break; + User::After(100000); + } + if (r==KErrNone) + { + iThread.Logon(iStatus); + SetActive(); + } + return ProcessStartError(r); + } + +TBool CThread::PanicBadHandleAllowed() + { + return EFalse; + } + +void CThread::RegisterAllowedPanic() + { + } + +void CThread::Cleanup() + { + } + +TInt CThread::ProcessStartError(TInt anError) + { + return anError; + } + +CServerThread::CServerThread() + : CThread(0) + { + } + +TInt CServerThread::StartThread() + { + TUint seed[2]; + seed[1]=0; + seed[0]=User::TickCount(); + TInt heapMin=TInt(Random(seed)&0x0f)+1; + heapMin<<=12; + TInt r=iThread.Create(KNullDesC(),ServerThread,KStackSize,heapMin,KHeapMaxSize,this); // use unnamed thread + if (r!=KErrNone) + return r; + iThread.Resume(); + return KErrNone; + } + +void CServerThread::NewL() + { + CServerThread* pT=new (ELeave) CServerThread; + TheServer=pT; + CActiveScheduler::Add(pT); + User::LeaveIfError(pT->Start()); + } + +void CServerThread::DisplayStats() + { + test.Printf(_L("Svr : X:%9d ST:%9d T:%9d RX:%9d\n"),iExitCount,iServerTerminatedCount,iTerminateCount,iMessagesReceived); + } + +CClientThread::CClientThread(TInt anId) + : CThread(0), iId(anId) + { + } + +TInt CClientThread::StartThread() + { + TInt r=iThread.Create(KNullDesC(),ClientThread,KStackSize,NULL,this); // use unnamed threads + if (r!=KErrNone) + return r; + iSession.SetHandle(0); + iThread.Resume(); + return KErrNone; + } + +void CClientThread::NewL(TInt anId, TInt aPrimaryId) + { + CClientThread* pT=new (ELeave) CClientThread(anId); + TheClients[anId]=pT; + pT->iPrimary=TheClients[aPrimaryId]; + CActiveScheduler::Add(pT); + User::LeaveIfError(pT->Start()); + } + +void CClientThread::DisplayStats() + { + test.Printf(_L("Cli %1d: X:%9d ST:%9d T:%9d CL:%9d\n"),iId,iExitCount,iServerTerminatedCount,iTerminateCount,iCloses); + } + +TBool CClientThread::PanicBadHandleAllowed() + { + return (iPrimary!=this); + } + +void CClientThread::RegisterAllowedPanic() + { + ++iCloses; + } + +void CClientThread::Cleanup() + { + TInt r=KErrNone; + if (iPrimary==this) + { + if (!IsLocalHandle(iSession.Handle())) // don't close if not shared yet + iSession.Close(); + CClientThread* pS1=TheClients[iId+1]; + CClientThread* pS2=TheClients[iId+2]; + if (pS1->iWaitingToRestart) + r=pS1->Start(); + if (r==KErrNone && pS2->iWaitingToRestart) + r=pS2->Start(); + if (r!=KErrNone) + { + test.Printf(_L("Start thread error %d\n"),r); + CActiveScheduler::Stop(); + } + } + } + +TInt CClientThread::ProcessStartError(TInt anError) + { + if (anError==KErrAlreadyExists && iPrimary!=this && !iWaitingToRestart) + { + iWaitingToRestart=ETrue; + return KErrNone; + } + iWaitingToRestart=EFalse; + return anError; + } + +void CRandomTimer::NewL() + { + CRandomTimer* pR=new (ELeave) CRandomTimer(20); + User::LeaveIfError(pR->iTimer.CreateLocal()); + CActiveScheduler::Add(pR); + TheRandomTimer=pR; + pR->Start(); + } + +CRandomTimer::CRandomTimer(TInt aPriority) + : CActive(aPriority) + { + iSeed[0]=User::TickCount(); + } + +CRandomTimer::~CRandomTimer() + { + Cancel(); + iTimer.Close(); + } + +void CRandomTimer::RunL() + { + ++iCount; + TUint x=Random(iSeed)&15; + CThread* pT=NULL; + if (x==0) + pT=TheServer; + else if (x<10) + { + pT=TheClients[x-1]; + if (((CClientThread*)pT)->iWaitingToRestart) + pT=NULL; + } + if (pT) + pT->iThread.Kill(0); + Start(); + } + +void CRandomTimer::Start() + { + TUint x=Random(iSeed)&63; + x+=64; + iTimer.HighRes(iStatus, x*1000); + SetActive(); + } + +void CRandomTimer::DoCancel() + { + iTimer.Cancel(); + } + +void CStatsTimer::NewL() + { + CStatsTimer* pT=new (ELeave) CStatsTimer(-10); + User::LeaveIfError(pT->iTimer.CreateLocal()); + CActiveScheduler::Add(pT); + pT->Start(); + } + +CStatsTimer::CStatsTimer(TInt aPriority) + : CActive(aPriority) + { + iInitFreeRam = FreeRam(); + } + +CStatsTimer::~CStatsTimer() + { + Cancel(); + iTimer.Close(); + } + +void CStatsTimer::RunL() + { + TheServer->DisplayStats(); + TInt i; + for (i=0; iDisplayStats(); + test.Printf(_L("RndTm: %9d\n"),TheRandomTimer->iCount); + TInt free_ram = FreeRam(); + TInt delta_ram = iInitFreeRam - free_ram; + if (delta_ram > iMaxDelta) + iMaxDelta = delta_ram; + if (++iCount==10) + { + test.Printf(_L("Max RAM delta %dK Free RAM %08x\n"), iMaxDelta/1024, free_ram); + iCount=0; + } + Start(); + } + +void CStatsTimer::Start() + { + iTimer.After(iStatus, 1000000); + SetActive(); + } + +void CStatsTimer::DoCancel() + { + iTimer.Cancel(); + } + +void InitialiseL() + { + CActiveScheduler* pA=new (ELeave) CActiveScheduler; + CActiveScheduler::Install(pA); + CServerThread::NewL(); + TInt p; + TInt s; + TInt id=0; + for (p=0; p0) + { + // new heap required + RHeap* pH = NULL; + r = CreateThreadHeap(aInfo, pH, 0, aNotFirst); + } + else if (aInfo.iAllocator) + { + // sharing a heap + RAllocator* pA = aInfo.iAllocator; + pA->Open(); + User::SwitchAllocator(pA); + } + return r; + } +