memana/analyzetoolclient/kerneleventhandler/src/analyzetooleventhandler.cpp
changeset 0 f0f2b8682603
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memana/analyzetoolclient/kerneleventhandler/src/analyzetooleventhandler.cpp	Thu Feb 11 15:51:35 2010 +0200
@@ -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 <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