--- /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 <fshell/extrabtrace.h>
+#include <platform.h>
+#include <kern_priv.h>
+#include "memsamplerdd.h"
+#include <fshell/common.mmh>
+
+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<TChunkInfo> 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();
+ }