diff -r 67c6ff54ec25 -r a009639409f5 piprofiler/plugins/GeneralsPlugin/inc/MemSamplerImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/inc/MemSamplerImpl.h Thu May 27 14:26:55 2010 +0300 @@ -0,0 +1,427 @@ +/* +* 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: +* +*/ + + +#ifndef PROFILER_MEM_SAMPLER_H +#define PROFILER_MEM_SAMPLER_H + +#include "GeneralsConfig.h" + +#include + +#include +#include +#include "GppSamplerImpl.h" +#include "MemoryEventHandler.h" +#include + + +// constants +// defines the maximum thread amount that is assumed to +// be possible with MEM trace +const TInt KSampleBufferSize = 257; +const TInt KProfilerMaxThreadsAmount = 512; +const TInt KProfilerMaxChunksAmount = 1024; +const TInt KProfilerMaxLibrariesAmount = 1024; +const TInt KProfilerTotalMemorySamplePeriod = 100; + +// flags +#define MEM_EVENT_HANDLER +//#define MEM_EVENT_HANDLER_LIBRARY_EVENTS + +/* + * + * MEM sampler definition + * + */ + +class DMemoryEventHandler; + +class DMemSamplerImpl //: public DBase +{ +public: + enum EProcessingState + { + EStartingToProcess, + EProcessingNames, + EProcessingData, + ENothingToProcess + }; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + enum ESampleType + { + ESampleChunks, + ESampleThreads, + ESampleLibraries + }; +#endif + + DMemSamplerImpl(); + ~DMemSamplerImpl(); + + TInt CreateFirstSample(); + TInt SampleImpl(); + TBool SampleNeeded(); + void Reset(); + TInt ProcessChunks(); + TInt ProcessThreads(); + TInt GatherChunks(); + TInt GatherThreads(); + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TInt GatherLibraries(); + TInt ProcessLibraries(); +#endif + + TInt EncodeChunkData(DChunk& chunk); + TInt EncodeChunkName(DChunk& chunk); + TInt EncodeChunkData(DThread& thread); + TInt EncodeChunkName(DThread& thread); +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TInt EncodeChunkData(DLibrary& library); + TInt EncodeChunkName(DLibrary& library); +#endif + + TInt EncodeTotalMemoryName(); + TInt EncodeTotalMemory(); + + TInt EncodeNameCode(); + TInt EncodeDataCode(); + + DChunk* heapChunksToSample[KProfilerMaxChunksAmount]; + DChunk* heapChunkNamesToReport[KProfilerMaxChunksAmount]; + TInt iCount; + TInt iChunkCount; + TInt iNewChunkCount; + TBuf8<0x50> name; + DThread* threadsToSample[KProfilerMaxThreadsAmount]; + DThread* threadNamesToReport[KProfilerMaxThreadsAmount]; + TInt iThreadCount; + TInt iNewThreadCount; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + DLibrary* librariesToSample[KProfilerMaxLibrariesAmount]; + DLibrary* libraryNamesToReport[KProfilerMaxLibrariesAmount]; + TInt iLibraryCount; + TInt iNewLibraryCount; + TInt iLibrariesProcessing; +#endif + + TInt iChunksProcessing; + TInt iThreadsProcessing; + TInt iMemSamplingPeriod; + TInt iMemSamplingPeriodDiv2; + TInt iMemSamplingPeriodDiv3; + +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + ESampleType iSampleType; +#else + TBool iSampleThreads; +#endif + + TBool iTimeToSample; + + TBool iTotalMemoryOk; + TBool iTotalMemoryNameOk; + + TUint8 sample[KSampleBufferSize]; + TPtr8 sampleDescriptor; + + // test +#ifdef MEM_EVENT_HANDLER +// DMemoryEventHandler* iEventHandler; + TBool iChunksGathered; + TBool iThreadsGathered; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + TBool iLibrariesGathered; +#endif +#endif +}; + + +template +class DProfilerMemSampler : public DProfilerGenericSampler +{ +public: + DProfilerMemSampler(struct TProfilerGppSamplerData*, TInt id); + ~DProfilerMemSampler(); + + void Sample(); + TInt Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset); + TInt PostSample(); + TBool PostSampleNeeded(); + +private: +#ifdef MEM_EVENT_HANDLER + DMemoryEventHandler* iEventHandler; +#endif + DMemSamplerImpl memSamplerImpl; + struct TProfilerGppSamplerData* gppSamplerData; + TBool sampleNeeded; +}; + +/* + * + * MEM sampler implementation + * + */ + +template +DProfilerMemSampler::DProfilerMemSampler(struct TProfilerGppSamplerData* gppSamplerDataIn, TInt id) : + DProfilerGenericSampler(PROFILER_MEM_SAMPLER_ID) + { + LOGSTRING2("DProfilerMemSampler<%d>::CProfilerMemSampler",BufferSize); + this->gppSamplerData = gppSamplerDataIn; + this->iSamplingPeriod = 3000; // set default setting + } + +template +TInt DProfilerMemSampler::Reset(DProfilerSampleStream* aStream, TUint32 aSyncOffset) + { +//#ifdef MEM_EVENT_HANDLER +// Kern::Printf("DProfilerMemSampler<%d>::Reset - calling superclass reset",BufferSize); + +//#endif + // check if reset called in stop (by driver) + if(aSyncOffset != 999999) + { + DProfilerGenericSampler::Reset(aStream); + memSamplerImpl.Reset(); + +#ifdef MEM_EVENT_HANDLER + // reset member variables + this->memSamplerImpl.iThreadsGathered = false; + this->memSamplerImpl.iChunksGathered = false; +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iLibrariesGathered = false; +#endif + + // memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } + +// Kern::Printf("Initiating DMemoryEventHandler"); + iEventHandler = new DMemoryEventHandler(this->iSampleBuffer); + if(iEventHandler) + { +// Kern::Printf("Creating DMemoryEventHandler"); + TInt err(iEventHandler->Create()); + if(err != KErrNone) + { + Kern::Printf("Error in creation of DMemoryEventHandler, error %d", err); + return err; + } + } + else + { + Kern::Printf("Could not initiate DMemoryEventHandler"); + return KErrGeneral; + } + + // set first chunk&thread memory lookup at the 5 ms, should be enough +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iMemSamplingPeriod = 45; +#else + this->memSamplerImpl.iMemSamplingPeriod = 10; +#endif + +#else + this->memSamplerImpl.iMemSamplingPeriod = this->iSamplingPeriod; +#endif + this->memSamplerImpl.iMemSamplingPeriodDiv2 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 2); +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + this->memSamplerImpl.iMemSamplingPeriodDiv3 = (TInt)(this->memSamplerImpl.iMemSamplingPeriod / 3); +#endif + + LOGSTRING3("CProfilerMemSampler<%d>::Reset - set mem sampling period to %d", + BufferSize,this->memSamplerImpl.iMemSamplingPeriod); + } + else + { + LOGSTRING2("DProfilerMemSampler<%d>::Reset - reset in stop", BufferSize); +#ifdef MEM_EVENT_HANDLER + // destroy memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif + return KErrNone; // return if reset called in stop + } + + // add MEM sample header + TInt length(memSamplerImpl.CreateFirstSample()); + this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); + + this->sampleNeeded = false; + LOGSTRING("DProfilerMemSampler::Reset - exit"); + return KErrNone; + } + +template +TInt DProfilerMemSampler::PostSample() + { + this->sampleNeeded = false; + + LOGSTRING3("DProfilerMemSampler<%d>::PostSample - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + +#ifdef MEM_EVENT_HANDLER + // check if all threads and chunks (and libraries) are gathered +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered || !memSamplerImpl.iLibrariesGathered) +#else + if(!memSamplerImpl.iThreadsGathered || !memSamplerImpl.iChunksGathered) +#endif + { +#endif + // disable interrupts for checking the kernel containers (EChunk, EThread) +// TInt interruptLevel(NKern::DisableInterrupts(0)); + + // first collect chunk data + TInt length(this->memSamplerImpl.SampleImpl()); + if(length != 0) + { + // then, encode the sample to the buffer until no further data available + while(length > 0) + { + this->iSampleBuffer->AddSample(memSamplerImpl.sample,length); + length = this->memSamplerImpl.SampleImpl(); + + // indicate that the whole MEM sample ends by having a 0x00 in the end + if(length == 0) + { + TUint8 number(0); + LOGSTRING("MEM sampler PostSample - all samples generated!"); + + this->iSampleBuffer->AddSample(&number,1); + LOGSTRING2("MEM sampler PostSample - end mark added, time: %d", gppSamplerData->sampleNumber); + } + } + } + // restore interrupts and continue normal execution +// NKern::RestoreInterrupts(interruptLevel); +#ifdef MEM_EVENT_HANDLER + } + // check if all threads and chunks are gathered +#ifdef MEM_EVENT_HANDLER_LIBRARY_EVENTS + if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered && memSamplerImpl.iLibrariesGathered) +#else + if(memSamplerImpl.iThreadsGathered && memSamplerImpl.iChunksGathered) +#endif + { + // start memory event tracking after checking the current memory status + if(!iEventHandler->Tracking()) + { + iEventHandler->Start(); +// Kern::Printf("DProfilerMemSampler<%d>::PostSample - memory event handler started",BufferSize); + } + + } +#endif + + LOGSTRING2("MEM sampler PostSample - finished sampling, time: %d", gppSamplerData->sampleNumber); + + // finally perform superclass postsample + TInt i(this->DProfilerGenericSampler::PostSample()); + return i; + } + +template +TBool DProfilerMemSampler::PostSampleNeeded() + { + LOGSTRING3("DProfilerMemSampler<%d>::PostSampleNeeded - state %d",BufferSize,this->iSampleBuffer->GetBufferStatus()); + + TUint32 status(this->iSampleBuffer->iBufferStatus); + + if(status == DProfilerSampleBuffer::BufferCopyAsap || status == DProfilerSampleBuffer::BufferFull || this->sampleNeeded == true) + { + return true; + } + + return false; + } + +template +void DProfilerMemSampler::Sample() + { + LOGSTRING2("DProfilerMemSampler<%d>::Sample",BufferSize); + + // check if sample is needed, i.e. the sampling interval is met + if(memSamplerImpl.SampleNeeded()) + { + // set the flag for post sampling + this->sampleNeeded = true; + + // start the MEM sample with the sample time + TUint8 number(4); // mem sampler id + this->iSampleBuffer->AddSample(&number,1); + this->iSampleBuffer->AddSample((TUint8*)&(gppSamplerData->sampleNumber),4); + + // leave the rest of the processing for PostSample() + } + +#ifdef MEM_EVENT_HANDLER + // call this to increase the time stamp + else if(iEventHandler->SampleNeeded()) + { + // set the flag for post sampling + this->sampleNeeded = true; + } + +// // check if time stamp is divibable with +// if((memSamplerImpl.iCount % KProfilerTotalMemorySamplePeriod) == 0 && +// memSamplerImpl.iCount > 0) +// { +// // sample total memory once per 100 ms +// memSamplerImpl.EncodeTotalMemory(); +// +// // add end mark +// TUint8 number(0); +// this->iSampleBuffer->AddSample(&number,1); +// } +#endif + + LOGSTRING2("CProfilerMemSampler<%d>::Sample",BufferSize); + return; + } + +template +DProfilerMemSampler::~DProfilerMemSampler() + { + LOGSTRING2("CProfilerMemSampler<%d>::~CProfilerMemSampler",BufferSize); +#ifdef MEM_EVENT_HANDLER + // memory event handler + if(iEventHandler) + { + // stop previous sampling if still running +// Kern::Printf("Stopping DMemoryEventHandler"); + iEventHandler->Stop(); + iEventHandler->Close(); + iEventHandler = NULL; + } +#endif + } +#endif