memspy/Driver/Kernel/Source/MemSpyDriverInspectedProcess.cpp
changeset 0 a03f92240627
child 30 86a2e675b80a
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include "MemSpyDriverInspectedProcess.h"
       
    19 
       
    20 // System includes
       
    21 #include <kern_priv.h>
       
    22 #include <nk_trace.h>
       
    23 #include <u32hal.h>
       
    24 
       
    25 #ifdef __MARM__
       
    26 #include "kdebug.h"
       
    27 #endif //__MARM__
       
    28 
       
    29 // User includes
       
    30 #include "MemSpyDriverUtils.h"
       
    31 #include "MemSpyDriverDevice.h"
       
    32 #include "MemSpyDriverOSAdaption.h"
       
    33 #include "MemSpyDriverInspectedProcessManager.h"
       
    34 
       
    35 // Constants
       
    36 _LIT8( KMemSpyLitDollarHeap, "$HEAP" );
       
    37 _LIT8( KMemSpyLitDollarDllData, "DLL$DATA" );
       
    38 _LIT8( KMemSpyLitDollarDat, "$DAT" );
       
    39 _LIT( KMemSpyInspectedProcessMutexName, "MemSpyInspectedProcess_0x" );
       
    40 
       
    41 
       
    42 DMemSpyInspectedProcess::DMemSpyInspectedProcess( DMemSpyDriverDevice& aDevice )
       
    43 :   iDevice( aDevice )
       
    44 	{
       
    45 	}
       
    46 
       
    47 
       
    48 DMemSpyInspectedProcess::~DMemSpyInspectedProcess()
       
    49 	{
       
    50     TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - START - this: 0x%08x, %O", this, iProcess ));
       
    51 	EventMonitor().RequestEventsCancel( *this );
       
    52 
       
    53     TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling NotifyOnChangeCancel..." ) );
       
    54     NotifyOnChangeCancel();
       
    55 
       
    56     TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling ResetTrackedList..." ) );
       
    57     ResetTrackedList();
       
    58 
       
    59     TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling ResetPendingChanges..." ) );
       
    60     ResetPendingChanges();
       
    61 
       
    62 	if  ( iLock )
       
    63 		{
       
    64         TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closing mutex..." ) );
       
    65 		iLock->Close(NULL);
       
    66 		}
       
    67 
       
    68     if  ( iProcess )
       
    69         {
       
    70         TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closing process..." ) );
       
    71 	    Kern::SafeClose( (DObject*&) iProcess, NULL );
       
    72         TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closed process!" ) );
       
    73         }
       
    74 
       
    75     TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - END - this: 0x%08x", this ) );
       
    76 	}
       
    77 
       
    78 
       
    79 TInt DMemSpyInspectedProcess::Open( DProcess* aProcess )
       
    80     {
       
    81     TRACE( Kern::Printf("DMemSpyInspectedProcess::Open() - START - this: 0x%08x, aProcess: 0x%08x (%O)", this, aProcess, aProcess ));
       
    82 
       
    83     TInt error = KErrNone;
       
    84     //
       
    85     iProcess = aProcess;
       
    86     error = iProcess->Open();
       
    87     //
       
    88     if  ( error == KErrNone )
       
    89         {
       
    90         iProcessId = iDevice.OSAdaption().DProcess().GetId( *aProcess );
       
    91 
       
    92         // Create mutex
       
    93         TName name( KMemSpyInspectedProcessMutexName );
       
    94         name.AppendNumFixedWidth( (TUint) this, EHex, 8 );
       
    95         error = Kern::MutexCreate( iLock, name, KMutexOrdNone );
       
    96         //
       
    97         if  ( error == KErrNone )
       
    98             {
       
    99             // Get size of all stacks (user & supervsior) for process. Also
       
   100             // updates iUserThreadStackSize with the current size of just
       
   101             // the user-side thread stacks.
       
   102             iInfoCurrent.iMemoryStack = StackSize( *aProcess );
       
   103         
       
   104             // Request events
       
   105             EventMonitor().RequestEvents( *this );
       
   106         
       
   107             // Find initial chunks that are mapped into process
       
   108             FindChunks( *aProcess );
       
   109         
       
   110             // Indicate that we have data waiting for client. This will
       
   111             // cause the client's RS to be completed as soon as it 
       
   112             // registers with us...
       
   113             UpdateStatistics();
       
   114             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   115             }
       
   116         }
       
   117     //
       
   118     TRACE( Kern::Printf("DMemSpyInspectedProcess::Open() - END - this: 0x%08x, error: %d", this, error ));
       
   119     return error;
       
   120     }
       
   121 
       
   122 
       
   123 
       
   124 
       
   125 
       
   126 
       
   127 
       
   128 
       
   129 TInt DMemSpyInspectedProcess::NotifyOnChange( DThread* aThread, TRequestStatus* aRequestStatus, TMemSpyDriverProcessInspectionInfo* aInfo )
       
   130     {
       
   131 	Kern::MutexWait( *iLock );
       
   132 
       
   133     TInt err = KErrInUse;
       
   134     const TBool notificationQueued = NotifyOnChangeQueued();
       
   135     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - START - this: 0x%08x, iAmDead: %d, aRequestStatus: 0x%08x, notificationQueued: %d, iChangeObserverThread: 0x%08x (%O)", this, iAmDead, aRequestStatus, notificationQueued, iChangeObserverThread, iChangeObserverThread ) );
       
   136     //
       
   137     if  ( notificationQueued == EFalse )
       
   138         {
       
   139         TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - Saving client RS..." ) );
       
   140         iChangeObserverThread = aThread;
       
   141         iChangeObserverRS = aRequestStatus;
       
   142         iChangeObserverInfo = aInfo;
       
   143         
       
   144         // Whilst we still have items in the buffer, we let the client drain them fully.
       
   145         // However, if the process is now marked as dead and the buffer is exhausted,
       
   146         // we indicate this via KErrDied completion which will cause the client to
       
   147         // stop requesting any more changes.
       
   148         if	( !iPendingChanges.IsEmpty() )
       
   149 			{
       
   150             TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - Have buffered changes - SENDING TO CLIENT IMMEDIATELY..." ) );
       
   151 			
       
   152             // We have something in the pending buffer so we can
       
   153 			// give it back to the client immediately.
       
   154 	        TMemSpyTrackedChunkChangeInfo* cachedChange = _LOFF( iPendingChanges.First(), TMemSpyTrackedChunkChangeInfo, iLink );
       
   155 			cachedChange->iLink.Deque();
       
   156 			
       
   157             // Notify about change			
       
   158 			CompleteClientsRequest( KErrNone, &cachedChange->iInfo );
       
   159 			
       
   160 			// Discard cached entry
       
   161             NKern::ThreadEnterCS();
       
   162 			delete cachedChange;
       
   163             NKern::ThreadLeaveCS();
       
   164 			}
       
   165         else if ( iAmDead )
       
   166             {
       
   167             // We must stop listening outside of an event monitor callback...
       
   168     	    EventMonitor().RequestEventsCancel( *this );
       
   169 			CompleteClientsRequest( KErrDied );
       
   170             }
       
   171         //
       
   172 		err = KErrNone;
       
   173         }
       
   174 	//
       
   175     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - END - this: 0x%08x, err: %d", this, err ) );
       
   176 
       
   177 	Kern::MutexSignal( *iLock );
       
   178     return err;
       
   179     }
       
   180 
       
   181 
       
   182 TInt DMemSpyInspectedProcess::NotifyOnChangeCancel()
       
   183     {
       
   184 	Kern::MutexWait( *iLock );
       
   185     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeCancel() - START - this: 0x%08x, queued: %d, iChangeObserverThread: 0x%08x, iChangeObserverRS: 0x%08x", this, NotifyOnChangeQueued(), iChangeObserverThread, iChangeObserverRS ) );
       
   186     //
       
   187     if  ( NotifyOnChangeQueued() )
       
   188         {
       
   189         TRACE( Kern::Printf( "DMemSpyInspectedProcess::NotifyOnChangeCancel() - this: 0x%08x, iChangeObserverRS: 0x%08x, iProcessId: %d (0x%04x)", this, iChangeObserverRS, iProcessId, iProcessId ) );
       
   190 		Kern::RequestComplete( iChangeObserverThread, iChangeObserverRS, KErrCancel );
       
   191         iChangeObserverThread = NULL;
       
   192         iChangeObserverRS = NULL;
       
   193         iChangeObserverInfo = NULL;
       
   194         }
       
   195 	//
       
   196     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeCancel() - END - this: 0x%08x", this ) );
       
   197 	Kern::MutexSignal( *iLock );
       
   198 
       
   199     return KErrNone;
       
   200     }
       
   201 
       
   202 
       
   203 TBool DMemSpyInspectedProcess::NotifyOnChangeQueued() const
       
   204     {
       
   205     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeQueued() - START - this: 0x%08x", this ) );
       
   206     //
       
   207 	Kern::MutexWait( *iLock );
       
   208     const TBool queued = ( iChangeObserverRS != NULL );
       
   209 	Kern::MutexSignal( *iLock );
       
   210     //
       
   211     TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeQueued() - END - this: 0x%08x, queued: %d", this, queued ) );
       
   212     return queued;
       
   213     }
       
   214 
       
   215 
       
   216 
       
   217 
       
   218 
       
   219 
       
   220 
       
   221 
       
   222 
       
   223 void DMemSpyInspectedProcess::CompleteClientsRequest( TInt aCompletionCode, TMemSpyDriverProcessInspectionInfo* aInfo )
       
   224     {
       
   225     const TBool notificationQueued = NotifyOnChangeQueued();
       
   226     TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - START - this: 0x%08x, iChangeObserverThread: 0x%08x, iChangeObserverRS: 0x%08x, iChangeObserverInfo: 0x%08x, notificationQueued: %d", this, iChangeObserverThread, iChangeObserverRS, iChangeObserverInfo, notificationQueued ) );
       
   227     TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - iAmDead: %d, buffer is empty: %d, aCompletionCode: %d, iProcessId: %d (0x%04x), aInfo: 0x%08x, iChangeDeliveryCounter: %d", iAmDead, iPendingChanges.IsEmpty(), aCompletionCode, iProcessId, iProcessId, aInfo, iChangeDeliveryCounter ) );
       
   228 
       
   229     if  ( notificationQueued )
       
   230         {
       
   231         ++iChangeDeliveryCounter;
       
   232         TInt completionCode = aCompletionCode;
       
   233         
       
   234         // Write them to client...
       
   235         if ( aInfo != NULL )
       
   236             {
       
   237             const TInt writeErr = Kern::ThreadRawWrite( iChangeObserverThread, iChangeObserverInfo, aInfo, sizeof(TMemSpyDriverProcessInspectionInfo) );
       
   238     		if  ( writeErr != KErrNone )
       
   239     		    {
       
   240                 completionCode = writeErr;
       
   241     		    }
       
   242             }
       
   243 
       
   244         // Complete client's async request
       
   245         DThread* changeThread = iChangeObserverThread;
       
   246         TRequestStatus* changeRS = iChangeObserverRS;
       
   247 
       
   248         // Zero these out first to avoid race condition
       
   249         iChangeObserverThread = NULL;
       
   250         iChangeObserverRS = NULL;
       
   251         iChangeObserverInfo = NULL;
       
   252 
       
   253         // ...and then tell client.
       
   254         TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - SENDING CHANGE [%4d] TO CLIENT [err: %d]", iChangeDeliveryCounter, completionCode ) );
       
   255 		Kern::RequestComplete( changeThread, changeRS, completionCode );
       
   256         }
       
   257 	else if ( aInfo )
       
   258 		{
       
   259 		// Buffer the change for next time around...
       
   260         TRACE( Kern::Printf("DMemSpyInspectedProcess::CompleteClientsRequest() - BUFFERING change event whilst client is AWOL...", this ) );
       
   261         NKern::ThreadEnterCS();
       
   262         
       
   263         TMemSpyTrackedChunkChangeInfo* changeInfo = new TMemSpyTrackedChunkChangeInfo();
       
   264         if ( changeInfo )
       
   265             {
       
   266             changeInfo->iInfo = *aInfo;
       
   267             iPendingChanges.Add( &changeInfo->iLink );
       
   268             }
       
   269         //
       
   270         NKern::ThreadLeaveCS();
       
   271 		}
       
   272 
       
   273     TRACE( Kern::Printf("DMemSpyInspectedProcess::CompleteClientsRequest() - END - this: 0x%08x", this ) );
       
   274     }
       
   275 
       
   276 
       
   277 
       
   278 
       
   279 
       
   280 
       
   281 
       
   282 
       
   283 
       
   284 
       
   285 
       
   286 
       
   287 void DMemSpyInspectedProcess::ResetTrackedList()
       
   288     {
       
   289     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetTrackedList() - START - this: 0x%08x", this ) );
       
   290     NKern::ThreadEnterCS();
       
   291     //
       
   292     SDblQueLink* link = iTrackedChunks.GetFirst();
       
   293 	while( link )
       
   294 		{
       
   295 		TMemSpyTrackedChunk* object = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   296         delete object;
       
   297         link = iTrackedChunks.GetFirst();
       
   298 		}
       
   299     //
       
   300     NKern::ThreadLeaveCS();
       
   301     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetTrackedList() - END - this: 0x%08x", this ) );
       
   302     }
       
   303 
       
   304 
       
   305 void DMemSpyInspectedProcess::SetTrackedListUnused()
       
   306     {
       
   307     TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnused() - START - this: 0x%08x", this ) );
       
   308 	SDblQueLink* anchor = &iTrackedChunks.iA;
       
   309 	for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext)
       
   310 		{
       
   311 		TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   312         trackedChunk->SetUnused( ETrue );
       
   313 		}
       
   314     TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnused() - END - this: 0x%08x", this ) );
       
   315     }
       
   316 
       
   317 
       
   318 void DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::TType aType, TBool aUnusedStatus )
       
   319     {
       
   320     TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType() - START - this: 0x%08x", this ) );
       
   321 	SDblQueLink* anchor = &iTrackedChunks.iA;
       
   322 	for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext)
       
   323 		{
       
   324 		TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   325 		if ( trackedChunk->Type() == aType )
       
   326 		    {
       
   327             trackedChunk->SetUnused( aUnusedStatus );
       
   328 		    }
       
   329 		}
       
   330     TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType() - END - this: 0x%08x", this ) );
       
   331     }
       
   332 
       
   333 
       
   334 void DMemSpyInspectedProcess::DiscardUnusedTrackListItems()
       
   335     {
       
   336     TRACE( Kern::Printf("DMemSpyInspectedProcess::DiscardUnusedTrackListItems() - START - this: 0x%08x", this ) );
       
   337     NKern::ThreadEnterCS();
       
   338 	const SDblQueLink* const anchor = &iTrackedChunks.iA;
       
   339     //	
       
   340 	SDblQueLink* link = iTrackedChunks.First();
       
   341 	while( link && link != anchor )
       
   342 		{
       
   343 		TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   344         const TBool unused = trackedChunk->iUnused;
       
   345         //
       
   346         link = link->iNext;
       
   347         //
       
   348         if  ( unused )
       
   349             {
       
   350     		trackedChunk->iLink.Deque();
       
   351             delete trackedChunk;
       
   352             }
       
   353         else
       
   354             {
       
   355             trackedChunk->SetUnused( EFalse );
       
   356             }
       
   357 		}
       
   358     //
       
   359     NKern::ThreadLeaveCS();
       
   360     TRACE( Kern::Printf("DMemSpyInspectedProcess::DiscardUnusedTrackListItems() - END - this: 0x%08x", this ) );
       
   361     }
       
   362 
       
   363 
       
   364 void DMemSpyInspectedProcess::AddTrackedChunk( DChunk* aChunk, TMemSpyTrackedChunk::TType aType )
       
   365     {
       
   366     TRACE( Kern::Printf("DMemSpyInspectedProcess::AddTrackedChunk() - START - this: 0x%08x, aChunk: 0x%08x (%O)", this, aChunk, aChunk ) );
       
   367     NKern::ThreadEnterCS();
       
   368     //
       
   369     TMemSpyTrackedChunk* wrapper = new TMemSpyTrackedChunk( aChunk, aType );
       
   370     if ( wrapper )
       
   371         {
       
   372         DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk();
       
   373         const TInt cSize = chunkAdaption.GetSize( *aChunk );
       
   374         wrapper->SetSize( cSize );
       
   375         iTrackedChunks.Add( &wrapper->iLink );
       
   376         }
       
   377     //
       
   378     NKern::ThreadLeaveCS();
       
   379     TRACE( Kern::Printf("DMemSpyInspectedProcess::AddTrackedChunk() - END - this: 0x%08x", this ) );
       
   380     }
       
   381 
       
   382 
       
   383 TMemSpyTrackedChunk* DMemSpyInspectedProcess::TrackedChunkByHandle( TAny* aHandle )
       
   384     {
       
   385     TRACE( Kern::Printf("DMemSpyInspectedProcess::TrackedChunkByHandle() - START - this: 0x%08x", this ) );
       
   386     TMemSpyTrackedChunk* ret = NULL;
       
   387     //
       
   388 	const SDblQueLink* const anchor = &iTrackedChunks.iA;
       
   389 	for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext)
       
   390 		{
       
   391 		TMemSpyTrackedChunk* const trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   392 
       
   393 		if  ( trackedChunk && trackedChunk->Handle() == aHandle )
       
   394 			{
       
   395 			ret = trackedChunk;
       
   396             break;
       
   397 			}
       
   398 		}
       
   399     //
       
   400     TRACE( Kern::Printf("DMemSpyInspectedProcess::TrackedChunkByHandle() - END - this: 0x%08x, entry: 0x%08x (%O)", this, ret, ret ? ret->iChunk : NULL ) );
       
   401 	return ret;
       
   402     }
       
   403 
       
   404 
       
   405 
       
   406 
       
   407 
       
   408 
       
   409 
       
   410 
       
   411     
       
   412 
       
   413 
       
   414 DMemSpyInspectedProcessManager& DMemSpyInspectedProcess::PManager()
       
   415     {
       
   416     return iDevice.ProcessInspectionManager();
       
   417     }
       
   418 
       
   419 
       
   420 DMemSpyEventMonitor& DMemSpyInspectedProcess::EventMonitor()
       
   421     {
       
   422     return iDevice.EventMonitor();
       
   423     }
       
   424 
       
   425 
       
   426 
       
   427 
       
   428 
       
   429 
       
   430 
       
   431 TUint DMemSpyInspectedProcess::EMTypeMask() const
       
   432     {
       
   433     TUint ret = EMemSpyEventThreadAdd     | EMemSpyEventThreadRemove  | EMemSpyEventThreadKill |
       
   434                 EMemSpyEventProcessUpdate | EMemSpyEventProcessRemove | 
       
   435                 EMemSpyEventChunkAdd      | EMemSpyEventChunkUpdate   | EMemSpyEventChunkDelete;
       
   436 
       
   437     if  ( iAmDead )
       
   438         {
       
   439         // Not interested anymore...
       
   440         ret = 0;
       
   441         }
       
   442 
       
   443     return ret;
       
   444     }
       
   445 
       
   446 
       
   447 void DMemSpyInspectedProcess::EMHandleProcessUpdated( DProcess& aProcess )
       
   448     {
       
   449     const TUint procId = iDevice.OSAdaption().DProcess().GetId( aProcess );
       
   450     if  ( procId == iProcessId )
       
   451         {
       
   452 	    Kern::MutexWait( *iLock );
       
   453 
       
   454         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessUpdated() - START - this: 0x%08x, iProcess: 0x%08x (%O)", this, iProcess, iProcess ) );
       
   455 	    NKern::ThreadEnterCS();
       
   456 
       
   457         // Mark all tracked chunks as dirty whilst we work out
       
   458         // what is and isn't mapped into the process
       
   459         SetTrackedListUnused();
       
   460         SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkGlobalData, EFalse /* global data chunks are still in use */ );
       
   461 
       
   462         // Locate any suitable chunks, tagging existing entries as
       
   463         // 'in use' so that we can easily spot ones which are no longer
       
   464         // mapped into the process.
       
   465         FindChunks( *iProcess );
       
   466 
       
   467         // Throw away and tracked chunks which aren't mapped into the 
       
   468         // process anymore.
       
   469         DiscardUnusedTrackListItems();
       
   470 
       
   471         // Calculate latest statistics...
       
   472         const TBool changeDetected = UpdateStatistics();
       
   473         if  ( changeDetected )
       
   474             {
       
   475             // Inform observer about new results.
       
   476             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   477             }
       
   478 
       
   479         NKern::ThreadLeaveCS();
       
   480         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessUpdated() - END - this: 0x%08x", this ) );
       
   481 
       
   482         Kern::MutexSignal( *iLock );
       
   483         }
       
   484     }
       
   485 
       
   486 
       
   487 void DMemSpyInspectedProcess::EMHandleProcessRemoved( DProcess& aProcess )
       
   488     {
       
   489     DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess();
       
   490     const TUint pid = dProcessAdaption.GetId( aProcess );
       
   491 
       
   492     if  ( pid == iProcessId )
       
   493         {
       
   494 	    Kern::MutexWait( *iLock );
       
   495 
       
   496         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessRemoved() - START - this: 0x%08x", this ) );
       
   497 	    NKern::ThreadEnterCS();
       
   498 
       
   499         // We will implement a multi phased approach to the process being removed.
       
   500         //
       
   501         // The first notification we will send will show that the process heap and
       
   502         // local chunks have been removed, leaving shared chunk sizes intact.
       
   503         //
       
   504         // We will then send another change, this time setting everything to zero...
       
   505         SetTrackedListUnused();
       
   506         SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkShared, EFalse /* shared chunks are still in use */ );
       
   507         SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkGlobalData, EFalse /* global data chunks are still in use */ );
       
   508         DiscardUnusedTrackListItems();
       
   509         const TBool changeDetected1 = UpdateStatistics();
       
   510         if  ( changeDetected1 )
       
   511             {
       
   512             // Inform observer about new results.
       
   513             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   514             }
       
   515 
       
   516         // Now repeat the exercise, this time removing everything.
       
   517         ResetTrackedList();
       
   518     
       
   519         // ... including stack
       
   520         iInfoCurrent.iMemoryStack = 0;
       
   521         
       
   522         const TBool changeDetected2 = UpdateStatistics();
       
   523         if  ( changeDetected2 )
       
   524             {
       
   525             // Inform observer about new results.
       
   526             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   527             }
       
   528 
       
   529         // Stop listening to events since we've drained everything now...
       
   530         iAmDead = ETrue;
       
   531 
       
   532         NKern::ThreadLeaveCS();
       
   533         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessRemoved() - END - this: 0x%08x", this ) );
       
   534 
       
   535         Kern::MutexSignal( *iLock );
       
   536         }
       
   537     }
       
   538 
       
   539 
       
   540 void DMemSpyInspectedProcess::EMHandleThreadAdd( DThread& aThread )
       
   541     {
       
   542     DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread();
       
   543     DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess();
       
   544     //
       
   545     DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread );
       
   546     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadAdd() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) );
       
   547     if ( owningProcess )
       
   548         {
       
   549         const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess );
       
   550         const TUint myId = dProcessAdaption.GetId( *iProcess );
       
   551         //
       
   552         if ( myId == owningProcessId )
       
   553             {
       
   554             EMHandleThreadChanged( aThread );
       
   555             }
       
   556         }
       
   557     }
       
   558 
       
   559 
       
   560 void DMemSpyInspectedProcess::EMHandleThreadRemoved( DThread& aThread )
       
   561     {
       
   562     DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread();
       
   563     DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess();
       
   564     //
       
   565     DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread );
       
   566     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadRemoved() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) );
       
   567     if ( owningProcess )
       
   568         {
       
   569         const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess );
       
   570         const TUint myId = dProcessAdaption.GetId( *iProcess );
       
   571         //
       
   572         if ( myId == owningProcessId )
       
   573             {
       
   574             EMHandleThreadChanged( aThread );
       
   575             }
       
   576         }
       
   577     }
       
   578 
       
   579 
       
   580 void DMemSpyInspectedProcess::EMHandleThreadKilled( DThread& aThread )
       
   581     {
       
   582     //
       
   583     DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread();
       
   584     DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess();
       
   585     //
       
   586     DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread );
       
   587     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadKilled() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) );
       
   588     if ( owningProcess )
       
   589         {
       
   590         const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess );
       
   591         const TUint myId = dProcessAdaption.GetId( *iProcess );
       
   592         //
       
   593         if ( myId == owningProcessId )
       
   594             {
       
   595             EMHandleThreadChanged( aThread );
       
   596             }
       
   597         }
       
   598     }
       
   599 
       
   600 
       
   601 void DMemSpyInspectedProcess::EMHandleThreadChanged( DThread& /*aThread*/ )
       
   602     {
       
   603 	Kern::MutexWait( *iLock );
       
   604 
       
   605     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadChanged() - START - this: 0x%08x", this ) );
       
   606 
       
   607     // This is called when a thread is added, changed, or terminated/killed.
       
   608     // We must be careful to only access the members of aThread that still
       
   609     // exist as if it is being destroyed, the object may be in an intermediate
       
   610     // state.
       
   611 	NKern::ThreadEnterCS();
       
   612 
       
   613     // All we are really interested in is recalculating the stack usage
       
   614     // for the process... 
       
   615     iInfoCurrent.iMemoryStack = StackSize( *iProcess );
       
   616 
       
   617     // Always inform observer about new results.
       
   618     CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   619 
       
   620     NKern::ThreadLeaveCS();
       
   621     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadChanged() - END - this: 0x%08x", this ) );
       
   622 
       
   623     Kern::MutexSignal( *iLock );
       
   624     }
       
   625 
       
   626 
       
   627 void DMemSpyInspectedProcess::EMHandleChunkAdd( DChunk& aChunk )
       
   628     {
       
   629 	Kern::MutexWait( *iLock );
       
   630 
       
   631     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - START - this: 0x%08x, aChunk: 0x%08x (%O)", this, &aChunk, &aChunk ) );
       
   632 	NKern::ThreadEnterCS();
       
   633 
       
   634     // Is this chunk related to our process somehow?
       
   635     if  ( IsChunkRelevantToOurProcess( aChunk ) )
       
   636         {
       
   637         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - processes match, checking chunk type..." ) );
       
   638 
       
   639         const TMemSpyTrackedChunk::TType type = ChunkType( &aChunk );
       
   640         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - chunkType: %d", type ) );
       
   641 
       
   642         if  ( type != TMemSpyTrackedChunk::ETypeNotRelevant )
       
   643             {
       
   644             // It's a new entry in our process
       
   645             TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - this: 0x%08x, creating new entry for chunk: 0x%08x", this, &aChunk ) );
       
   646 
       
   647             AddTrackedChunk( &aChunk, type );
       
   648             TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - added chunk..." ));
       
   649 
       
   650             const TBool changeDetected = UpdateStatistics();
       
   651             if  ( changeDetected )
       
   652                 {
       
   653                 // Inform observer about new results.
       
   654                 CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   655                 }
       
   656             }
       
   657         }
       
   658 
       
   659     NKern::ThreadLeaveCS();
       
   660     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - END - this: 0x%08x", this ) );
       
   661 
       
   662     Kern::MutexSignal( *iLock );
       
   663     }
       
   664 
       
   665 
       
   666 void DMemSpyInspectedProcess::EMHandleChunkUpdated( DChunk& aChunk )
       
   667     {
       
   668 	Kern::MutexWait( *iLock );
       
   669 
       
   670     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - START - this: 0x%08x, aChunk: 0x%08x [S: %8d] (%O)", this, &aChunk, aChunk.Size(), &aChunk ) );
       
   671 	NKern::ThreadEnterCS();
       
   672 
       
   673     // Is this chunk mapped into our process?
       
   674     TMemSpyTrackedChunk* trackedEntry = TrackedChunkByHandle( &aChunk );
       
   675     if  ( trackedEntry != NULL )
       
   676         {
       
   677         const TInt oldSize = trackedEntry->Size();
       
   678         const TInt newSize = iDevice.OSAdaption().DChunk().GetSize( aChunk );
       
   679 
       
   680         TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - was tracked entry [0x%08x, size; %10d, type: %d] vs new size: %d", trackedEntry, oldSize, trackedEntry->Type(), newSize ) );
       
   681         
       
   682         // If the existing entry had a size of 0 and the new size is non-zero
       
   683         // then we may have enough data such that we can validate type information.
       
   684         // For example, any secondary heap chunk that is created within the process will
       
   685         // most likely have a Local-NNNNNN style name, and this chunk will be created with
       
   686         // an initial size of zero.
       
   687         //
       
   688         // We can only identify it's type once the chunk has been updated with some data
       
   689         // that supports vTable verification. Hence the type may fluctuate...
       
   690         if  ( oldSize == 0 && newSize > 0 )
       
   691             {
       
   692             TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - checking type again as chunk size was zero..." ) );
       
   693 
       
   694             PrintChunkInfo( aChunk );
       
   695             const TMemSpyTrackedChunk::TType type = ChunkType( &aChunk );
       
   696             if  ( type != trackedEntry->Type() )
       
   697                 {
       
   698                 // Type has changed
       
   699                 TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - type has transitioned from: %d to %d", trackedEntry->Type(), type ) );
       
   700                 trackedEntry->SetType( type );
       
   701                 }
       
   702             }
       
   703 
       
   704         // Update our record with new chunk size
       
   705         trackedEntry->SetSize( newSize );
       
   706 
       
   707         const TBool changeDetected = UpdateStatistics();
       
   708         if  ( changeDetected )
       
   709             {
       
   710             // Inform observer about new results.
       
   711             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   712             }
       
   713         }
       
   714 
       
   715     NKern::ThreadLeaveCS();
       
   716     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - END - this: 0x%08x", this ) );
       
   717 
       
   718     Kern::MutexSignal( *iLock );
       
   719     }
       
   720 
       
   721 
       
   722 void DMemSpyInspectedProcess::EMHandleChunkDeleted( DChunk& aChunk )
       
   723     {
       
   724 	Kern::MutexWait( *iLock );
       
   725 
       
   726     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkDeleted() - START - this: 0x%08x", this ) );
       
   727 	NKern::ThreadEnterCS();
       
   728 
       
   729     // Is this chunk mapped into our process?
       
   730     TMemSpyTrackedChunk* trackedEntry = TrackedChunkByHandle( &aChunk );
       
   731     if ( trackedEntry != NULL )
       
   732         {
       
   733         // Delete entry
       
   734 		trackedEntry->iLink.Deque();
       
   735         delete trackedEntry;
       
   736 
       
   737         const TBool changeDetected = UpdateStatistics();
       
   738         if  ( changeDetected )
       
   739             {
       
   740             // Inform observer about new results.
       
   741             CompleteClientsRequest( KErrNone, &iInfoCurrent );
       
   742             }
       
   743         }
       
   744 
       
   745     NKern::ThreadLeaveCS();
       
   746     TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkDeleted() - END - this: 0x%08x", this ) );
       
   747 
       
   748     Kern::MutexSignal( *iLock );
       
   749     }
       
   750 
       
   751 
       
   752 void DMemSpyInspectedProcess::PrintChunkInfo( DChunk& aChunk ) const
       
   753     {
       
   754     TRACE( Kern::Printf("DMemSpyInspectedProcess::PrintChunkInfo() - iProcess*:           0x%08x", iProcess ) );
       
   755     TRACE( Kern::Printf("DMemSpyInspectedProcess::PrintChunkInfo() - iProcess id:         0x%04x", iProcessId ) );
       
   756     MemSpyDriverUtils::PrintChunkInfo( aChunk, iDevice.OSAdaption() );
       
   757     }
       
   758 
       
   759 
       
   760 TBool DMemSpyInspectedProcess::IsChunkRelevantToOurProcess( DChunk& aChunk ) const
       
   761     {
       
   762     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - START - this: 0x%08x, iProcess: 0x%08x (%4d), aChunk: 0x%08x (%O)", this, iProcess, iProcessId, &aChunk, &aChunk) );
       
   763 
       
   764     TBool relevant = EFalse;
       
   765     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk();
       
   766     //
       
   767     PrintChunkInfo( aChunk );
       
   768     //
       
   769     DProcess* chunkProc = chunkAdaption.GetOwningProcess( aChunk );
       
   770     if  ( chunkProc )
       
   771         {
       
   772         const TUint procId = iDevice.OSAdaption().DProcess().GetId( *chunkProc );
       
   773         TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Owning Process] Comparing chunk pid: 0x%04x with procPid: 0x%04x", this, procId, iProcessId ) );
       
   774         relevant = ( procId == iProcessId );
       
   775         }
       
   776     else if ( chunkAdaption.GetOwner( aChunk ) == iProcess )
       
   777         {
       
   778         TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Owner Match]" ) );
       
   779         relevant = ETrue;
       
   780         }
       
   781     else
       
   782         {
       
   783         const TUint controllingOwnerPid = chunkAdaption.GetControllingOwnerId( aChunk );
       
   784         TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Controlling Owner] Comparing chunk owner: 0x%04x with procPid: 0x%04x", this, controllingOwnerPid, iProcessId ) );
       
   785         relevant = ( controllingOwnerPid == iProcessId );
       
   786         }
       
   787 
       
   788     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - END - this: 0x%08x, relevant: %d", this, relevant ) );
       
   789     return relevant;
       
   790     }
       
   791 
       
   792 
       
   793 TMemSpyTrackedChunk::TType DMemSpyInspectedProcess::ChunkType( DObject* aObject ) const
       
   794     {
       
   795     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - START - this: 0x%08x, iProcess: 0x%08x, aObject: 0x%08x (%O)", this, iProcess, aObject, aObject ) );
       
   796     TMemSpyTrackedChunk::TType ret = TMemSpyTrackedChunk::ETypeNotRelevant;
       
   797 
       
   798     // Firstly, check if it's actually held within the chunk container.
       
   799     if  ( aObject )
       
   800         {
       
   801         DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk();
       
   802         const TObjectType objectType = chunkAdaption.GetObjectType( *aObject );
       
   803         TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - objectType: %d vs EChunk (%d)", objectType, EChunk ) );
       
   804 
       
   805         if  ( objectType == EChunk )
       
   806             {
       
   807             DChunk* chunk = (DChunk*) aObject;
       
   808             //
       
   809             if  ( IsChunkRelevantToOurProcess( *chunk ) )
       
   810                 {
       
   811                 TName name;
       
   812                 TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - getting chunk name..." ) );
       
   813                 chunk->Name( name );
       
   814                 TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - name: %S", &name ) );
       
   815 
       
   816                 // It is definitely owned by this process. That means that
       
   817                 // it could be a heap, or then it's a just some other kind
       
   818                 // of data chunk which our process happens to have created.
       
   819                 //
       
   820                 // The main thread within a process results in the creation
       
   821                 // of a heap called $HEAP, but that isn't the case for other
       
   822                 // secondary (etc) threads.
       
   823                 //
       
   824                 // Only way I can think to identify these is via vTables.
       
   825                 if  ( name == KMemSpyLitDollarDllData )
       
   826                     {
       
   827                     // This chunk contains Dll Global Data for the process
       
   828                     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkGlobalData" ) );
       
   829                     ret = TMemSpyTrackedChunk::ETypeChunkGlobalData;
       
   830                     }
       
   831                 else if ( name == KMemSpyLitDollarDat )
       
   832                     {
       
   833                     // This chunk contains process global data as well as user-side stacks for
       
   834                     // the process. However, we calculate the stacks independently, so we must 
       
   835                     // adjust this later on to remove stack overhead.
       
   836                     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack" ) );
       
   837                     ret = TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack;
       
   838                     }
       
   839                 else if ( IsHeapChunk( *chunk, name ) )
       
   840                     {
       
   841                     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkHeap" ) );
       
   842                     ret = TMemSpyTrackedChunk::ETypeChunkHeap;
       
   843                     }
       
   844                 else
       
   845                     {
       
   846                     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkLocal" ) );
       
   847                     ret = TMemSpyTrackedChunk::ETypeChunkLocal;
       
   848                     }
       
   849                 }
       
   850             else
       
   851                 {
       
   852                 // It's a chunk that is mapped into our process,
       
   853                 // but isn't owned by us. Therefore it is shared by some
       
   854                 // other process.
       
   855                 TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkShared" ) );
       
   856                 ret = TMemSpyTrackedChunk::ETypeChunkShared;
       
   857                 }
       
   858             }
       
   859         }
       
   860 
       
   861     TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - END - this: 0x%08x, ret: %d", this, ret ) );
       
   862     return ret;
       
   863     }
       
   864 
       
   865 
       
   866 TBool DMemSpyInspectedProcess::IsHeapChunk( DChunk& aChunk, const TName& aName ) const
       
   867     {
       
   868     const TUint rHeapVTable = iDevice.RHeapVTable();
       
   869     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, iProcess: 0x%08x, aName: %S, (%O)", this, &aChunk, rHeapVTable, iProcess, &aName, &aChunk ) );
       
   870     
       
   871     // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks).
       
   872     // If it matches RHeap's vtable, we'll treat it as a heap.
       
   873     TBool isHeap = EFalse;
       
   874 
       
   875     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk();
       
   876     TUint8* base = chunkAdaption.GetBase( aChunk );
       
   877     const TInt size = chunkAdaption.GetSize( aChunk );
       
   878     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - base: 0x%08x, size: %d", base, size ) );
       
   879 
       
   880     if  ( iProcess && size >= 4 )
       
   881         {
       
   882         // Chunks are mapped into entire process so any thread within the process is enough...
       
   883         DThread* firstThread = iProcess->FirstThread();
       
   884         TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) );
       
   885         if  ( firstThread != NULL )
       
   886             {
       
   887             TInt err = firstThread->Open();
       
   888             TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - firstThread open result: %d", err ) );
       
   889 
       
   890             if  ( err == KErrNone )
       
   891                 {
       
   892                 TBuf8<4> allocatorVTableBuffer;
       
   893                 err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() );
       
   894                 TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk - read result of vtable data from requested thread is: %d", err ));
       
   895                 //
       
   896                 if  ( err == KErrNone )
       
   897                     {
       
   898                     TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) );
       
   899                     allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() );
       
   900                     
       
   901                     const TUint32 vtable =   allocatorVTableBuffer[0] +
       
   902                                             (allocatorVTableBuffer[1] << 8) + 
       
   903                                             (allocatorVTableBuffer[2] << 16) + 
       
   904                                             (allocatorVTableBuffer[3] << 24);
       
   905                     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) );
       
   906 
       
   907                     // Check the v-table to work out if it really is an RHeap
       
   908                     isHeap = ( vtable == rHeapVTable );
       
   909                     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - isHeap: %d", isHeap ) );
       
   910                     }
       
   911 
       
   912                 TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - closing first thread..." ) );
       
   913             	Kern::SafeClose( (DObject*&) firstThread, NULL );
       
   914                 }
       
   915             }
       
   916         }
       
   917     //
       
   918     if  ( !isHeap && aName == KMemSpyLitDollarHeap )
       
   919         {
       
   920         TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - is standard Symbian OS initial heap chunk - $HEAP" ) );
       
   921         isHeap = ETrue;
       
   922         }
       
   923     //
       
   924     TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) );
       
   925     return isHeap;
       
   926     }
       
   927 
       
   928 
       
   929 TUint32 DMemSpyInspectedProcess::TotalStatistics( const TMemSpyDriverProcessInspectionInfo& aStats, TBool aIncludeShared )
       
   930     {
       
   931     TUint32 total = aStats.iMemoryStack + 
       
   932                     aStats.iMemoryHeap +
       
   933                     aStats.iMemoryChunkLocal + 
       
   934                     aStats.iMemoryGlobalData;
       
   935     //
       
   936     if ( aIncludeShared )
       
   937         {
       
   938         total += aStats.iMemoryChunkShared;
       
   939         }
       
   940     //
       
   941     return total;
       
   942     }
       
   943 
       
   944 
       
   945 TBool DMemSpyInspectedProcess::IsEqual( const TMemSpyDriverProcessInspectionInfo& aLeft, const TMemSpyDriverProcessInspectionInfo& aRight )
       
   946     {
       
   947     const TBool equal = ( aLeft.iMemoryStack == aRight.iMemoryStack &&
       
   948                           aLeft.iMemoryHeap == aRight.iMemoryHeap &&
       
   949                           aLeft.iMemoryChunkLocal == aRight.iMemoryChunkLocal &&
       
   950                           aLeft.iMemoryChunkShared == aRight.iMemoryChunkShared &&
       
   951                           aLeft.iMemoryGlobalData == aRight.iMemoryGlobalData 
       
   952                         );
       
   953     return equal;
       
   954     }
       
   955 
       
   956 
       
   957 void DMemSpyInspectedProcess::ResetStatistics( TMemSpyDriverProcessInspectionInfo& aStats )
       
   958     {
       
   959     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetStatistics() - START - this: 0x%08x", this ) );
       
   960     aStats.iProcessId = iProcessId;
       
   961     aStats.iMemoryHeap = 0;
       
   962     aStats.iMemoryChunkLocal = 0;
       
   963     aStats.iMemoryChunkShared = 0;
       
   964     aStats.iMemoryGlobalData = 0;
       
   965     aStats.iTime = Kern::SystemTime();
       
   966     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetStatistics() - END - this: 0x%08x", this ) );
       
   967     }
       
   968 
       
   969 
       
   970 TBool DMemSpyInspectedProcess::UpdateStatistics()
       
   971     {
       
   972     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - START - this: 0x%08x, iChangeDeliveryCounter: %04d, iProcess: 0x%08x %O", this, iChangeDeliveryCounter, iProcess, iProcess ) );
       
   973 
       
   974     // Preserve last stats so we can identify if something really changed...
       
   975     iInfoLast = iInfoCurrent;
       
   976 
       
   977     // Reset current stats ready for updating. This doesn't wipe the stack field, since
       
   978     // that only changes when some kind of thread event occurs...
       
   979     ResetStatistics( iInfoCurrent );
       
   980     
       
   981     // Go through all tracked chunks and update our stats based upon
       
   982     // their current values...
       
   983     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
   984     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
   985     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
   986     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() CHUNK ENTRIES:" ) );
       
   987     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
   988 	const SDblQueLink* const anchor = &iTrackedChunks.iA;
       
   989 	for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext)
       
   990 		{
       
   991 		TMemSpyTrackedChunk* const trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink );
       
   992         //
       
   993         switch( trackedChunk->Type() )
       
   994             {
       
   995         case TMemSpyTrackedChunk::ETypeChunkHeap:
       
   996             iInfoCurrent.iMemoryHeap += trackedChunk->Size();
       
   997             TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkHeap       - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) );
       
   998             break;
       
   999         case TMemSpyTrackedChunk::ETypeChunkLocal:
       
  1000             iInfoCurrent.iMemoryChunkLocal += trackedChunk->Size();
       
  1001             TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkLocal      - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) );
       
  1002             break;
       
  1003         case TMemSpyTrackedChunk::ETypeChunkShared:
       
  1004             iInfoCurrent.iMemoryChunkShared += trackedChunk->Size();
       
  1005             TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkShared     - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) );
       
  1006             break;
       
  1007         case TMemSpyTrackedChunk::ETypeChunkGlobalData:
       
  1008             iInfoCurrent.iMemoryGlobalData += trackedChunk->Size();
       
  1009             TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkGlobalData - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) );
       
  1010             break;
       
  1011         case TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack:
       
  1012             break;
       
  1013 
       
  1014         default:
       
  1015         case TMemSpyTrackedChunk::ETypeNotRelevant:
       
  1016             break;
       
  1017             }
       
  1018 		}
       
  1019 
       
  1020     const TUint32 totalLastIncShared = TotalStatistics( iInfoLast );
       
  1021     const TUint32 totalLastExcShared = TotalStatistics( iInfoLast, EFalse );
       
  1022     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1023     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1024     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() LAST:" ) );
       
  1025     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1026     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryStack:                   %12d", iInfoLast.iMemoryStack ) );
       
  1027     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryHeap:                    %12d", iInfoLast.iMemoryHeap ) );
       
  1028     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryChunkLocal:              %12d", iInfoLast.iMemoryChunkLocal ) );
       
  1029     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryChunkShared:             %12d", iInfoLast.iMemoryChunkShared ) );
       
  1030     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryGlobalData:              %12d", iInfoLast.iMemoryGlobalData ) );
       
  1031     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - --------------------------------------------------------------------------" ) );
       
  1032     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast total:                          %12d / %12d", totalLastIncShared, totalLastExcShared ) );
       
  1033     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1034     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1035 
       
  1036 
       
  1037     const TUint32 totalCurrentIncShared = TotalStatistics( iInfoCurrent );
       
  1038     const TUint32 totalCurrentExcShared = TotalStatistics( iInfoCurrent, EFalse );
       
  1039     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() CURRENT:" ) );
       
  1040     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1041     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryStack:                %12d", iInfoCurrent.iMemoryStack ) );
       
  1042     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryHeap:                 %12d", iInfoCurrent.iMemoryHeap ) );
       
  1043     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryChunkLocal:           %12d", iInfoCurrent.iMemoryChunkLocal ) );
       
  1044     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryChunkShared:          %12d", iInfoCurrent.iMemoryChunkShared ) );
       
  1045     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryGlobalData:           %12d", iInfoCurrent.iMemoryGlobalData ) );
       
  1046     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - --------------------------------------------------------------------------" ) );
       
  1047     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent total:                       %12d / %12d", totalCurrentIncShared, totalCurrentExcShared ) );
       
  1048     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1049     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1050 
       
  1051     // Update peaks, i.e. how large each individual element reached
       
  1052     const TUint32 totalPeaks = TotalStatistics( iInfoPeaks );
       
  1053     iInfoPeaks.iMemoryStack = Max( iInfoPeaks.iMemoryStack, iInfoCurrent.iMemoryStack );
       
  1054     iInfoPeaks.iMemoryHeap = Max( iInfoPeaks.iMemoryHeap, iInfoCurrent.iMemoryHeap );
       
  1055     iInfoPeaks.iMemoryChunkLocal = Max( iInfoPeaks.iMemoryChunkLocal, iInfoCurrent.iMemoryChunkLocal );
       
  1056     iInfoPeaks.iMemoryChunkShared = Max( iInfoPeaks.iMemoryChunkShared, iInfoCurrent.iMemoryChunkShared );
       
  1057     iInfoPeaks.iMemoryGlobalData = Max( iInfoPeaks.iMemoryGlobalData, iInfoCurrent.iMemoryGlobalData );
       
  1058     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() PEAK:" ) );
       
  1059     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1060     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryStack:                  %12d", iInfoPeaks.iMemoryStack ) );
       
  1061     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryHeap:                   %12d", iInfoPeaks.iMemoryHeap ) );
       
  1062     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryChunkLocal:             %12d", iInfoPeaks.iMemoryChunkLocal ) );
       
  1063     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryChunkShared:            %12d", iInfoPeaks.iMemoryChunkShared ) );
       
  1064     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryGlobalData:             %12d", iInfoPeaks.iMemoryGlobalData ) );
       
  1065     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) );
       
  1066     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks total:                         %12d", totalPeaks ) );
       
  1067     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1068     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1069 
       
  1070     // Update HWM, i.e. the largest total so far.
       
  1071     const TUint32 totalHWMIncShared = TotalStatistics( iInfoHWMIncShared );
       
  1072     const TUint32 totalHWMExcShared = TotalStatistics( iInfoHWMIncShared, EFalse );
       
  1073     if  ( totalCurrentIncShared > totalHWMIncShared )
       
  1074         {
       
  1075         iInfoHWMIncShared = iInfoCurrent;
       
  1076         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() HWM INC SHARED:" ) );
       
  1077         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1078         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryStack:           %12d", iInfoHWMIncShared.iMemoryStack ) );
       
  1079         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryHeap:            %12d", iInfoHWMIncShared.iMemoryHeap ) );
       
  1080         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryChunkLocal:      %12d", iInfoHWMIncShared.iMemoryChunkLocal ) );
       
  1081         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryChunkShared:     %12d", iInfoHWMIncShared.iMemoryChunkShared ) );
       
  1082         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryGlobalData:      %12d", iInfoHWMIncShared.iMemoryGlobalData ) );
       
  1083         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) );
       
  1084         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared total:                  %12d", totalHWMIncShared ) );
       
  1085         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1086         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1087         }
       
  1088     if  ( totalCurrentExcShared > totalHWMExcShared )
       
  1089         {
       
  1090         iInfoHWMExcShared = iInfoCurrent;
       
  1091         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() HWM EXC SHARED:" ) );
       
  1092         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1093         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryStack:           %12d", iInfoHWMExcShared.iMemoryStack ) );
       
  1094         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryHeap:            %12d", iInfoHWMExcShared.iMemoryHeap ) );
       
  1095         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryChunkLocal:      %12d", iInfoHWMExcShared.iMemoryChunkLocal ) );
       
  1096         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryChunkShared:     %12d", iInfoHWMExcShared.iMemoryChunkShared ) );
       
  1097         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryGlobalData:      %12d", iInfoHWMExcShared.iMemoryGlobalData ) );
       
  1098         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) );
       
  1099         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared total:                  %12d", totalHWMExcShared ) );
       
  1100         }
       
  1101 
       
  1102     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1103     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) );
       
  1104 
       
  1105     // Work out if something changed...
       
  1106     const TBool statsChanged = !IsEqual( iInfoLast, iInfoCurrent );
       
  1107     if  ( statsChanged )
       
  1108         {
       
  1109         TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - STATS CHANGED!" ) );
       
  1110         }
       
  1111 
       
  1112     TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - END - this: 0x%08x, statsChanged: %d, iChangeDeliveryCounter: %04d, iProcess: 0x%08x %O", this, statsChanged, iChangeDeliveryCounter, iProcess, iProcess ) );
       
  1113     return statsChanged;
       
  1114     }
       
  1115 
       
  1116 
       
  1117 void DMemSpyInspectedProcess::FindChunks( DProcess& aProcess )
       
  1118     {
       
  1119     TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - START - this: 0x%08x", this ) );
       
  1120   
       
  1121     DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk();
       
  1122     DMemSpyDriverOSAdaptionDProcess& processAdaption = iDevice.OSAdaption().DProcess();
       
  1123 
       
  1124     // Iterate through each handle in the process
       
  1125     if  ( processAdaption.IsHandleIndexValid( aProcess ) )
       
  1126         {
       
  1127 	    MemSpyObjectIx* processHandles = processAdaption.GetHandles( aProcess );
       
  1128         MemSpyObjectIx_Wait( processHandles );
       
  1129 
       
  1130         const TInt count = processHandles->Count();
       
  1131         TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - got: %d handles...", count ) );
       
  1132 
       
  1133 	    for( TInt i=0; i<count; i++ )
       
  1134     	    {
       
  1135             TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - checking handle index: %2d", i ) );
       
  1136 
       
  1137     	    // Get a handle from the process container...
       
  1138             NKern::LockSystem();
       
  1139     	    DObject* object = (*processHandles)[ i ];
       
  1140             NKern::UnlockSystem();
       
  1141 
       
  1142             const TObjectType objectType = ( object ? chunkAdaption.GetObjectType( *object ) : EObjectTypeAny );
       
  1143             TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - object: 0x%08x, type: %2d (%O)", object, objectType, object ) );
       
  1144 
       
  1145             // Is it a chunk that is already mapped into our process?
       
  1146             // See if we're already aware of this chunk...
       
  1147             if  ( object != NULL && objectType == EChunk )
       
  1148                 {
       
  1149                 TMemSpyTrackedChunk* existingEntry = TrackedChunkByHandle( object );
       
  1150                 TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - found a chunk, existing lookup entry: 0x%08x", existingEntry ) );
       
  1151 
       
  1152                 if  ( existingEntry != NULL )
       
  1153                     {
       
  1154                     const TInt cSize = chunkAdaption.GetSize( *existingEntry->iChunk );
       
  1155                     TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - setting existing entry size to: %d", cSize ) );
       
  1156 
       
  1157                     // It must be a chunk then... Update size
       
  1158                     existingEntry->SetSize( cSize );
       
  1159 
       
  1160                     // This item is in use, i.e. it is not unused
       
  1161                     existingEntry->SetUnused( EFalse );
       
  1162                     }
       
  1163                 else
       
  1164                     {
       
  1165                     DChunk* chunk = (DChunk*) object;
       
  1166                     TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - chunk not known, checking type..." ) );
       
  1167 
       
  1168                     // We have no record of this item so far. Is it really a chunk?
       
  1169                     const TMemSpyTrackedChunk::TType type = ChunkType( object );
       
  1170                     TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - type is: %d", type ) );
       
  1171 
       
  1172                     if  ( type != TMemSpyTrackedChunk::ETypeNotRelevant )
       
  1173                         {
       
  1174                         // It's a new entry
       
  1175                         TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - this: 0x%08x, creating new entry for chunk: 0x%08x", this, chunk ) );
       
  1176 
       
  1177                         AddTrackedChunk( chunk, type );
       
  1178                         TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - added chunk..." ));
       
  1179                         }
       
  1180                     }
       
  1181                 }
       
  1182     	    }
       
  1183 
       
  1184         MemSpyObjectIx_Signal( processHandles );
       
  1185         }
       
  1186 
       
  1187     TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - END - this: 0x%08x", this ) );
       
  1188     }
       
  1189     
       
  1190     
       
  1191 TInt DMemSpyInspectedProcess::StackSize( DProcess& aProcess )
       
  1192     {
       
  1193     TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - START - this: 0x%08x", this ) );
       
  1194     TInt ret = 0;
       
  1195     //
       
  1196     DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread();
       
  1197 
       
  1198     iUserThreadStackSize = 0;
       
  1199     //
       
  1200 	SDblQueLink* pLink = aProcess.iThreadQ.First();
       
  1201 	while(pLink != &aProcess.iThreadQ.iA)
       
  1202 		{
       
  1203 		DThread* pT = _LOFF( pLink, DThread, iProcessLink );
       
  1204         //
       
  1205         const TUint32 userStackSize = dThreadAdaption.GetUserStackSize( *pT );
       
  1206         const TUint32 suprStackSize = dThreadAdaption.GetSupervisorStackSize( *pT );
       
  1207         TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - thread: 0x%08x, userStack: %8d, suprStack: %8d, total: %8d %O", pT, userStackSize, suprStackSize, userStackSize + suprStackSize, pT ));
       
  1208         //
       
  1209         iUserThreadStackSize += userStackSize;
       
  1210 		ret += userStackSize + suprStackSize;
       
  1211         //
       
  1212 		pLink = pLink->iNext;
       
  1213 		}
       
  1214 	//
       
  1215     TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - END - this: 0x%08x, total stack size for process: %8d, iUserThreadStackSize: %8d", this, ret, iUserThreadStackSize ) );
       
  1216 	return ret;
       
  1217     }
       
  1218 
       
  1219 
       
  1220 void DMemSpyInspectedProcess::ResetPendingChanges()
       
  1221     {
       
  1222     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetPendingChanges() - START - this: 0x%08x", this ) );
       
  1223     NKern::ThreadEnterCS();
       
  1224     //
       
  1225     SDblQueLink* link = iPendingChanges.GetFirst();
       
  1226 	while( link )
       
  1227 		{
       
  1228         TMemSpyTrackedChunkChangeInfo* cachedChange = _LOFF( link, TMemSpyTrackedChunkChangeInfo, iLink );
       
  1229         delete cachedChange;
       
  1230         link = iPendingChanges.GetFirst();
       
  1231 		}
       
  1232     //
       
  1233     NKern::ThreadLeaveCS();
       
  1234     TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetPendingChanges() - END - this: 0x%08x", this ) );
       
  1235     }
       
  1236 
       
  1237 
       
  1238 
       
  1239 
       
  1240 
       
  1241 
       
  1242 
       
  1243 
       
  1244 
       
  1245 
       
  1246 
       
  1247 
       
  1248 TMemSpyTrackedChunk::TMemSpyTrackedChunk( DChunk* aChunk, TType aType )
       
  1249 :   iChunk( aChunk ), iType( aType ), iSize( 0 ), iUnused( EFalse )
       
  1250     {
       
  1251     }
       
  1252 
       
  1253 
       
  1254 void TMemSpyTrackedChunk::SetSize( TInt aSize )
       
  1255     {
       
  1256     iSize = aSize;
       
  1257     }
       
  1258 
       
  1259 
       
  1260 void TMemSpyTrackedChunk::SetUnused( TBool aUnused )
       
  1261     {
       
  1262     iUnused = aUnused;
       
  1263     }
       
  1264