diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/mmu/t_shbuf_perfserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/t_shbuf_perfserver.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,837 @@ +// Copyright (c) 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: +// t_shbuf_perfserver.cpp +// +// + +/** + * @file + * + * Test server used for Performance Testing of shared buffers. + */ + +#include +#include +#include +#include + +#include "t_shbuf_perfserver.h" + + +/** + * Second phase constructor for sessions. Called by the CServer2 framework + * when a session is created (e.g. a connection is made to the server). + */ +void CShBufTestServerSession::CreateL() + { + Server().AddSessionL(this); + } // CShBufTestServerSession::CreateL() + + +/** + * Destructor for session classes. When this is called it indicates that + * a session is closing its connection with the server. + */ +CShBufTestServerSession::~CShBufTestServerSession() + { + Server().DropSession(this); + } // CShBufTestServerSession::~CShBufTestServerSession() + + +/** + * Handle message requests for this session. Leaving is handled by + * CShBufTestServer::RunError() which reports the error code to the client. + * + * @param aMessage RMessage2 reference which encapsulates a client request. + */ +void CShBufTestServerSession::ServiceL(const RMessage2& aMessage) + + { + switch (aMessage.Function()) + { + case EShBufServerShutdownServer: + { + ShutdownServerL(aMessage); + } + break; + + case EShBufServerFromTPtr8ProcessAndReturn: + { + FromTPtr8ProcessAndReturnL(aMessage); + } + break; + + case EShBufServerFromTPtr8ProcessAndRelease: + { + FromTPtr8ProcessAndReleaseL(aMessage); + } + break; + + case EShBufServerOpenRShBufPool: + { + OpenRShBufPoolL(aMessage); + } + break; + + case EShBufServerCloseRShBufPool: + { + CloseRShBufPoolL(aMessage); + } + break; + + case EShBufServerFromRShBufProcessAndReturn: + { + FromRShBufProcessAndReturnL(aMessage); + } + break; + + case EShBufServerFromRShBufProcessAndRelease: + { + FromRShBufProcessAndReleaseL(aMessage); + } + break; + + case EShBufServerDbgMarkHeap: + { + DbgMarkHeapL(aMessage); + } + break; + + case EShBufServerDbgCheckHeap: + { + DbgCheckHeapL(aMessage); + } + break; + + case EShBufServerDbgMarkEnd: + { + DbgMarkEndL(aMessage); + } + break; + + case EShBufServerDbgFailNext: + { + DbgFailNextL(aMessage); + } + break; + + default: + { + aMessage.Panic(KRShBufTestServerName, 999); + } + break; + } + } // CShBufTestServerSession::ServiceL() + + +/** + * Completes a client request. This function provides a single point of + * message completion which benefits debugging and maintenance. + * + * @param aMessage The RMessage2 client request. + * @param aResult Result of the request. + */ +void CShBufTestServerSession::CompleteRequest(const RMessage2& aMessage, + TInt aResult) const + { + if (aMessage.IsNull() == EFalse) + { + aMessage.Complete(aResult); + } + } // CShBufTestServerSession::CompleteRequest() + + +/** + * Takes a buffer from the client, sends to the driver and back to the client. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::FromTPtr8ProcessAndReturnL(const RMessage2& aMessage) + { + // + // Read the client buffer... + // + TPtr8 bufPtr(iSessionTempBuffer, sizeof(iSessionTempBuffer)); + + aMessage.ReadL(0, bufPtr); + + TUint bufSize; + + bufSize = aMessage.Int1(); + + // + // Pass to the server to pass to the driver and back... + // + TInt result; + + result = Server().FromTPtr8ProcessAndReturn(bufPtr, bufSize); + + // + // Write the client buffer back... + // + aMessage.WriteL(0, bufPtr); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::FromTPtr8ProcessAndReturnL + + +/** + * Takes a buffer from the client and sends to the driver. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::FromTPtr8ProcessAndReleaseL(const RMessage2& aMessage) + { + // + // Read the client buffer... + // + TPtr8 bufPtr(iSessionTempBuffer, sizeof(iSessionTempBuffer)); + + aMessage.ReadL(0, bufPtr); + + // + // Pass to the server to pass to the driver and back... + // + TInt result; + + result = Server().FromTPtr8ProcessAndRelease(bufPtr); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::FromTPtr8ProcessAndReleaseL + + +/** + * Allows the client to ask the test server to open a buffer pool. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::OpenRShBufPoolL(const RMessage2& aMessage) + { + // + // Read the handle... + // + TInt poolHandle = aMessage.Int0(); + + // + // Read the pool info... + // + TShPoolInfo shPoolInfo; + TPckg shPoolInfoPckg(shPoolInfo); + + aMessage.ReadL(1, shPoolInfoPckg); + + // + // Pass to the server to open the pool... + // + TInt result = Server().OpenRShBufPool(poolHandle, shPoolInfo); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::OpenRShBufPoolL + + +/** + * Allows the client to ask the test server to close a buffer pool. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::CloseRShBufPoolL(const RMessage2& aMessage) + { + // + // Pass to the server to close the pool... + // + TInt result = Server().CloseRShBufPool(); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::CloseRShBufPoolL + + +/** + * Takes a buffer from the client, sends to the driver and back to the client. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::FromRShBufProcessAndReturnL(const RMessage2& aMessage) + { + // + // Read the client handle buffer... + // + RShBuf shBuf; + TUint bufSize; + + bufSize = aMessage.Int1(); + + // + // Pass to the server to pass to the driver and back... + // + TInt result; + + result = Server().FromRShBufProcessAndReturn(shBuf, bufSize); + + // + // Write the client buffer handle back... + // +#ifdef CAN_TRANSFER_SHBUF_TO_ANOTHER_PROCESS + // TDBD aMessage.Complete(shbuf->Handle()); +#else + TPckg handlePckg(shBuf.Handle()); + aMessage.WriteL(0, handlePckg); +#endif + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::FromRShBufProcessAndReturnL + + +/** + * Takes a buffer from the client and sends to the driver. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::FromRShBufProcessAndReleaseL(const RMessage2& aMessage) + { + // + // Read the client buffer handle... + // + + RShBuf shBuf; + +#ifdef CAN_TRANSFER_SHBUF_TO_ANOTHER_PROCESS + // TBD RShBuf.Open(aMessage, 0); +#else + shBuf.SetReturnedHandle(aMessage.Int0()); +#endif + + // + // Pass to the server to pass to the driver and back... + // + TInt result; + + result = Server().FromRShBufProcessAndRelease(shBuf); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::FromRShBufProcessAndReleaseL + + +/** + * Requests the server to mark the start of checking the server's heap. + * This function only works in debug releases and is a synchronous request + * which will be completed when the procedure returns. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::DbgMarkHeapL(const RMessage2& aMessage) + { + TInt result; + + result = Server().DbgMarkHeap(); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::DbgMarkHeapL() + + +/** + * Requests the server to check that the number of allocated cells at the + * current nested level on the server's heap is the same as the specified value. + * This function only works for debug builds and is a synchronous request + * which will be completed when the procedure returns. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::DbgCheckHeapL(const RMessage2& aMessage) + { + TInt count = aMessage.Int0(); + TInt result; + + result = Server().DbgCheckHeap(count); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::DbgCheckHeapL() + + +/** + * Requests the server to mark the end of checking the server's heap. This + * function must match an earlier call to DbgMarkHeap() and only functions + * on debug releases. This is a synchronous request which will be completed + * when the procedure returns. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::DbgMarkEndL(const RMessage2& aMessage) + { + TInt count = aMessage.Int0(); + TInt result; + + result = Server().DbgMarkEnd(count); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::DbgMarkEndL() + + +/** + * Simulates heap allocation failure for the sever. The failure occurs on + * the next call to new or any of the functions which allocate memory from + * the heap. This is defined only for debug builds and is a synchronous + * request which will be completed when the procedure returns. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::DbgFailNextL(const RMessage2& aMessage) + { + TInt count = aMessage.Int0(); + TInt result; + + result = Server().DbgFailNext(count); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::DbgFailNextL() + + +/** + * Requests the server to shut down when it no longer has any connected + * sessions. This procedure is only premitted in debug builds for security + * reasons (e.g. to prevent a denial of service attack) and is provided + * for testing purposes. This is a synchronous request which will be + * completed when the procedure returns. The server will shutdown when the + * last session disconnects. + * + * @param aMessage RMessage2 client request. + */ +void CShBufTestServerSession::ShutdownServerL(const RMessage2& aMessage) + { + TInt result = Server().ShutdownServer(); + + // + // Complete the request... + // + CompleteRequest(aMessage, result); + } // CShBufTestServerSession::ShutdownServerL() + + +/** + * Static factory method used to create a CShBufTestServer object. + * + * @return Pointer to the created CShBufTestServer object, or NULL. + */ +CShBufTestServer* CShBufTestServer::NewL() + { + CShBufTestServer* self = new (ELeave) CShBufTestServer(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } // CShBufTestServer::NewL + + +/** + * Standard constructor. + */ +CShBufTestServer::CShBufTestServer() + : CServer2(EPriorityNormal), + iShouldShutdownServer(EFalse) + { + __DECLARE_NAME(_L("CShBufTestServer")); + } // CShBufTestServer::CShBufTestServer + + +/** + * Second phase constructor. Ensures the server is created and ready to run. + */ +void CShBufTestServer::ConstructL() + { + // + // Open the driver... + // + TInt ret; + + ret = User::LoadLogicalDevice(_L("D_SHBUF_CLIENT.LDD")); + if (ret != KErrAlreadyExists) + { + User::LeaveIfError(ret); + } + + ret = User::LoadLogicalDevice(_L("D_SHBUF_OWN.LDD")); + if (ret != KErrAlreadyExists) + { + User::LeaveIfError(ret); + } + + User::LeaveIfError(iShBufLdd.Open(RShBufTestChannel::EClientThread)); + + StartL(KRShBufTestServerName); + } // CShBufTestServer::ConstructL + + +/** + * Destructor. + */ +CShBufTestServer::~CShBufTestServer() + { + iSessionArray.Reset(); + iShBufLdd.Close(); + } // CShBufTestServer::~CShBufTestServer + + +/** + * Create a new client session. + */ +CSession2* CShBufTestServer::NewSessionL(const TVersion&, const RMessage2& /*aMessage*/) const + { + return new(ELeave) CShBufTestServerSession(); + } // CShBufTestServer::NewSessionL + + +/** + * Called by the session class when it is being created. + * + * @param aSession Server side session. + */ +void CShBufTestServer::AddSessionL(CShBufTestServerSession* aSession) + { + // + // Store this session in the list of sessions... + // + iSessionArray.Append(aSession); + } // CShBufTestServer::AddSessionL + + +/** + * Called by the session class when it is being destroyed. + * + * @param aSession Server side session. + */ +void CShBufTestServer::DropSession(CShBufTestServerSession* aSession) + { + // + // Remove this session from the session array list... + // + TInt position; + + position = iSessionArray.Find(aSession); + if (position != KErrNotFound) + { + iSessionArray.Remove(position); + } + + // + // If we are shuting down then unconfigure and stop... + // + if (iSessionArray.Count() == 0 && iShouldShutdownServer) + { + CActiveScheduler::Stop(); + } + } // CShBufTestServer::DropSession + + +TInt CShBufTestServer::FromTPtr8ProcessAndReturn(TDes8& aBuf, TUint aBufSize) + { + // clear cache + memset(iClearCache, 0xFF, sizeof(iClearCache)); + + return iShBufLdd.FromTPtr8ProcessAndReturn(aBuf, aBufSize); + } // CShBufTestServer::FromTPtr8ProcessAndReturn + + +TInt CShBufTestServer::FromTPtr8ProcessAndRelease(TDes8& aBuf) + { + return iShBufLdd.FromTPtr8ProcessAndRelease(aBuf); + } // CShBufTestServer::FromTPtr8ProcessAndRelease + + +TInt CShBufTestServer::OpenRShBufPool(TInt aHandle, const TShPoolInfo& aPoolInfo) + { + return iShBufLdd.OpenUserPool(aHandle, aPoolInfo); + } // CShBufTestServer::OpenRShBufPool + + +TInt CShBufTestServer::CloseRShBufPool() + { + return iShBufLdd.CloseUserPool(); + } // CShBufTestServer::CloseRShBufPool + + +TInt CShBufTestServer::FromRShBufProcessAndReturn(RShBuf& aShBuf, TUint aBufSize) + { + TInt ret; + + // clear cache + memset(iClearCache, 0xFF, sizeof(iClearCache)); + + ret = iShBufLdd.FromRShBufProcessAndReturn(aBufSize); + + if (ret > 0) + { + aShBuf.SetReturnedHandle(ret); + return KErrNone; + } + + return ret; + } // CShBufTestServer::FromRShBufProcessAndReturn + + +TInt CShBufTestServer::FromRShBufProcessAndRelease(RShBuf& aShBuf) + { + return iShBufLdd.FromRShBufProcessAndRelease(aShBuf.Handle()); + } // CShBufTestServer::FromRShBufProcessAndRelease + + +/** + * Marks the start of checking the server's heap. This function only works + * in debug releases. + * + * Calls to this function can be nested but each call must be matched by + * corresponding DbgMarkEnd(). + * + * @return KErrNone. + */ +TInt CShBufTestServer::DbgMarkHeap() const + { +#ifdef _DEBUG + __UHEAP_MARK; +#endif + + return(KErrNone); + } // CShBufTestServer::DbgMarkHeap + + +/** + * Checks that the number of allocated cells at the current nested level on + * the server's heap is the same as the specified value. This function only + * works for debug builds. + * + * @param aCount The number of heap cells expected to be allocated at + * the current nest level. + * + * @return KErrNone. + */ +TInt CShBufTestServer::DbgCheckHeap(TInt aCount) const + { +#ifdef _DEBUG + __UHEAP_CHECK(aCount); +#else + (void) aCount; +#endif + + return(KErrNone); + } // CShBufTestServer::DbgCheckHeap + + +/** + * Marks the end of checking the current server's heap. + * + * The function expects aCount heap cells to remain allocated at the + * current nest level. This function must match an earlier call to + * DbgMarkHeap() and only functions on debug releases. + * + * @param aCount The number of heap cells expected to remain allocated + * at the current nest level. + * + * @return KErrNone. + */ +TInt CShBufTestServer::DbgMarkEnd(TInt aCount) const + { +#ifdef _DEBUG + __UHEAP_MARKENDC(aCount); +#else + (void) aCount; +#endif + + return(KErrNone); + } // CShBufTestServer::DbgMarkEnd + + +/** + * Simulates heap allocation failure for the server. + * + * The failure occurs on the next call to new or any of the functions which + * allocate memory from the heap. This is defined only for debug builds. + * + * @param aCount Determines when the allocation will fail. + * + * @return KErrNone. + */ +TInt CShBufTestServer::DbgFailNext(TInt aCount) const + { +#ifdef _DEBUG + if (aCount == 0) + { + __UHEAP_RESET; + } + else + { + __UHEAP_FAILNEXT(aCount); + } +#else + (void) aCount; +#endif + + return(KErrNone); + } // CShBufTestServer::DbgFailNext + + +/** + * Requests the server to shut down when it no longer has any connected + * sessions. This procedure is only premitted in debug builds and is provided + * for testing purposes. + * + * The server will shutdown when the last session disconnects. + * + * @return KErrNone if the shutdown request was accepted, otherwise returns + * an error. + */ +TInt CShBufTestServer::ShutdownServer() + { + iShouldShutdownServer = ETrue; + + return(KErrNone); + } // CShBufTestServer::ShutdownServer + + + +/** + * Standard Active Object RunError() method, called when the RunL() method + * leaves, which will be when the CShBufTestServerSession::ServiceL() leaves. + * + * Find the current message and complete it before restarting the server. + * + * @param aError Leave code from CShBufTestServerSession::ServiceL(). + * + * @return KErrNone + */ +TInt CShBufTestServer::RunError(TInt aError) + { + // + // Complete the request with the available error code. + // + if (Message().IsNull() == EFalse) + { + Message().Complete(aError); + } + + // + // The leave will result in an early return from CServer::RunL(), skipping + // the call to request another message. So do that now in order to keep the + // server running. + // + ReStart(); + + return KErrNone; + } // CShBufTestServer::RunError + + +/** + * Perform all server initialisation, in particular creation of the + * scheduler and server and then run the scheduler. + */ +static void RunServerL() + { + // + // Naming the server thread after the server helps to debug panics. + // + User::LeaveIfError(User::RenameThread(KRShBufTestServerName)); + + // + // Increase priority so that requests are handled promptly... + // + RThread().SetPriority(EPriorityMuchMore); + + // + // Create a new Active Scheduler... + // + CActiveScheduler* scheduler = new CActiveScheduler(); + CleanupStack::PushL(scheduler); + CActiveScheduler::Install(scheduler); + + // + // Create a new PhoneBookServer... + // + CShBufTestServer* server = CShBufTestServer::NewL(); + CleanupStack::PushL(server); + + // + // Initialisation complete, now signal the client thread... + // +#ifdef CAN_TRANSFER_SHBUF_TO_ANOTHER_PROCESS + RProcess::Rendezvous(KErrNone); +#else + RThread::Rendezvous(KErrNone); +#endif + + // + // Run the server... + // + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(2, scheduler); + } // RunServerL + + +/** + * Server process entry-point. + * + * @return KErrNone or a standard Symbian error code. + */ +#ifdef CAN_TRANSFER_SHBUF_TO_ANOTHER_PROCESS +TInt E32Main() +#else +TInt RShBufTestServerThread(TAny* /*aPtr*/) +#endif + { + __UHEAP_MARK; + + CTrapCleanup* cleanup = CTrapCleanup::New(); + TInt ret(KErrNoMemory); + + if (cleanup) + { + TRAP(ret, RunServerL()); + delete cleanup; + } + + __UHEAP_MARKEND; + + return ret; + } // E32Main + + +