diff -r 000000000000 -r 7f656887cf89 commands/memsampler/memsamplerdd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/memsampler/memsamplerdd.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,342 @@ +// memsamplerdd.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "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: +// Accenture - Initial contribution +// + +#include +#include +#include +#include "memsamplerdd.h" +#include + +const TInt KMinRate = 10; +const TInt KMaxRate = 10000; +const TInt KMajorVersionNumber = 1; +const TInt KMinorVersionNumber = 0; +const TInt KBuildVersionNumber = 0; +const TInt KArrayGranularity = 32; +const TInt KDfcThreadPriority = 26; +_LIT(KDfcThreadName, "MemSamplerDD"); + +class DDeviceMemSampler : public DLogicalDevice + { +public: + DDeviceMemSampler(); + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); + }; + +class TChunkInfo + { +public: + TChunkInfo(DChunk& aChunk); + TBool operator==(const TChunkInfo& aChunkInfo); +public: + DChunk* iAddress; + TInt iSize; + TInt iHighWaterMark; + TBool iSeen; + }; + +TChunkInfo::TChunkInfo(DChunk& aChunk) + : iAddress(&aChunk), iSize(aChunk.Size()), iHighWaterMark(aChunk.Size()), iSeen(ETrue) + { + } + +TBool TChunkInfo::operator==(const TChunkInfo& aChunkInfo) + { + return (iSize == aChunkInfo.iSize); + } + +class DMemSamplerChannel : public DLogicalChannel + { +public: + DMemSamplerChannel(); + ~DMemSamplerChannel(); +protected: + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual void HandleMsg(TMessageBase* aMsg); +private: + TInt StartSampling(TInt aRate); + TInt StopSampling(); + TInt ResetSampling(); + TInt ReadChunks(); + void TraceNewChunk(const TChunkInfo& aChunkInfo) const; + void TraceChangedChunk(const TChunkInfo& aChunkInfo) const; + void TraceDeletedChunk(const TChunkInfo& aChunkInfo) const; + void TraceNewSample() const; +#if FSHELL_PLATFORM_SYMTB >= 92 + inline TBool Running() + {return iTimer.IsPending();} +#else + inline TBool Running() + {return iTimer.iState!=NTimer::EIdle;} +#endif +private: + static void Sample(TAny*); + static void DoSample(TAny*); + static void ExitDfcThread(TAny*); +private: + RArray iChunkInfo; + NTimer iTimer; + TInt iPeriod; + TInt iPeriodNumber; + TDfcQue iPrivateDfcQ; + TDfc iDoSampleDfc; + TDfc iExitDfc; + DThread* iClient; + mutable TBool iNewSampleTraced; + }; + +DECLARE_STANDARD_LDD() + { + return new DDeviceMemSampler; + } + +DDeviceMemSampler::DDeviceMemSampler() + { + iVersion=TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber); + } + +TInt DDeviceMemSampler::Install() + { + TInt r = SetName(&KMemSamplerName); + return r; + } + +void DDeviceMemSampler::GetCaps(TDes8&) const + { + } + +TInt DDeviceMemSampler::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DMemSamplerChannel; + return aChannel ? KErrNone : KErrNoMemory; + } + +DMemSamplerChannel::DMemSamplerChannel() + : iChunkInfo(KArrayGranularity, _FOFF(TChunkInfo, iAddress)), iTimer(Sample, this), iPeriodNumber(-1), iDoSampleDfc(DoSample, this, 1), iExitDfc(ExitDfcThread, this, 0), iNewSampleTraced(EFalse) + { + } + +DMemSamplerChannel::~DMemSamplerChannel() + { + Kern::SafeClose((DObject*&)iClient, NULL); + iExitDfc.Enque(); + } + +void DMemSamplerChannel::ExitDfcThread(TAny*) + { + Kern::Exit(KErrNone); + } + +TInt DMemSamplerChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer) + { + if (!Kern::QueryVersionSupported(TVersion(1,0,0),aVer)) + { + return KErrNotSupported; + } + iClient=&Kern::CurrentThread(); + iClient->Open(); + TInt err = Kern::DfcQInit(&iPrivateDfcQ, KDfcThreadPriority, &KDfcThreadName); + if (err == KErrNone) + { + SetDfcQ(&iPrivateDfcQ); + iDoSampleDfc.SetDfcQ(&iPrivateDfcQ); + iExitDfc.SetDfcQ(&iPrivateDfcQ); + iMsgQ.Receive(); + } + + return err; + } + +TInt DMemSamplerChannel::StartSampling(TInt aRate) + { + DEBUG_MEMSAMPLER(Kern::Printf("START");) + ReadChunks(); + aRate = Min(KMaxRate, Max(KMinRate, aRate)); + iPeriod = NKern::TimerTicks(aRate); + if (!Running()) + { + iTimer.OneShot(iPeriod, EFalse); + } + DEBUG_MEMSAMPLER(Kern::Printf("START end");) + return KErrNone; + } + +TInt DMemSamplerChannel::StopSampling() + { + DEBUG_MEMSAMPLER(Kern::Printf("STOP");) + if (Running()) + { + iTimer.Cancel(); + } + DEBUG_MEMSAMPLER(Kern::Printf("STOP end");) + return KErrNone; + } + +TInt DMemSamplerChannel::ResetSampling() + { + DEBUG_MEMSAMPLER(Kern::Printf("RESET");) + iChunkInfo.Reset(); + DEBUG_MEMSAMPLER(Kern::Printf("RESET end");) + return KErrNone; + } + +TInt DMemSamplerChannel::ReadChunks() + { + ++iPeriodNumber; + iNewSampleTraced = EFalse; + + for (TInt i = (iChunkInfo.Count() - 1); i >= 0; --i) + { + iChunkInfo[i].iSeen = EFalse; + } + + DObjectCon* const * containers = Kern::Containers(); + DObjectCon& container = *containers[EChunk]; + container.Wait(); + + for (TInt i = (container.Count() - 1); i >= 0; --i) + { + TChunkInfo thisChunk(*(DChunk*)container[i]); + TInt pos; + TInt err = iChunkInfo.FindInUnsignedKeyOrder(thisChunk, pos); + if (err == KErrNotFound) + { + if (pos < iChunkInfo.Count()) + { + iChunkInfo.Insert(thisChunk, pos); + } + else + { + TInt err = iChunkInfo.Append(thisChunk); + if (err) + { + container.Signal(); + return err; + } + } + TraceNewChunk(thisChunk); + } + else + { + if (thisChunk == iChunkInfo[pos]) + { + // Chunk size hasn't changed - ignore. + iChunkInfo[pos].iSeen = ETrue; + } + else + { + TChunkInfo& c = iChunkInfo[pos]; + if (thisChunk.iSize > c.iHighWaterMark) + { + c.iHighWaterMark = thisChunk.iSize; + } + c.iSize = thisChunk.iSize; + c.iSeen = ETrue; + TraceChangedChunk(c); + } + } + } + + container.Signal(); + + for (TInt i = (iChunkInfo.Count() - 1); i >= 0; --i) + { + const TChunkInfo& chunkInfo = iChunkInfo[i]; + if (!chunkInfo.iSeen) + { + TraceDeletedChunk(chunkInfo); + iChunkInfo.Remove(i); + } + } + + return KErrNone; + } + +void DMemSamplerChannel::TraceNewChunk(const TChunkInfo& aChunkInfo) const + { + TraceNewSample(); + TFullName nameBuf; + aChunkInfo.iAddress->FullName(nameBuf); + BTraceN(RMemSampler::EBtraceCategory, RMemSampler::ENewChunk, aChunkInfo.iAddress, aChunkInfo.iAddress->MaxSize(), nameBuf.Ptr(), nameBuf.Size()); + TraceChangedChunk(aChunkInfo); + } + +void DMemSamplerChannel::TraceChangedChunk(const TChunkInfo& aChunkInfo) const + { + TraceNewSample(); + BTraceContext12(RMemSampler::EBtraceCategory, RMemSampler::EChangedChunk, aChunkInfo.iAddress, aChunkInfo.iSize, aChunkInfo.iHighWaterMark); + } + +void DMemSamplerChannel::TraceDeletedChunk(const TChunkInfo& aChunkInfo) const + { + TraceNewSample(); + BTraceContext4(RMemSampler::EBtraceCategory, RMemSampler::EDeletedChunk, aChunkInfo.iAddress); + } + +void DMemSamplerChannel::TraceNewSample() const + { + if (!iNewSampleTraced) + { + iNewSampleTraced = ETrue; + BTraceContext8(RMemSampler::EBtraceCategory, RMemSampler::ENewSample, iPeriod, iPeriodNumber); + } + } + +void DMemSamplerChannel::HandleMsg(TMessageBase* aMsg) + { + TInt r=KErrNone; + TThreadMessage& m=*(TThreadMessage*)aMsg; + TInt id=m.iValue; + if (id==(TInt)ECloseMsg) + { + DEBUG_MEMSAMPLER(Kern::Printf("CLOSE");) + iTimer.Cancel(); + m.Complete(KErrNone,EFalse); + iMsgQ.CompleteAll(KErrServerTerminated); + DEBUG_MEMSAMPLER(Kern::Printf("CLOSE end");) + return; + } + else + { + switch(id) + { + case RMemSampler::EControlStartProfile: + r = StartSampling(m.Int0()); + break; + case RMemSampler::EControlStopProfile: + r = StopSampling(); + break; + case RMemSampler::EControlResetProfile: + r = ResetSampling(); + break; + default: + r = KErrNotSupported; + break; + } + } + m.Complete(r,ETrue); + } + +void DMemSamplerChannel::Sample(TAny* aPtr) + { + DMemSamplerChannel& d = *(DMemSamplerChannel*)aPtr; + d.iTimer.Again(d.iPeriod); + d.iDoSampleDfc.Add(); + } + +void DMemSamplerChannel::DoSample(TAny* aPtr) + { + DMemSamplerChannel& d = *(DMemSamplerChannel*)aPtr; + d.ReadChunks(); + }