diff -r 000000000000 -r a03f92240627 memspy/Driver/Kernel/Source/MemSpyDriverUserEventMonitor.cpp --- /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 + +// 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 ) ); + } + + + + + + + + + + + + + + +