--- /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 ) );
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+