memspy/Driver/Kernel/Source/MemSpyDriverUserEventMonitor.cpp
changeset 0 a03f92240627
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memspy/Driver/Kernel/Source/MemSpyDriverUserEventMonitor.cpp	Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,429 @@
+/*
+* 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:
+*
+*/
+
+#include "MemSpyDriverUserEventMonitor.h"
+
+// System includes
+#include <memspy/driver/memspydriverenumerationsshared.h>
+
+// User includes
+#include "MemSpyDriverUtils.h"
+#include "MemSpyDriverDevice.h"
+#include "MemSpyDriverOSAdaption.h"
+#include "MemSpyDriverEventMonitor.h"
+
+// Literal constants
+_LIT( KMemSpyDriverClientEMMutexName, "MemSpyDriverClientEM_0x" );
+
+
+
+
+DMemSpyDriverClientEMManager::DMemSpyDriverClientEMManager( DMemSpyDriverDevice& aDevice )
+:   iDevice( aDevice )
+    {
+    }
+
+
+DMemSpyDriverClientEMManager::~DMemSpyDriverClientEMManager()
+	{
+	TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::~DMemSpyDriverClientEMManager() - START"));
+
+    NKern::ThreadEnterCS();
+    FreeAllInstances();
+    NKern::ThreadLeaveCS();
+
+	TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::~DMemSpyDriverClientEMManager() - END"));
+	}
+
+
+TInt DMemSpyDriverClientEMManager::Create()
+    {
+    return KErrNone;
+    }
+
+
+DMemSpyDriverClientEM* DMemSpyDriverClientEMManager::EMOpen()
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMOpen() - START - iNextHandle: %d, iDevice: 0x%08x", iNextHandle+1, &iDevice ) );
+    NKern::ThreadEnterCS();
+    //
+    DMemSpyDriverClientEM* object = new DMemSpyDriverClientEM( iDevice, ++iNextHandle );
+    if  ( object != NULL )
+        {
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMOpen() - calling create..." ) );
+        const TInt error = object->Create();
+        if ( error != KErrNone )
+            {
+            TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMOpen() - creation error: %d", error ) );
+            delete object;
+            object = NULL;
+            }
+        else
+            {
+            iEMInstances.Add( &object->iLink );
+            }
+        }
+    //
+    NKern::ThreadLeaveCS();
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMOpen() - END - object: 0x%08x", object ) );
+    //
+    return object;
+    }
+
+
+TInt DMemSpyDriverClientEMManager::EMClose( TUint aHandle )
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMClose() - START - aHandle: 0x%08x", aHandle ) );
+    TInt error = KErrNotFound;
+    //
+    DMemSpyDriverClientEM* object = EMInstance( aHandle );
+    if  ( object != NULL )
+        {
+        NKern::ThreadEnterCS();
+        object->iLink.Deque();
+        delete object;
+        NKern::ThreadLeaveCS();
+        error = KErrNone;
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMClose() - END - error: %d", error ) );
+    return error;
+    }
+
+
+DMemSpyDriverClientEM* DMemSpyDriverClientEMManager::EMInstance( TUint aHandle )
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMInstance() - START - aHandle: 0x%08x", aHandle ) );
+    DMemSpyDriverClientEM* ret = NULL;
+    //
+	const SDblQueLink* const anchor = &iEMInstances.iA;
+	for (SDblQueLink* link = iEMInstances.First(); link != anchor; link = link->iNext )
+		{
+		DMemSpyDriverClientEM* object = _LOFF( link, DMemSpyDriverClientEM, iLink );
+        //
+        if  ( object->Handle() == aHandle )
+            {
+            ret = object;
+            break;
+            }
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::EMInstance() - END - aHandle: 0x%08x, ret: 0x%08x", aHandle, ret ) );
+    return ret;
+    }
+
+
+void DMemSpyDriverClientEMManager::FreeAllInstances()
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::FreeAllInstances() - START") );
+	
+    SDblQueLink* link = iEMInstances.GetFirst();
+	while( link )
+		{
+		DMemSpyDriverClientEM* object = _LOFF( link, DMemSpyDriverClientEM, iLink );
+        delete object;
+        link = iEMInstances.GetFirst();
+		}
+
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEMManager::FreeAllInstances() - END") );
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+DMemSpyDriverClientEM::DMemSpyDriverClientEM( DMemSpyDriverDevice& aDevice, TUint aHandle )
+:   iDevice( aDevice ), iHandle( aHandle )
+    {
+    }
+
+
+DMemSpyDriverClientEM::~DMemSpyDriverClientEM()
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::~DMemSpyDriverClientEM() - START - this: 0x%08x", this ));
+	iDevice.EventMonitor().RequestEventsCancel( *this );
+
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::~DMemSpyDriverClientEM() - calling NotifyChangesCancel..." ) );
+    NotifyChangesCancel();
+    
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::~DMemSpyDriverClientEM() - calling ResetPendingChanges..." ) );
+    ResetPendingChanges();
+
+	if  ( iLock )
+		{
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::~DMemSpyDriverClientEM() - closing mutex..." ) );
+		iLock->Close(NULL);
+		}
+
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::~DMemSpyDriverClientEM() - END - this: 0x%08x" ));
+    }
+
+
+TInt DMemSpyDriverClientEM::Create()
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::Create() - START - handle: 0x%08x", Handle() ) );
+
+    // Create mutex
+    TName name( KMemSpyDriverClientEMMutexName );
+    name.AppendNumFixedWidth( (TUint) this, EHex, 8 );
+    TInt error = Kern::MutexCreate( iLock, name, KMutexOrdNone );
+    //
+    if  ( error == KErrNone )
+        {
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::Create() - calling global device driver event monitor...") );
+        iDevice.EventMonitor().RequestEvents( *this );
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::Create() - END - handle: 0x%08x, err: %d", Handle(), error ) );
+    return error;
+    }
+
+
+TInt DMemSpyDriverClientEM::NotifyChanges( DThread* aClientThread, TRequestStatus* aClientRS, TAny* aClientContext )
+    {
+	Kern::MutexWait( *iLock );
+
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChanges() - START - handle: 0x%08x", Handle() ) );
+    TInt r = KErrInUse;
+    //
+    if  ( iClientRS == NULL )
+        {
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChanges() - saving client's request...") );
+        iClientThread = aClientThread;
+        iClientRS = aClientRS;
+        iClientContext = aClientContext;
+        //
+        if	( !iPendingChanges.IsEmpty() )
+			{
+            TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyOnChange() - Have buffered changes - SENDING TO CLIENT IMMEDIATELY..." ) );
+			
+            // We have something in the pending buffer so we can
+			// give it back to the client immediately.
+	        DMemSpyDriverClientEM::TChange* cachedChange = _LOFF( iPendingChanges.First(), DMemSpyDriverClientEM::TChange, iLink );
+			cachedChange->iLink.Deque();
+			
+            // Notify about change			
+			CompleteClientsRequest( cachedChange->iCompletionCode, cachedChange->iContext );
+			
+			// Discard cached entry
+            NKern::ThreadEnterCS();
+			delete cachedChange;
+            NKern::ThreadLeaveCS();
+			}
+        //
+        r = KErrNone;
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChanges() - END - handle: 0x%08x, error: %d", Handle(), r ) );
+	Kern::MutexSignal( *iLock );
+    return r;
+    }
+
+
+TInt DMemSpyDriverClientEM::NotifyChangesCancel()
+    {
+	Kern::MutexWait( *iLock );
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChangesCancel() - START - handle: 0x%08x, iClientThread: 0x%08x, iClientRS: 0x%08x", Handle(), iClientThread, iClientRS ) );
+    //
+    TInt r = KErrNotReady;
+    //
+    if  ( iClientRS != NULL )
+        {
+        DThread* clientThread = iClientThread;
+        TRequestStatus* clientRS = iClientRS;
+        //
+        iClientThread = NULL;
+        iClientRS = NULL;
+        iClientContext = NULL;
+        //
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChangesCancel() - doing final request complete...") );
+		Kern::RequestComplete( clientThread, clientRS, KErrCancel );
+        r = KErrNone;
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::NotifyChangesCancel() - END - handle: 0x%08x, error: %d", Handle(), r ) );
+	Kern::MutexSignal( *iLock );
+    return r;
+    }
+
+
+TUint DMemSpyDriverClientEM::EMTypeMask() const
+    {
+    const TUint ret = EMemSpyEventThreadAdd  | EMemSpyEventThreadKill |
+                      EMemSpyEventProcessAdd | EMemSpyEventProcessRemove | 
+                      EMemSpyEventChunkAdd   | EMemSpyEventChunkDelete;
+    return ret;
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleProcessAdd( DProcess& aProcess )
+    {
+    const TUint pid = iDevice.OSAdaption().DProcess().GetId( aProcess );
+    //
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeProcessCreate, pid );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleProcessRemoved( DProcess& aProcess )
+    {
+    const TUint pid = iDevice.OSAdaption().DProcess().GetId( aProcess );
+    //
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeProcessRemove, pid );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleThreadAdd( DThread& aThread )
+    {
+    const TUint tid = iDevice.OSAdaption().DThread().GetId( aThread );
+    //
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeThreadCreate, tid );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleThreadKilled( DThread& aThread )
+    {
+    const TUint tid = iDevice.OSAdaption().DThread().GetId( aThread );
+    //
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeThreadKill, tid );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleChunkAdd( DChunk& aChunk ) 
+    {
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeChunkAdd, (TUint) &aChunk );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::EMHandleChunkDeleted( DChunk& aChunk )
+    {
+	Kern::MutexWait( *iLock );
+    CompleteClientsRequest( EMemSpyDriverEventTypeChunkDestroy, (TUint) &aChunk );
+	Kern::MutexSignal( *iLock );
+    }
+
+
+void DMemSpyDriverClientEM::CompleteClientsRequest( TInt aCompletionCode, TUint aContext )
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - START - handle: 0x%08x, iClientThread: 0x%08x, iClientRS: 0x%08x, iClientContext: 0x%08x, aCompletionCode: %d, aContext: %d, changesPending: %d", Handle(), iClientThread, iClientRS, iClientContext, aCompletionCode, aContext, !iPendingChanges.IsEmpty() ) );
+    //
+    if  ( iClientRS != NULL )
+        {
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - attempting to complete client's request...") );
+
+        // First write context info
+        const TInt writeErr = Kern::ThreadRawWrite( iClientThread, iClientContext, &aContext, sizeof(TUint) );
+		if  ( writeErr != KErrNone )
+		    {
+            TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - write error: %d", writeErr ) );
+            aCompletionCode = writeErr;
+		    }
+
+        // Now complete event - avoiding race conditions!
+        DThread* clientThread = iClientThread;
+        TRequestStatus* clientRS = iClientRS;
+        //
+        iClientThread = NULL;
+        iClientRS = NULL;
+        iClientContext = NULL;
+        //
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - doing final request complete...") );
+		Kern::RequestComplete( clientThread, clientRS, aCompletionCode );
+        }
+    else
+        {
+		// Buffer the change for next time around...
+        TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - BUFFERING change event whilst client is AWOL...", this ) );
+        NKern::ThreadEnterCS();
+        
+        DMemSpyDriverClientEM::TChange* cachedChange = new DMemSpyDriverClientEM::TChange( aCompletionCode, aContext );
+        if  ( cachedChange )
+            {
+            iPendingChanges.Add( &cachedChange->iLink );
+            }
+        //
+        NKern::ThreadLeaveCS();
+        }
+    //
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::CompleteClientsRequest() - END - handle: 0x%08x", Handle() ) );
+    }
+
+
+void DMemSpyDriverClientEM::ResetPendingChanges()
+    {
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::ResetPendingChanges() - START - this: 0x%08x", this ) );
+    NKern::ThreadEnterCS();
+    //
+    SDblQueLink* link = iPendingChanges.GetFirst();
+	while( link )
+		{
+        DMemSpyDriverClientEM::TChange* cachedChange = _LOFF( link, DMemSpyDriverClientEM::TChange, iLink );
+        delete cachedChange;
+        link = iPendingChanges.GetFirst();
+		}
+    //
+    NKern::ThreadLeaveCS();
+    TRACE_EM( Kern::Printf("DMemSpyDriverClientEM::ResetPendingChanges() - END - this: 0x%08x", this ) );
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+