diff -r 185201be11b0 -r 516af714ebb4 perfsrv/analyzetool/kerneleventhandler/src/analyzetooleventhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/perfsrv/analyzetool/kerneleventhandler/src/analyzetooleventhandler.cpp Fri Sep 17 08:38:31 2010 +0300 @@ -0,0 +1,427 @@ +/* +* 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 "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: Definitions for the class DAnalyzeToolEventHandler. +* +*/ + + +// INCLUDE FILES +#include "analyzetooleventhandler.h" +#include + +// CONSTANTS + +// The handler mutex literal +_LIT( KHandlerMutexName, "AnalyzeToolHandlerMutex" ); + +// The handle data mutex literal +_LIT( KDataMutexName, "AnalyzeToolDataMutex" ); + + +// ================= MEMBER FUNCTIONS ========================================= + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::Create() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +TInt DAnalyzeToolEventHandler::Create( DLogicalDevice* aDevice, + const TUint aProcessId ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::Create()" ); + TInt ret( KErrNone ); + + // Store owner process ID + iProcessId = aProcessId; + LOGSTR2( "ATDD DAnalyzeToolEventHandler::Create > iProcessId %d", + iProcessId ); + + // Open the device + ret = aDevice->Open(); + if ( ret != KErrNone ) + return ret; + iDevice = aDevice; + + // Create mutex for the handler + ret = Kern::MutexCreate( iHandlerMutex, KHandlerMutexName, KMutexOrdDebug ); + if ( ret != KErrNone ) + return ret; + // Create mutex for the data + ret = Kern::MutexCreate( iDataMutex, KDataMutexName, KMutexOrdDebug-1 ); + if ( ret != KErrNone ) + return ret; + + // Add handler to the handler queue + return Add(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::~DAnalyzeToolEventHandler()" ); + + CancelInformLibraryEvent(); + + // Close the data mutex + if ( iDataMutex ) + { + iDataMutex->Close( NULL ); + } + + // Close the handler mutex + if ( iHandlerMutex ) + { + iHandlerMutex->Close( NULL ); + } + + // Close the device mutex + if ( iDevice ) + { + iDevice->Close( NULL ); + } + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::EventHandler() +// Function for receiving kernel events +// ----------------------------------------------------------------------------- +// +TUint DAnalyzeToolEventHandler::EventHandler( TKernelEvent aEvent, + TAny* a1, TAny* a2, TAny* aThis ) + { + + // Clarify the event type + switch ( aEvent) + { + case EEventRemoveLibrary: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventRemoveLibrary" ); + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + // Create variable for library information + TLibraryEventInfo info; + // Set as library remove event + info.iEventType = TLibraryEventInfo::ELibraryRemoved; + // Handle the event + handler->HandleLibraryEvent( ( DLibrary* ) a1, ( DThread* ) a2, info ); + break; + } + case EEventAddLibrary: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventAddLibrary" ); + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + // Create variable for library information + TLibraryEventInfo info; + // Set as library remove event + info.iEventType = TLibraryEventInfo::ELibraryAdded; + // Handle the event + handler->HandleLibraryEvent( ( DLibrary* ) a1, ( DThread* ) a2, info ); + break; + } + case EEventHwExc: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventHwExc" ); + break; + } + case EEventSwExc: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventSwExc" ); + break; + } + case EEventRemoveThread: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventRemoveThread" ); + break; + } + case EEventKillThread: + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventHandler() - EEventKillThread" ); + + // Cast the pointer to the handler + DAnalyzeToolEventHandler* handler = + ( ( DAnalyzeToolEventHandler* ) aThis ); + + // Create variable for library information + TLibraryEventInfo info; + + // Set as kill thread event + info.iEventType = TLibraryEventInfo::EKillThread; + // Handle the event + handler->HandleKillThreadEvent( ( DThread* ) a1, info ); + break; + } + default: + { + } + break; + } + return ERunNext; + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::HandleLibraryEvent() +// Handles the EEventAddLibrary and EEventRemoveLibrary events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::HandleLibraryEvent( DLibrary* aLib, + DThread* aThread, TLibraryEventInfo& aInfo ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::HandleLibraryEvent()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + TBool addInfo( EFalse ); + + // Check the library event type + if ( aInfo.iEventType == TLibraryEventInfo::ELibraryAdded ) + { + if ( aThread != NULL ) + { + if ( iProcessId == aThread->iOwningProcess->iId ) + { + LOGSTR1( "ATDD > Process id match" ); + aInfo.iProcessId = aThread->iOwningProcess->iId; + addInfo = ETrue; + } + } + } + else if ( aInfo.iEventType == TLibraryEventInfo::ELibraryRemoved ) + { + if ( aThread != NULL ) + { + aInfo.iProcessId = aThread->iOwningProcess->iId; + } + else + { + aInfo.iProcessId = 0; + } + addInfo = ETrue; + } + + if ( addInfo ) + { + // Store lib info + aLib->AppendName( aInfo.iLibraryName );//lint !e64 !e1514 + aInfo.iSize = aLib->iCodeSeg->iSize; + aInfo.iRunAddress = aLib->iCodeSeg->iRunAddress; + // Store library event info to the array + iEventArray.Append( aInfo ); + LOGSTR2( "ATDD > iEventArray.Count() = %d", iEventArray.Count() ); + + // if client has subscribed the event it is queued + if ( iClientThread != NULL ) + { + iEventDfc.Enque(); + } + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::InformLibraryEvent() +// Subscribes library event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::InformLibraryEvent( TRequestStatus* aStatus, + TAny* aLibraryInfo, + TThreadMessage& aMessage ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::InformLibraryEvent()" ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + // Check if request from client which is already pending + DThread* current = aMessage.Client(); + + LOGSTR2( "ATDD > Current Thread ID = %d", current->iId ); + + // Ensure that client doesn't subscribe service when there is a pending + // subscription + if ( NULL != iClientThread ) + { + aMessage.PanicClient( KClientPanic, EPanicRequestPending ); + } + else + { + // Store the client variable pointers + iClientThread = current; + iClientRequestStatus = aStatus; + iClientInfo = aLibraryInfo; + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Queue the event since now the client has subscribed it + iEventDfc.Enque(); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::CancelInformLibraryEvent +// Cancels subscription of the library event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::CancelInformLibraryEvent() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::CancelInformLibraryEvent()" ); + + iEventDfc.Cancel(); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + if ( NULL != iClientThread && iEventArray.Count() > 0 ) + { + // Signal the request as complete + Kern::RequestComplete( iClientThread, + iClientRequestStatus, + KErrCancel ); + + iClientThread = NULL; + iClientRequestStatus = NULL; + iClientInfo = NULL; + + // Reset the event array + iEventArray.Reset(); + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::HandleKillThreadEvent() +// Handles the EEventKillThread events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::HandleKillThreadEvent( DThread* aThread, + TLibraryEventInfo& aInfo ) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::HandleKillThreadEvent()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + aInfo.iProcessId = aThread->iOwningProcess->iId; + TBool alone( aThread->iOwningProcess->iThreadQ.First()->Alone() ); + LOGSTR2( "ATDD > Is alone = %d", alone ); + + // Check if this our process and is the only thread item. + if ( aInfo.iProcessId == iProcessId && !alone ) + { + if ( aThread ) + { + // Set current Thread id + LOGSTR2( "ATDD > Thread ID = %d", aThread->iId ); + aInfo.iThreadId = aThread->iId; + // Append event to array (beginning of the array) + iEventArray.Insert( aInfo, 0 ); + + // if client has subscribed the event it is queued + if ( iClientThread != NULL ) + { + iEventDfc.Enque(); + } + } + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::DoEventComplete() +// Informs client about the occured event. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::DoEventComplete() + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::DoEventComplete()" ); + + // Aqcuire the handler mutex + Kern::MutexWait( *iHandlerMutex ); + + // Aqcuire the data mutex + Kern::MutexWait( *iDataMutex ); + + if ( NULL != iClientThread && iEventArray.Count() > 0 ) + { + TInt ret = Kern::ThreadRawWrite( iClientThread, + iClientInfo, + &iEventArray[0], + sizeof( iEventArray[0] ) ); + + LOGSTR2( "ATDD > ThreadRawWrite err = %d", ret ); + + // Signal the request as complete + Kern::RequestComplete( iClientThread, + iClientRequestStatus, + ret ); + + // Remove first item to array + iEventArray.Remove( 0 ); + + // Compresses the array down to a minimum + iEventArray.Compress(); + + // Ensure that pointers are set to NULL + iClientThread = NULL; + iClientRequestStatus = NULL; + iClientInfo = NULL; + + LOGSTR2( "ATDD > iEventArray = %d", iEventArray.Count() ); + } + + // Release the data mutex + Kern::MutexSignal( *iDataMutex ); + + // Release the handler mutex + Kern::MutexSignal( *iHandlerMutex ); + } + +// ----------------------------------------------------------------------------- +// DAnalyzeToolEventHandler::EventDfc() +// Static function for DFC events. +// ----------------------------------------------------------------------------- +// +void DAnalyzeToolEventHandler::EventDfc(TAny* aPtr) + { + LOGSTR1( "ATDD DAnalyzeToolEventHandler::EventDfc()" ); + ( (DAnalyzeToolEventHandler*) aPtr )->DoEventComplete(); + } + +// End of File