/*
* 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 <kernel/kern_priv.h>
// 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