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