piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp
branchRCL_3
changeset 13 da2cedce4920
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/GeneralsPlugin/src/MemSamplerImpl.cpp	Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,976 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#include <piprofiler/ProfilerVersion.h>
+#include <piprofiler/ProfilerTraces.h>
+
+#include <kern_priv.h>
+#include <plat_priv.h>
+
+#include "MemSamplerImpl.h"
+
+// for testing precise stack utilization tracing...
+// crashes at the moment
+
+#include <nk_cpu.h>
+
+#if !defined(__NKERN_H__)
+#include <nkern.h>
+#endif 
+
+#define TAG(obj) (*(TUint32*)&(obj->iAsyncDeleteNext))
+#define PROFILER_CHUNK_MARK		((TUint32)0x00001000)
+#define PROFILER_MEM_THREAD_MARK	((TUint32)0x00000001)
+#define PROFILER_LIBRARY_MARK    ((TUint32)0x10000000)
+#define PROFILER_MEM_THREAD_UNMARK  ~PROFILER_MEM_THREAD_MARK
+
+#ifdef MEM_EVENT_HANDLER
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+_LIT8(KMemVersion,"2.03");
+#else
+_LIT8(KMemVersion, "2.02");
+#endif
+#else
+_LIT8(KMemVersion, "1.56");
+#endif
+
+DMemSamplerImpl::DMemSamplerImpl() :
+	sampleDescriptor(&(this->sample[1]),0,256)
+    {
+    LOGSTRING("MemSamplerImpl::MemSamplerImpl() - konstruktori");
+
+	iCount = 0;
+		
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+	iSampleType = ESampleThreads;
+#else
+	iSampleThreads = true;
+#endif
+	iTimeToSample = false;
+	
+	iTotalMemoryOk = false;
+	iTotalMemoryNameOk = false;
+	
+	iNewChunkCount = 0;
+	iChunkCount = 0;
+	iChunksProcessing = ENothingToProcess;
+    iThreadsProcessing = ENothingToProcess;
+	
+	iNewThreadCount = 0;
+	iThreadCount = 0;
+	
+	// reset data structures
+    for(TInt i(0);i<KProfilerMaxChunksAmount;i++)
+        {
+        // heap chunks
+        this->heapChunksToSample[i] = 0;
+        this->heapChunkNamesToReport[i] = 0;
+        }
+    
+    for(TInt i(0);i<KProfilerMaxThreadsAmount;i++)
+        {
+        // threads
+        this->threadsToSample[i] = 0;
+        this->threadNamesToReport[i] = 0;
+        }
+    
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+    iLibrariesProcessing = ENothingToProcess;
+    iNewLibraryCount = 0;
+    iLibraryCount = 0;
+    
+    for(TInt i(0); i<KProfilerMaxLibrariesAmount; i++)
+        {
+        // libraries
+        this->librariesToSample[i] = 0;
+        this->libraryNamesToReport[i] = 0;
+        }
+#endif
+
+    }
+
+DMemSamplerImpl::~DMemSamplerImpl()
+    {
+
+    }
+
+TInt DMemSamplerImpl::CreateFirstSample()
+    {
+    LOGSTRING("MemSamplerImpl::CreateFirstSample - entry");
+	
+	this->sampleDescriptor.Zero();
+	this->sampleDescriptor.Append(_L8("Bappea_V"));
+	this->sampleDescriptor.Append(KMemVersion);
+	this->sampleDescriptor.Append(_L8("_MEM"));
+	
+	sample[0] = this->sampleDescriptor.Size();
+
+	LOGSTRING("MemSamplerImpl::CreateFirstSample - exit");
+
+	return (TInt)(sample[0]+1);
+    }
+
+TBool DMemSamplerImpl::SampleNeeded()
+    {
+	iCount++;
+#ifdef MEM_EVENT_HANDLER
+    // make the collection of chunks/threads only once, rest will be collected with mem event handler
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+	if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv3) == 0))
+#else
+    if (iCount <= iMemSamplingPeriod && ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0))
+#endif
+#else
+	if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0)
+#endif
+	    {
+        LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount);
+		iTimeToSample = true;
+		return true;
+        }
+	else 
+	    {
+		return false;
+        }
+
+    }
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+TInt DMemSamplerImpl::SampleImpl()
+    {    
+    // Sample threads:
+    if( iSampleType == ESampleThreads )
+        {    
+        if(this->iThreadsProcessing == ENothingToProcess )
+            {     
+            if(!iTimeToSample)
+                {
+                return 0;
+                }
+            else
+                {
+                iTimeToSample = false;
+                // gather first all thread stacks
+                return GatherThreads();
+                }
+            }
+        else
+            {
+            // process now thread stack list
+            TInt length = this->ProcessThreads();
+
+            if(length == 0)
+                {
+                this->iThreadsProcessing = ENothingToProcess;
+                // switch to collect chunk data
+                iSampleType = ESampleChunks;
+                }
+            return length;
+            }
+        }
+
+    // Sample chunks:
+    if( iSampleType == ESampleChunks )
+        {
+        if(this->iChunksProcessing == ENothingToProcess)
+            {
+            if(!iTimeToSample)
+                {
+                return 0;
+                }
+            else
+                {
+                iTimeToSample = false;
+                // gather first all chunks
+                return GatherChunks();
+                }
+            }
+        else
+            {
+            // still something to go through in lists
+            TInt length = this->ProcessChunks();
+        
+            if(length == 0) 
+            {
+                this->iChunksProcessing = ENothingToProcess;
+                // switch to collect library data
+                iSampleType = ESampleLibraries;
+                //iSampleThreads = true;
+            }
+            return length;
+            }
+        }
+        
+    // Sample libraries:
+    if( iSampleType == ESampleLibraries )
+        {
+        if(this->iLibrariesProcessing == ENothingToProcess )
+            {        
+            if(!iTimeToSample)
+                {             
+                return 0;
+                }
+            else
+                {
+                iTimeToSample = false;
+                // gather libraries
+                return GatherLibraries();
+                }
+            }
+        else
+            {
+            // process now thread stack list
+            TInt length = this->ProcessLibraries();
+            if(length == 0)
+                {
+                this->iLibrariesProcessing = ENothingToProcess;
+                // switch to collect chunk data
+                iSampleType = ESampleThreads;
+                }
+            return length;
+            }
+        }
+
+    // should not reach this point...
+    return 0;
+    }
+#else
+TInt DMemSamplerImpl::SampleImpl()
+    {
+    // check if either chunk or thread lists have unprocessed items
+    if(this->iChunksProcessing == ENothingToProcess && !iSampleThreads)
+        {
+        if(!iTimeToSample)
+            {
+            return 0;
+            }
+        else
+            {
+            iTimeToSample = false;
+            // gather first all chunks
+            return GatherChunks();
+            }
+        }
+    else if(!iSampleThreads)
+        {
+        // still something to go through in lists
+        TInt length = this->ProcessChunks();
+        
+        if(length == 0) 
+            {
+            this->iChunksProcessing = ENothingToProcess;
+            // switch to collect thread data
+            iSampleThreads = true;
+            }
+        return length;
+        }
+    
+    if(this->iThreadsProcessing == ENothingToProcess && iSampleThreads)
+        {
+        if(!iTimeToSample)
+            {
+            return 0;
+            }
+        else
+            {
+            iTimeToSample = false;
+            // gather first all thread stacks
+            return GatherThreads();
+            }
+        }
+    
+    else if(iSampleThreads)
+        {
+        // process now thread stack list
+        TInt length = this->ProcessThreads();
+
+        if(length == 0)
+            {
+            this->iThreadsProcessing = ENothingToProcess;
+            // switch to collect chunk data
+            iSampleThreads = false;
+            }
+        return length;
+        }
+
+    // should not reach this point...
+    return 0;
+    }
+#endif
+
+inline TInt DMemSamplerImpl::GatherChunks()
+    {
+    // encode a process binary
+    name.Zero();
+    
+    NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
+    DObjectCon& chunks = *Kern::Containers()[EChunk];
+    chunks.Wait();  // Obtain the container mutex so the list does get changed under us
+    
+    this->iChunkCount = 0; 
+    this->iNewChunkCount = 0;
+    this->iTotalMemoryOk = false;
+    TInt totalChunkCount(chunks.Count());
+    DChunk* c; 
+    
+    for(TInt i(0);i<totalChunkCount;i++)
+        {
+        c = (DChunk*)(chunks)[i];
+
+        LOGSTRING3("Processing chunk %d, tag: 0x%x",i,TAG(c));
+        
+        if( (TAG(c) & 0x0000ffff) != PROFILER_CHUNK_MARK)
+            {
+            LOGSTRING4("Marking chunk %d/%d, old tag 0x%x",i,(totalChunkCount-1), TAG(c));
+            // this chunk has not been tagged yet
+            name.Zero();
+            c->TraceAppendName(name,false);
+            const TUint8* ptr = name.Ptr();
+            
+            TAG(c) = (PROFILER_CHUNK_MARK);
+            this->heapChunkNamesToReport[iNewChunkCount] = c;
+            iNewChunkCount++;
+            }
+
+        // the chunk has been tagged, add heap chunks to the list
+        this->heapChunksToSample[this->iChunkCount] = c;
+        this->iChunkCount++;
+        LOGSTRING2("Added chunk %d to Chunks",i);
+        }
+
+    if(this->iChunkCount > 0 || this->iNewChunkCount > 0)
+        {
+        this->iChunksProcessing = EStartingToProcess;
+        
+        // process the first sample
+        TInt length = this->ProcessChunks();
+        
+        if(length == 0)
+            {
+            this->iChunksProcessing = ENothingToProcess;
+            }
+    
+        chunks.Signal();  // Release the container mutex
+        NKern::ThreadLeaveCS();  // End of critical section
+        return length;
+        }
+
+    LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
+    chunks.Signal();  // Release the container mutex
+    NKern::ThreadLeaveCS();  // End of critical section
+    return 0;
+    }
+
+inline TInt DMemSamplerImpl::GatherThreads()
+    {
+    // The thread memory consumption
+    
+    NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
+    DObjectCon& threads = *Kern::Containers()[EThread];
+    threads.Wait(); // Obtain the container mutex so the list does get changed under us
+    
+    this->iThreadCount = 0; 
+    this->iNewThreadCount = 0;
+    this->iTotalMemoryOk = false;           
+
+    TInt totalThreadCount = threads.Count();
+
+    for(TInt i(0);i<totalThreadCount;i++)
+        {
+        DThread* t = (DThread*)(threads)[i];
+
+        LOGSTRING3("Processing thread %d, tag: 0x%x",i,TAG(t));
+
+        if( (TAG(t) & PROFILER_MEM_THREAD_MARK) == 0)
+            {
+            LOGSTRING4("Marking thread %d/%d, old tag 0x%x",i,(totalThreadCount-1), TAG(t));
+            // this thread's chunk has not been reported yet
+            this->threadNamesToReport[iNewThreadCount] = t;
+            iNewThreadCount++;
+            // tag the thread
+            TAG(t) |= PROFILER_MEM_THREAD_MARK;
+            }
+
+        // the chunk has been tagged, add heap chunks to the list
+        this->threadsToSample[this->iThreadCount] = t;
+        this->iThreadCount++;
+        LOGSTRING2("Added thread %d to threads to sample",i);
+        }
+    
+    if(this->iThreadCount > 0 || this->iNewThreadCount > 0)
+        {
+        this->iThreadsProcessing = EStartingToProcess;
+        
+        // process the first sample
+        TInt length = this->ProcessThreads();
+        
+        if(length == 0)
+            {
+            this->iThreadsProcessing = ENothingToProcess;
+            }
+        threads.Signal();  // Release the container mutex
+        NKern::ThreadLeaveCS();  // End of critical section
+        return length;
+        }
+    
+    LOGTEXT("MemSamplerImpl::SampleImpl - Error, no threads"); 
+    threads.Signal();  // Release the container mutex
+    NKern::ThreadLeaveCS();  // End of critical section
+    return 0;
+    }
+
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+
+inline TInt DMemSamplerImpl::GatherLibraries()
+    {
+    LOGTEXT("MemSamplerImpl::GatherLibraries() - entry");
+    // encode a process binary
+    name.Zero();
+    
+    NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
+    DObjectCon& libs = *Kern::Containers()[ELibrary];
+    libs.Wait();  // Obtain the container mutex so the list does get changed under us
+    
+    this->iLibraryCount = 0; 
+    this->iNewLibraryCount = 0;
+    this->iTotalMemoryOk = false;
+    TInt totalLibCount(libs.Count());
+    DLibrary* l; 
+    
+    for(TInt i(0);i<totalLibCount;i++)
+        {
+        l = (DLibrary*)(libs)[i];
+
+        LOGSTRING3("Processing library %d, tag: 0x%x",i,TAG(l));
+        
+        if( (TAG(l) & 0xffffffff) != PROFILER_LIBRARY_MARK)
+            {
+            LOGSTRING4("Marking library %d/%d, old tag 0x%x",i,(totalLibCount-1), TAG(l));
+            // this library has not been tagged yet
+            name.Zero();
+            l->TraceAppendName(name,false);
+            const TUint8* ptr = name.Ptr();
+            
+            TAG(l) = (PROFILER_LIBRARY_MARK);
+            this->libraryNamesToReport[iNewLibraryCount] = l;
+            iNewLibraryCount++;
+            }
+
+        // the library has been tagged, add library to the list
+        this->librariesToSample[this->iLibraryCount] = l;
+        this->iLibraryCount++;
+        LOGSTRING2("Added library %d to Libraries",i);
+        }
+
+    if(this->iLibraryCount > 0 || this->iNewLibraryCount > 0)
+        {
+        this->iLibrariesProcessing = EStartingToProcess;
+        
+        // process the first sample
+        TInt length = this->ProcessLibraries();
+        
+        if(length == 0)
+            {
+            this->iLibrariesProcessing = ENothingToProcess;
+            }
+    
+        libs.Signal();  // Release the container mutex
+        NKern::ThreadLeaveCS();  // End of critical section
+        return length;
+        }
+
+    LOGTEXT("MemSamplerImpl::SampleImpl - Error, no libraries"); 
+    libs.Signal();  // Release the container mutex
+    NKern::ThreadLeaveCS();  // End of critical section
+    return 0;
+    }
+#endif
+
+inline TInt DMemSamplerImpl::ProcessChunks()
+    {
+    if(iNewChunkCount > 0)
+        {
+        if(this->iChunksProcessing == EStartingToProcess)
+            {
+            // this is the first sample, encode a code for names
+            this->iChunksProcessing = EProcessingNames;
+            return EncodeNameCode();
+            }
+
+        if(iTotalMemoryNameOk == false)
+            {
+            return EncodeTotalMemoryName();
+            }
+        
+        // there are new chunk names to report
+        iNewChunkCount--;
+        DChunk* c = this->heapChunkNamesToReport[iNewChunkCount];
+        return EncodeChunkName(*c);
+        
+        }
+    else if(iChunkCount > 0)
+        {
+        if(this->iChunksProcessing == EProcessingNames || this->iChunksProcessing == EStartingToProcess)
+            {
+            // this is the first data sample, encode a code for data
+            this->iChunksProcessing = EProcessingData;
+            return EncodeDataCode();
+            }
+        
+        if(this->iTotalMemoryOk == false)
+            {
+            return EncodeTotalMemory();	
+            }
+
+        // there are no new chunks to report
+        // thus generate the real report
+        iChunkCount--;
+        DChunk* c = this->heapChunksToSample[iChunkCount];
+        return EncodeChunkData(*c);
+        }
+    else
+        {
+        // everything is processed
+        LOGSTRING2(" Chunks processed! Chunk count = %d", iChunkCount);
+#ifdef MEM_EVENT_HANDLER
+        this->iChunksGathered = true;
+        Kern::Printf("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount);
+#endif
+        return 0;
+        }
+    }
+
+inline TInt DMemSamplerImpl::ProcessThreads()
+    {
+
+    if(iNewThreadCount > 0)
+        {
+        if(this->iThreadsProcessing == EStartingToProcess)
+            {
+            // this is the first sample, encode a code for names
+            this->iThreadsProcessing = EProcessingNames;
+            return EncodeNameCode();
+            }
+        
+        if(iTotalMemoryNameOk == false)
+            {
+            return EncodeTotalMemoryName();
+            }
+
+        iNewThreadCount--;
+        DThread* t = this->threadNamesToReport[iNewThreadCount];
+        return EncodeChunkName(*t);
+        }
+    else if(iThreadCount > 0)
+        {
+        if(this->iThreadsProcessing == EProcessingNames || this->iThreadsProcessing == EStartingToProcess)
+            {
+            // this is the first data sample, encode a code for data
+            this->iThreadsProcessing = EProcessingData;
+            return EncodeDataCode();
+            }
+
+        if(this->iTotalMemoryOk == false)
+            {
+            return EncodeTotalMemory(); 
+            }
+
+        // there are no new threads to report
+        // thus generate the real report
+        iThreadCount--;
+        DThread* t = this->threadsToSample[iThreadCount];
+        return EncodeChunkData(*t);
+        }
+    else
+        {   
+        // everything is processed
+        LOGSTRING2(" Threads processed! Thread count = %d", iThreadCount);
+#ifdef MEM_EVENT_HANDLER
+        this->iThreadsGathered = true;
+        Kern::Printf("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount);
+#endif
+        return 0;
+        }
+    }
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+inline TInt DMemSamplerImpl::ProcessLibraries()
+    {
+    LOGTEXT("ProcessLibraries - entry");
+    if(iNewLibraryCount > 0)
+        {
+        if(this->iLibrariesProcessing == EStartingToProcess)
+            {
+            // this is the first sample, encode a code for names
+            this->iLibrariesProcessing = EProcessingNames;
+            return EncodeNameCode();
+            }
+
+        if(iTotalMemoryNameOk == false)
+            {
+            return EncodeTotalMemoryName();
+            }
+        
+        // there are new library names to report
+        iNewLibraryCount--;
+        DLibrary* l = this->libraryNamesToReport[iNewLibraryCount];
+        return EncodeChunkName(*l);
+        
+        }
+    else if(iLibraryCount > 0)
+        {
+        if(this->iLibrariesProcessing == EProcessingNames || this->iLibrariesProcessing == EStartingToProcess)
+            {
+            // this is the first data sample, encode a code for data
+            this->iLibrariesProcessing = EProcessingData;
+            return EncodeDataCode();
+            }
+        
+        if(this->iTotalMemoryOk == false)
+            {
+            return EncodeTotalMemory(); 
+            }
+
+        // there are no new libraries to report
+        // thus generate the real report
+        iLibraryCount--;
+        DLibrary* l = this->librariesToSample[iLibraryCount];
+        return EncodeChunkData(*l);
+        }
+    else
+        {
+        // everything is processed
+        LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount);
+
+        this->iLibrariesGathered = true;
+        Kern::Printf("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount);
+
+        return 0;
+        }
+    }
+#endif
+inline TInt DMemSamplerImpl::EncodeNameCode()
+    {
+	sample[0] = 1;
+	sample[1] = 0xaa;
+	return 2;
+    }
+
+inline TInt DMemSamplerImpl::EncodeDataCode()
+    {
+	sample[0] = 1;
+	sample[1] = 0xdd;
+	return 2;
+    }
+
+inline TInt DMemSamplerImpl::EncodeTotalMemoryName()
+    {
+	this->iTotalMemoryNameOk = true;
+	
+	TUint8* size = &sample[0];
+	*size = 0;
+		
+	// encode name
+	this->sampleDescriptor.Zero();
+	this->sampleDescriptor.Append(_L("TOTAL_MEMORY"));
+	*size += this->sampleDescriptor.Size();
+		
+	// add id here
+	TUint32 id(0xbabbeaaa);
+	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
+	*size += sizeof(TUint32);
+	
+	// the size is the descriptor length + the size field
+	return ((TInt)(*size))+1;	
+    }
+
+inline TInt DMemSamplerImpl::EncodeTotalMemory()
+    {	
+	
+	TUint8* size = &sample[0];
+	*size = 0;
+
+	NKern::LockSystem();
+	TInt freeRam = Kern::FreeRamInBytes();
+	TInt totalRam = Kern::SuperPage().iTotalRamSize;
+	NKern::UnlockSystem();
+
+	this->sampleDescriptor.Zero();
+	
+	TUint32 id(0xbabbeaaa);
+	TInt zero(0);
+		
+	this->sampleDescriptor.Append((TUint8*)&(id),sizeof(TUint32));
+	*size += sizeof(TUint);
+	
+	this->sampleDescriptor.Append((TUint8*)&(totalRam),sizeof(TInt));
+	*size += sizeof(TInt);
+		
+	// append the cell amount allocated
+	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+	*size += sizeof(TInt);
+	
+	// append the chunk size
+	this->sampleDescriptor.Append((TUint8*)&(freeRam),sizeof(TInt));
+	*size += sizeof(TInt);
+		
+	// append the thread user stack size
+	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+	*size += sizeof(TInt);
+
+	this->iTotalMemoryOk = true;
+
+	return ((TInt)(*size))+1;
+    }
+
+inline TInt DMemSamplerImpl::EncodeChunkName(DChunk& c)
+    {	
+	// the size of the following name is in the first byte
+	TUint8* size = &sample[0];
+	*size = 0;
+		
+	// encode chunk name
+	this->sampleDescriptor.Zero();
+	this->sampleDescriptor.Append(_L("C_"));
+	c.TraceAppendFullName(this->sampleDescriptor,false);
+	*size += this->sampleDescriptor.Size();
+		
+	// add chunk object address here
+	TUint32 chunkAddr((TUint32)&c);
+	this->sampleDescriptor.Append((TUint8*)&(chunkAddr),sizeof(TUint32));
+	*size += sizeof(TUint32);
+
+	// the size is the descriptor length + the size field
+	LOGSTRING2("Non-Heap Chunk Name - %d",*size);
+	return ((TInt)(*size))+1;			
+    }
+
+inline TInt DMemSamplerImpl::EncodeChunkName(DThread& t)
+    {		
+	// the size of the following name is in the first byte
+	TUint8* size = &sample[0];
+	*size = 0;
+	this->sampleDescriptor.Zero();
+	
+	this->sampleDescriptor.Append(_L("T_"));
+	t.TraceAppendFullName(this->sampleDescriptor,false);
+	*size += this->sampleDescriptor.Size();
+	
+	// copy the 4 bytes from the thread id field
+	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
+	*size += sizeof(TUint);
+
+	// the size is the descriptor length + the size field
+	LOGSTRING2("Name - %d",*size);
+	return ((TInt)(*size))+1;
+    }
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+inline TInt DMemSamplerImpl::EncodeChunkName(DLibrary& l)
+    {   
+    // the size of the following name is in the first byte
+    TUint8* size = &sample[0];
+    *size = 0;
+        
+    // encode library name
+    this->sampleDescriptor.Zero();
+    this->sampleDescriptor.Append(_L("L_"));
+    l.TraceAppendFullName(this->sampleDescriptor,false);
+    *size += this->sampleDescriptor.Size();
+        
+    // add chunk object address here
+    TUint32 libAddr((TUint32)&l);
+    this->sampleDescriptor.Append((TUint8*)&(libAddr),sizeof(TUint32));
+    *size += sizeof(TUint32);
+
+    // the size is the descriptor length + the size field
+    LOGSTRING2("Name - %d",*size);
+    return ((TInt)(*size))+1;           
+    }
+#endif
+inline TInt DMemSamplerImpl::EncodeChunkData(DChunk& c)
+    {
+	// the size of the following name is in the first byte
+	TUint8* size = &sample[0];
+	*size = 0;
+	this->sampleDescriptor.Zero();
+	TInt zero(0);
+
+	TUint32 address((TUint32)&c);
+		
+	this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
+	*size += sizeof(TUint);
+	
+	// copy the total amount of memory allocated
+	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TInt));
+	*size += sizeof(TInt);
+		
+	// append the cell amount allocated
+	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+	*size += sizeof(TInt);
+	
+	// append the chunk size
+	this->sampleDescriptor.Append((TUint8*)&(c.iSize),sizeof(TUint));
+	*size += sizeof(TUint);
+		
+	// append the thread user stack size
+	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+	*size += sizeof(TInt);
+
+	LOGSTRING2("Data - %d",*size);
+	return ((TInt)(*size))+1;
+
+    }
+
+inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t)
+    {
+	LOGTEXT("MemSamplerImpl::EncodeChunkData - entry");
+	//LOGSTRING2("MemSamplerImpl::EncodeChunkData - processing thread 0x%x ",&t);
+		
+	// the size of the following name is in the first byte
+	TUint8* size = &sample[0];
+	*size = 0;
+	this->sampleDescriptor.Zero();
+
+	LOGTEXT("MemSamplerImpl::EncodeChunkData - cleared");
+
+	this->sampleDescriptor.Append((TUint8*)&(t.iId),sizeof(TUint));
+	*size += sizeof(TUint);
+		
+	// copy the total amount of memory allocated for user side stack
+	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
+	*size += sizeof(TInt);
+
+	TInt zero(0);		
+	// append the cell amount allocated (zero, not in use here)
+	this->sampleDescriptor.Append((TUint8*)&zero,sizeof(TInt));
+	*size += sizeof(TInt);
+	
+	// append the chunk size (this is not a chunk)
+	this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TUint));
+	*size += sizeof(TUint);
+
+	// append user stack (max) size
+	this->sampleDescriptor.Append((TUint8*)&(t.iUserStackSize),sizeof(TInt));
+	*size += sizeof(TInt);
+
+	LOGSTRING2("Data -> %d",*size);
+	return ((TInt)(*size))+1;
+    }
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+inline TInt DMemSamplerImpl::EncodeChunkData(DLibrary& l)
+    {
+    LOGTEXT("MemSamplerImpl::EncodeChunkData (Library) - entry");
+    // the size of the following name is in the first byte
+    TUint8* size = &sample[0];
+    *size = 0;
+    this->sampleDescriptor.Zero();
+    
+    TUint32 address((TUint32)&l);
+        
+    this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
+    *size += sizeof(TUint);
+             
+	this->sampleDescriptor.Append((TUint8*)&(l.iCodeSeg->iSize),sizeof(TUint32));
+    *size += sizeof(TInt); 
+             
+    this->sampleDescriptor.Append((TUint8*)&(l.iMapCount),sizeof(TInt));
+    *size += sizeof(TInt);  
+        
+    TInt zero(0);   
+    this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+    *size += sizeof(TInt);   
+        
+    this->sampleDescriptor.Append((TUint8*)&(zero),sizeof(TInt));
+    *size += sizeof(TInt);   
+
+    LOGSTRING2("LData - %d",*size);
+    return ((TInt)(*size))+1;
+
+    }
+#endif
+void DMemSamplerImpl::Reset()
+    {
+	Kern::Printf("MemSamplerImpl::Reset");
+	iCount = 0; // sample threads 1 cycle after actual MEM sample time...
+    this->iTimeToSample = false;
+    this->iChunkCount = 0;
+	this->iNewChunkCount = 0;
+	
+	this->iTotalMemoryOk = false;
+	this->iTotalMemoryNameOk = false;
+
+	this->iChunksProcessing = ENothingToProcess;
+    this->iThreadsProcessing = ENothingToProcess;
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+    this->iLibrariesProcessing = ENothingToProcess;
+    this->iSampleType = ESampleThreads;
+#else
+    this->iSampleThreads = true;
+#endif
+    
+	this->sampleDescriptor.Zero();
+	
+	// clear all chunk tags
+    NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
+	DObjectCon* chunks = Kern::Containers()[EChunk];
+    chunks->Wait(); // Obtain the container mutex so the list does get changed under us
+
+	TInt totalChunkCount = chunks->Count();
+	for(TInt i=0;i<totalChunkCount;i++)
+	    {
+		DChunk* c = (DChunk*)(*chunks)[i];
+		TAG(c) = 0;
+	    }
+	chunks->Signal();  // Release the container mutex
+
+	Kern::Printf("MemSamplerImpl::Reset");
+	this->iThreadCount = 0;
+	this->iNewThreadCount = 0;
+	this->sampleDescriptor.Zero();
+
+	// clear all chunk tags
+	DObjectCon* threads = Kern::Containers()[EThread];
+    threads->Wait(); // Obtain the container mutex so the list does get changed under us
+
+	TInt totalThreadCount = threads->Count();
+	for(TInt i=0;i<totalThreadCount;i++)
+	    {
+		DThread* t = (DThread*)(*threads)[i];
+		TAG(t) = (TAG(t) & 0xfffffffe);
+	    }
+	threads->Signal();  // Release the container mutex
+	
+#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
+	this->iLibraryCount = 0;
+	this->iNewLibraryCount = 0;
+	this->sampleDescriptor.Zero();
+
+	// clear all library tags
+	DObjectCon* libs = Kern::Containers()[ELibrary];
+	libs->Wait(); // Obtain the container mutex so the list does get changed under us
+
+	TInt totalLibraryCount = libs->Count();
+	for(TInt i=0; i<totalLibraryCount; i++)
+	    {
+        DLibrary* l = (DLibrary*)(*libs)[i];
+        TAG(l) = (TAG(l) & 0xefffffff);
+	    }
+	libs->Signal();  // Release the container mutex
+#endif
+
+    NKern::ThreadLeaveCS();  // End of critical section
+    }
+