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