--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/perfsrv/memspy/Driver/Kernel/Source/MemSpyDriverSuspensionManager.cpp Fri Sep 17 08:38:31 2010 +0300
@@ -0,0 +1,508 @@
+/*
+* 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 "MemSpyDriverSuspensionManager.h"
+
+// System includes
+#include <memspy/driver/memspydriverobjectsshared.h>
+
+// Shared includes
+#include "MemSpyDriverUtils.h"
+#include "MemSpyDriverDevice.h"
+#include "MemSpyDriverOSAdaption.h"
+
+// Constants
+const TInt KSuspendResumeCount = 1;
+
+
+
+DMemSpySuspensionManager::DMemSpySuspensionManager( DMemSpyDriverDevice& aDevice )
+: iDevice( aDevice )
+ {
+ }
+
+
+DMemSpySuspensionManager::~DMemSpySuspensionManager()
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::~DMemSpySuspensionManager() - START"));
+
+ if ( iAlreadySuspended )
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::~DMemSpySuspensionManager() - resuming threads in process with id: %d", iSuspendedProcessId ));
+ DoResumeAllThreadsInProcess( iSuspendedProcessId );
+ }
+ if ( iTempObj != NULL )
+ {
+ Kern::SafeClose( iTempObj, NULL );
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::~DMemSpySuspensionManager() - END"));
+ }
+
+
+TInt DMemSpySuspensionManager::Construct()
+ {
+ return KErrNone;
+ }
+
+
+
+
+
+
+
+
+
+
+
+TBool DMemSpySuspensionManager::IsSuspended( TUint aPid ) const
+ {
+ TBool ret = iAlreadySuspended;
+ //
+ if ( ret )
+ {
+ ret = ( aPid == iSuspendedProcessId );
+ }
+ //
+ TRACE( Kern::Printf("DMemSpySuspensionManager::IsSuspended() - iAlreadySuspended: %d, iSuspendedProcessId: %d, aPid: %d, ret: %d", iAlreadySuspended, iSuspendedProcessId, aPid, ret ) );
+ return ret;
+ }
+
+
+TBool DMemSpySuspensionManager::IsSuspended( DThread& aThread ) const
+ {
+ TBool ret = EFalse;
+ //
+ const TUint tid = iDevice.OSAdaption().DThread().GetId( aThread );
+ DProcess* process = iDevice.OSAdaption().DThread().GetOwningProcess( aThread );
+ TRACE( Kern::Printf("DMemSpySuspensionManager::IsSuspended() - START - iSuspendedProcessId: %d, aThread: (%d) %O, process: 0x%08x", iSuspendedProcessId, tid, &aThread, process ) );
+ //
+ if ( process )
+ {
+ ret = IsSuspended( *process );
+ }
+ //
+ TRACE( Kern::Printf("DMemSpySuspensionManager::IsSuspended() - END - ret: %d", ret ) );
+ return ret;
+ }
+
+
+TBool DMemSpySuspensionManager::IsSuspended( DProcess& aProcess ) const
+ {
+ const TUint pid = iDevice.OSAdaption().DProcess().GetId( aProcess );
+ TRACE( Kern::Printf("DMemSpySuspensionManager::IsSuspended() - START - iSuspendedProcessId: %d, aProcess: (%d / %d) %O", iSuspendedProcessId, pid, aProcess.iId, &aProcess ) );
+ //
+ const TBool ret = IsSuspended( pid );
+ //
+ TRACE( Kern::Printf("DMemSpySuspensionManager::IsSuspended() - END - ret: %d", ret ) );
+ return ret;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TInt DMemSpySuspensionManager::SuspendAllThreadsInProcess( TUint aPid, DThread& aClientThread )
+ {
+ // Suspend all threads in the process
+ TRACE( Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess() - START - id: %8d, iSuspendedProcessId: %8d, iAlreadySuspended: %d", aPid, iSuspendedProcessId, iAlreadySuspended ));
+ if ( iAlreadySuspended && aPid != iSuspendedProcessId )
+ {
+ Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess() - END - trying to suspend multiple processes!");
+ MemSpyDriverUtils::PanicThread( aClientThread, EPanicAttemptingToSuspendMultipleProcesses );
+ return KErrNone;
+ }
+ else if ( IsProcessTheClientThread( aPid, aClientThread ) )
+ {
+ Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess() - END - trying to suspend client thread! - request ignored");
+ return KErrLocked;
+ }
+
+ TInt r = KErrNone;
+ TRACE( Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess - iAlreadySuspended: %d", iAlreadySuspended));
+ if ( !iAlreadySuspended )
+ {
+ r = DoSuspendAllThreadsInProcess( aPid, &aClientThread );
+ if (r != KErrNone)
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess() - END - process not found") );
+ return r;
+ }
+
+ // To ensure we clean up in case of user-side problem...
+ iSuspendedProcessId = aPid;
+ iAlreadySuspended = ETrue;
+ iSuspendCount = 1;
+ }
+ else
+ {
+ // Just increment the count
+ ++iSuspendCount;
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::SuspendAllThreadsInProcess() - END - iSuspendCount: %d, iSuspendedProcessId: %d", iSuspendCount, iSuspendedProcessId ));
+ return iSuspendCount;
+ }
+
+
+TInt DMemSpySuspensionManager::ResumeAllThreadsInProcess( TUint aPid, DThread& aClientThread )
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - START - id: %8d, iSuspendedProcessId: %8d, iAlreadySuspended: %d", aPid, iSuspendedProcessId, iAlreadySuspended));
+ if ( !iAlreadySuspended )
+ {
+ // Nothing suspended - don't panic
+ TRACE( Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - END - nothing suspended, ignoring client request"));
+ return KErrNone;
+ }
+ else if ( iAlreadySuspended && aPid != iSuspendedProcessId )
+ {
+ Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - END - trying to resume incorrect process!");
+ MemSpyDriverUtils::PanicThread( aClientThread, EPanicAttemptingToResumeNonSuspendedProcess );
+ return KErrNone;
+ }
+ else if ( IsProcessTheClientThread( aPid, aClientThread ) )
+ {
+ Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - END - trying to resume client thread! - request ignored");
+ return KErrLocked;
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess"));
+
+ TInt r = KErrNone;
+ if ( --iSuspendCount <= 0 )
+ {
+ r = DoResumeAllThreadsInProcess( aPid, &aClientThread );
+ if (r != KErrNone)
+ {
+ Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - END - process not found");
+ return r;
+ }
+
+ // No longer need to clean up
+ iAlreadySuspended = EFalse;
+ iSuspendedProcessId = 0;
+ iSuspendCount = 0;
+ }
+ else
+ {
+ // No action needed - we've already decremented the counter
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::ResumeAllThreadsInProcess() - END - iSuspendCount: %d", iSuspendCount));
+ return iSuspendCount;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TInt DMemSpySuspensionManager::DoSuspendAllThreadsInProcess( TUint aPid, DThread* /*aClientThread*/ )
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoSuspendAllThreadsInProcess() - START - aPid: %d", aPid));
+ TInt r = OpenTempObject( aPid, EProcess );
+ if (r == KErrNone)
+ {
+ DProcess* process = (DProcess*) iTempObj;
+ TFullName processName;
+ process->FullName( processName );
+ processName.Append('*');
+
+ DObjectCon* container = Kern::Containers()[EThread];
+ NKern::ThreadEnterCS();
+ container->Wait();
+ //
+ TFullName result;
+#ifdef MCL_FIND_HANDLES
+ TFindHandle findHandle;
+#else
+ TInt findHandle = 0;
+#endif
+ r = container->FindByFullName( findHandle, processName, result );
+ while( r == KErrNone )
+ {
+ DThread* thread = (DThread*) container->At( findHandle );
+ if ( thread )
+ {
+ const TUint tid = iDevice.OSAdaption().DThread().GetId( *thread );
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoSuspendAllThreadsInProcess - suspending thread: (%d), %O", tid, thread ));
+ //
+ Kern::ThreadSuspend( *thread, KSuspendResumeCount );
+ }
+ //
+ r = container->FindByFullName( findHandle, processName, result );
+ }
+ //
+ container->Signal();
+ NKern::ThreadLeaveCS();
+
+ CloseTempObject();
+ r = KErrNone;
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoSuspendAllThreadsInProcess() - END - ret: %d", r));
+ return r;
+ }
+
+
+TInt DMemSpySuspensionManager::DoResumeAllThreadsInProcess( TUint aPid, DThread* aClientThread )
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoResumeAllThreadsInProcess() - START - aPid: %d", aPid));
+ TInt r = OpenTempObject( aPid, EProcess );
+ if (r == KErrNone)
+ {
+ // Check that this process is suspended
+ DProcess* process = (DProcess*) iTempObj;
+ const TUint pid = iDevice.OSAdaption().DProcess().GetId( *process );
+ if ( !aClientThread || ( aClientThread && CheckProcessSuspended( pid, *aClientThread ) ) )
+ {
+ // Resume all threads in the process
+ TFullName processName;
+ process->FullName( processName );
+ processName.Append('*');
+
+ DObjectCon* container = Kern::Containers()[EThread];
+ NKern::ThreadEnterCS();
+ container->Wait();
+ //
+ TFullName result;
+ #ifdef MCL_FIND_HANDLES
+ TFindHandle findHandle;
+ #else
+ TInt findHandle = 0;
+ #endif
+ r = container->FindByFullName( findHandle, processName, result );
+ while( r == KErrNone )
+ {
+ DThread* thread = (DThread*) container->At( findHandle );
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoResumeAllThreadsInProcess - resuming thread: %lS", &result));
+ //
+ Kern::ThreadResume(*thread);
+ r = container->FindByFullName( findHandle, processName, result );
+ }
+ //
+ container->Signal();
+ NKern::ThreadLeaveCS();
+
+ r = KErrNone;
+ }
+ else
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoResumeAllThreadsInProcess - parent process not suspended => KErrAccessDenied"));
+ r = KErrAccessDenied;
+ }
+
+ CloseTempObject();
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::DoResumeAllThreadsInProcess() - END - ret: %d", r));
+ return r;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TBool DMemSpySuspensionManager::IsProcessTheClientThread( TUint aPid, DThread& aClientThread ) const
+ {
+ TBool ret = EFalse;
+ DProcess& clientProcess = *iDevice.OSAdaption().DThread().GetOwningProcess( aClientThread );
+ const TUint pid = iDevice.OSAdaption().DProcess().GetId( clientProcess );
+ if ( pid == aPid )
+ {
+ ret = ETrue;
+ }
+ //
+ return ret;
+ }
+
+
+TBool DMemSpySuspensionManager::CheckProcessSuspended( TUint aExpectedPid, DThread& aClientThread ) const
+ {
+ TBool suspended = ETrue;
+ //
+ if ( !iAlreadySuspended )
+ {
+ MemSpyDriverUtils::PanicThread( aClientThread, EPanicThreadsInProcessNotSuspended );
+ }
+ else if ( aExpectedPid != iSuspendedProcessId )
+ {
+ MemSpyDriverUtils::PanicThread( aClientThread, EPanicWrongProcessSuspended );
+ }
+ //
+ return suspended;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TInt DMemSpySuspensionManager::OpenTempObject(TUint aId, TObjectType aType)
+ {
+ __ASSERT_DEBUG( aType == EProcess || aType == EThread, MemSpyDriverUtils::Fault( __LINE__ ) );
+ __ASSERT_DEBUG( !iTempObj, MemSpyDriverUtils::Fault( __LINE__ ) );
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - START - aId: %d, aType: %d", aId, aType ));
+ DObjectCon* pC = Kern::Containers()[aType];
+ NKern::ThreadEnterCS();
+ pC->Wait();
+ iTempObj = (aType == EProcess) ? (DObject*)Kern::ProcessFromId(aId) : (DObject*)Kern::ThreadFromId(aId);
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - kernel obj from id returned: 0x%08x %O", iTempObj, iTempObj ));
+ //
+ TBool openedOkay = EFalse;
+ TInt r = KErrNone;
+ //
+ if ( iTempObj )
+ {
+ r = iTempObj->Open();
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - open returned: %d", r ));
+ //
+ if ( r == KErrNone )
+ {
+ openedOkay = ETrue;
+ if ( aType == EProcess )
+ {
+ // Check the process is still alive
+ DProcess* process = (DProcess*) iTempObj;
+ const TExitType exitType = iDevice.OSAdaption().DProcess().GetExitType( *process );
+ if ( exitType != EExitPending )
+ {
+ r = KErrDied;
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - PROCESS IS DEAD!" ));
+ }
+ }
+ else if (aType == EThread )
+ {
+ // Check the thread is still alive
+ DThread* thread = (DThread*) iTempObj;
+ const TExitType exitType = iDevice.OSAdaption().DThread().GetExitType( *thread );
+ if ( exitType != EExitPending )
+ {
+ r = KErrDied;
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - THREAD IS DEAD!" ));
+ }
+ }
+ }
+
+ }
+ else if ( ! iTempObj )
+ {
+ r = KErrNotFound;
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - ENTITY NOT FOUND!" ));
+ }
+ //
+ pC->Signal();
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - signalled container..." ));
+ NKern::ThreadLeaveCS();
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - left CS..." ));
+ //
+ if ( r != KErrNone && iTempObj )
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - ERROR CASE - closing temp object (r: %d, openedOkay: %d)...", r, openedOkay ));
+ //
+ if ( openedOkay )
+ {
+ CloseTempObject();
+ }
+ else
+ {
+ NKern::SafeSwap( NULL, (TAny*&) iTempObj );
+ }
+ //
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - ERROR CASE - closed temp object" ));
+ }
+ //
+ TRACE( Kern::Printf("DMemSpySuspensionManager::OpenTempObject() - END - r: %d", r ));
+ return r;
+ }
+
+
+void DMemSpySuspensionManager::CloseTempObject()
+ {
+ TRACE( Kern::Printf("DMemSpySuspensionManager::CloseTempObject() - START - iTempObj: 0x%08x %O", iTempObj, iTempObj ));
+
+ __ASSERT_DEBUG( iTempObj, MemSpyDriverUtils::Fault( __LINE__ ) );
+ if ( iTempObj )
+ {
+ NKern::ThreadEnterCS();
+ Kern::SafeClose( iTempObj, NULL );
+ NKern::ThreadLeaveCS();
+ }
+
+ TRACE( Kern::Printf("DMemSpySuspensionManager::CloseTempObject() - END" ));
+ }
+
+