/*
* 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;
iSampleType = ESampleThreads;
//iSampleType = ESampleChunks;
iTimeToSample = true;
iTotalMemoryOk = false;
iTotalMemoryNameOk = false;
iNewChunkCount = 0;
iChunkCount = 0;
iChunksProcessing = ENothingToProcess;
iThreadsProcessing = ENothingToProcess;
iChunksGathered = false;
iThreadsGathered = false;
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"));
LOGSTRING2("timestamp : 0x%04x", iCount);
LOGSTRING("MemSamplerImpl::CreateFirstSample - exit");
sample[0] = this->sampleDescriptor.Size();
return (TInt)(sample[0]+1);
}
TBool DMemSamplerImpl::SampleNeeded(TUint32 sampleNum)
{
TBool ret(false);
iCount = sampleNum;
#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 == 0)
// #endif
#else
if ((iCount % iMemSamplingPeriod) == 0 || (iCount % iMemSamplingPeriodDiv2) == 0)
#endif
{
LOGSTRING2("MemSamplerImpl::SampleNeeded - time: %d", iCount);
ret= true;
}
else
{
ret=false;
}
return ret;
}
/*
* When returns 0, means that all samples done.
* Should return length of sample available in iSample
*/
TInt DMemSamplerImpl::SampleImpl(TUint32 sampleNum)
{
if(iTimeToSample)
{
// Sample threads:
if( iSampleType == ESampleThreads && !iThreadsGathered )
{
if(this->iThreadsProcessing == ENothingToProcess )
{
// 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;
iThreadsGathered = ETrue;
}
return length;
}
}
// Sample chunks:
else if( iSampleType == ESampleChunks && !iChunksGathered)
{
if(this->iChunksProcessing == ENothingToProcess)
{
// 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;
iChunksGathered = ETrue;
iThreadsGathered = ETrue;
//iSampleThreads = true;
}
return length;
}
}
#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
// Sample libraries:
else if( iSampleType == ESampleLibraries )
{
if(this->iLibrariesProcessing == ENothingToProcess )
{
// 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;
iLibrariesGathered = ETrue;
}
return length;
}
}
#endif
else
{
// Will not be executed. Ever. PostSample handles the state change and starting of
// memory event handler.
iChunksGathered = ETrue;
iThreadsGathered = ETrue;
iTimeToSample = false;
Kern::Printf("MEM sampler - all initial samples generated but we should not be here...!");
}
}
else // not time to sample
{
LOGSTRING("MEM sampler - not time to sample!");
}
// should not reach this point...
return 0;
}
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;
LOGSTRING2("DMemSamplerImpl::GatherChunks() chunk count %d",totalChunkCount);
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);
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 %d Chunks", totalChunkCount);
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();
LOGSTRING2("DMemSamplerImpl::GatherThreads() thread count %d",totalThreadCount);
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);
}
LOGSTRING3("Added %d threads. ithreadcount %d",totalThreadCount, iThreadCount);
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("DMemSamplerImpl::GatherThreads() - 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);
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(iHandledChunks < 50)
{
if(iNewChunkCount > 0)
{
if(this->iChunksProcessing == EStartingToProcess)
{
// this is the first sample, encode a code for names
this->iChunksProcessing = EProcessingNames;
iHandledChunks++;
return EncodeNameCode();
}
if(iTotalMemoryNameOk == false)
{
iHandledChunks++;
return EncodeTotalMemoryName();
}
iNewChunkCount--;
DChunk* c = this->heapChunkNamesToReport[iNewChunkCount];
iHandledChunks++;
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;
iHandledChunks++;
return EncodeDataCode();
}
if(this->iTotalMemoryOk == false)
{
iHandledChunks++;
return EncodeTotalMemory();
}
// there are no new chunks to report
// thus generate the real report
iChunkCount--;
DChunk* c = this->heapChunksToSample[iChunkCount];
iHandledChunks++;
return EncodeChunkData(*c);
}
else
{
// everything is processed
LOGSTRING2("MemSamplerImpl::ProcessChunks() Chunks processed! Chunk count = %d", iChunkCount);
#ifdef MEM_EVENT_HANDLER
this->iChunksGathered = ETrue;
LOGSTRING2("MemSamplerImpl::ProcessChunks() - chunks gathered! Time: %d",iCount);
#endif
return 0;
}
}
else
{
LOGSTRING("MemSamplerImpl::ProcessChunks() 0");
iHandledChunks =0;
}
return -1;
}
inline TInt DMemSamplerImpl::ProcessThreads()
{
if(iHandledThreads < 50)
{
if(iNewThreadCount > 0)
{
if(this->iThreadsProcessing == EStartingToProcess)
{
// this is the first sample, encode a code for names
this->iThreadsProcessing = EProcessingNames;
iHandledThreads++;
return EncodeNameCode();
}
if(iTotalMemoryNameOk == false)
{
LOGSTRING("MemSamplerImpl::ProcessThreads() Encoding total memory name!");
iHandledThreads++;
return EncodeTotalMemoryName();
}
iNewThreadCount--;
DThread* t = this->threadNamesToReport[iNewThreadCount];
iHandledThreads++;
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;
iHandledThreads++;
return EncodeDataCode();
}
if(this->iTotalMemoryOk == false)
{
iHandledThreads++;
return EncodeTotalMemory();
}
// there are no new threads to report
// thus generate the real report
iThreadCount--;
DThread* t = this->threadsToSample[iThreadCount];
iHandledThreads++;
return EncodeChunkData(*t);
}
else
{
// everything is processed
LOGSTRING2("MemSamplerImpl::ProcessThreads() Threads processed! Thread count = %d", iThreadCount);
#ifdef MEM_EVENT_HANDLER
this->iThreadsGathered = true;
LOGSTRING2("MemSamplerImpl::ProcessThreads() - threads gathered! Time: %d", iCount);
#endif
return 0;
}
}
else
{
LOGSTRING("MemSamplerImpl::ProcessThreads() 0");
iHandledThreads=0;
}
return -1;
}
#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS
inline TInt DMemSamplerImpl::ProcessLibraries()
{
LOGTEXT("ProcessLibraries - entry");
if(iHandledLibs < 50)
{
if(iNewLibraryCount > 0)
{
if(this->iLibrariesProcessing == EStartingToProcess)
{
// this is the first sample, encode a code for names
this->iLibrariesProcessing = EProcessingNames;
iHandledLibs++;
return EncodeNameCode();
}
if(iTotalMemoryNameOk == false)
{
iHandledLibs++;
return EncodeTotalMemoryName();
}
// there are new library names to report
iNewLibraryCount--;
DLibrary* l = this->libraryNamesToReport[iNewLibraryCount];
iHandledLibs++;
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;
iHandledLibs++;
return EncodeDataCode();
}
if(this->iTotalMemoryOk == false)
{
iHandledLibs++;
return EncodeTotalMemory();
}
// there are no new libraries to report
// thus generate the real report
iLibraryCount--;
DLibrary* l = this->librariesToSample[iLibraryCount];
iHandledLibs++;
return EncodeChunkData(*l);
}
else
{
// everything is processed
LOGSTRING2(" Libraries processed! Library count = %d", iLibraryCount);
this->iLibrariesGathered = true;
LOGSTRING2("MemSamplerImpl::ProcessLibraries() - libraries gathered! Time: %d",iCount);
return 0;
}
}
else
{
LOGSTRING("MemSamplerImpl::ProcessLibs() 0");
iHandledLibs =0;
}
return -1;
}
#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;
TInt zero(0);
this->sampleDescriptor.Zero();
TUint32 address((TUint32)&c);
this->sampleDescriptor.Append((TUint8*)&address,sizeof(TUint32));
*size += sizeof(TUint32);
LOGSTRING2("address - 0x%04x",&address);
// 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("chunk Data - %d",*size);
return ((TInt)(*size))+1;
}
inline TInt DMemSamplerImpl::EncodeChunkData(DThread& t)
{
// the size of the following name is in the first byte
TUint8* size = &sample[0];
*size = 0;
TInt zero(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);
// 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()
{
LOGSTRING("MemSamplerImpl::Reset - entry");
iCount = 0; // sample threads 1 cycle after actual MEM sample time...
this->iTimeToSample = true;
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;
#else
this->iSampleType = ESampleThreads;
//this->iSampleType = ESampleChunks;
//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
LOGSTRING("MemSamplerImpl::Reset");
this->iThreadCount = 0;
this->iNewThreadCount = 0;
this->sampleDescriptor.Zero();
// clear all thread 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
}
// end of file