Makefile fixes.
Fixed export_templates.mk and reenabled it
Updated fshell version generation to better work with multiple platforms including winscw
Updated other extension makefiles to better work with sbs --what
// topfshell.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 <e32hashtab.h>#include <fshell/ioutils.h>#include <fshell/memoryaccesscmd.h>#include "sampler.h"using namespace IoUtils;class CCmdTop : public CMemoryAccessCommandBase {public: static CCommandBase* NewLC(); ~CCmdTop();private: CCmdTop(); static TInt TimerCallback(TAny* aSelf); void TimerCallback(); void UpdateL(); struct SThreadData; static TInt SortReverse(const CCmdTop::SThreadData& aLeft, const CCmdTop::SThreadData& aRight);private: // From CCommandBase. virtual const TDesC& Name() const; virtual void DoRunL(); virtual void ArgumentsL(RCommandArgumentList& aArguments); virtual void OptionsL(RCommandOptionList& aOptions);private: RBuf8 iReadBuf; struct SThreadData { TUint iId; TInt iNumSamples; TFullName iName; // Saves recalculating every time }; RHashMap<TUint, SThreadData*> iSeenThreads; // Saves linear searching through iThreads for each sample (Maps thread id to SThreadData RPointerArray<SThreadData> iThreads; RSampler iSampler; CPeriodic* iTimer; TInt iRate; CTextBuffer* iBuffer; CTextFormatter* iFormatter; TInt iNumConsoleLines; TInt iNumLinesInLastUpdate; };CCommandBase* CCmdTop::NewLC() { CCmdTop* self = new(ELeave) CCmdTop(); CleanupStack::PushL(self); self->BaseConstructL(); return self; }CCmdTop::~CCmdTop() { if (iTimer) { iTimer->Cancel(); } delete iTimer; if (iSampler.Handle()) { iSampler.Stop(); iSampler.Close(); User::FreeLogicalDevice(KSamplerName); } delete iBuffer; delete iFormatter; iReadBuf.Close(); iThreads.ResetAndDestroy(); iSeenThreads.Close(); }CCmdTop::CCmdTop() : CMemoryAccessCommandBase(EManualComplete), iRate(1000) { }const TDesC& CCmdTop::Name() const { _LIT(KName, "top"); return KName; }void CCmdTop::ArgumentsL(RCommandArgumentList& /*aArguments*/) { }void CCmdTop::OptionsL(RCommandOptionList& aOptions) { aOptions.AppendIntL(iRate, _L("rate")); }EXE_BOILER_PLATE(CCmdTop)void CCmdTop::DoRunL() {#ifdef FSHELL_MEMORY_ACCESS_SUPPORT LoadMemoryAccessL();#endif TInt err = User::LoadLogicalDevice(KSamplerName); if (err != KErrNone && err != KErrAlreadyExists) { LeaveIfErr(err, _L("Couldn't load sampler ldd %S"), &KSamplerName); } iReadBuf.CreateL(iRate * 2 * sizeof(TUint32)); // go twice as big as needed just to be safe, allows for AO not getting to run on time iTimer = CPeriodic::NewL(CActive::EPriorityStandard); iTimer->Start(iRate*1000, iRate*1000, TCallBack(&CCmdTop::TimerCallback, this)); LeaveIfErr(iSampler.Open(), _L("Couldn't open sampler")); iSampler.Reset(ETrue); // Parameter is ignored iSampler.Start(1000); // Always tell sampler to sample every millisecond, regardless of the frequency we update the UI TSize size; User::LeaveIfError(Stdout().GetScreenSize(size)); iNumConsoleLines = size.iHeight; iBuffer = CTextBuffer::NewL(512); iFormatter = CTextFormatter::NewL(size.iWidth); Stdout().ClearScreen(); UpdateL(); // Just so we display something on screen before the first update }TInt CCmdTop::TimerCallback(TAny* aSelf) { static_cast<CCmdTop*>(aSelf)->TimerCallback(); return 0; }void CCmdTop::TimerCallback() { iReadBuf.Zero(); TRequestStatus stat; iSampler.Read(iReadBuf, stat); User::WaitForRequest(stat); // API used to be async, it's now sync but I haven't changed the interface // First off clear all the iNumSamples (as that was for the previous sampling period) for (TInt i = 0; i < iThreads.Count(); i++) { iThreads[i]->iNumSamples = 0; } TInt numSamples = iReadBuf.Length() / sizeof(TUint32); TUint32* buf = (TUint32*)iReadBuf.Ptr(); for (TInt i = 0; i < numSamples; i++) { TUint32 threadId = buf[i]; SThreadData** thread = iSeenThreads.Find(threadId); if (thread) { (*thread)->iNumSamples++; } else { // New thread id SThreadData* thread = new SThreadData; if (!thread) continue; TInt err = iThreads.Append(thread); if (err) { delete thread; continue; } err = iSeenThreads.Insert(threadId, thread); if (err) { iThreads.Remove(iThreads.Count()-1); delete thread; continue; } thread->iNumSamples = 1; thread->iId = threadId; RThread rthread;#ifdef FSHELL_MEMORY_ACCESS_SUPPORT err = iMemAccess.RThreadForceOpen(rthread, threadId);#else err = rthread.Open(TThreadId(threadId));#endif if (err == KErrNone) { thread->iName = rthread.FullName(); //PrettyName(EListThread, thread->iName); rthread.Close(); } else { thread->iName = _L("Tid: "); thread->iName.AppendNum(threadId); } } } TRAP_IGNORE(UpdateL()); }TInt CCmdTop::SortReverse(const CCmdTop::SThreadData& aLeft, const CCmdTop::SThreadData& aRight) { // This sorts largest number of samples first TInt res = - (aLeft.iNumSamples - aRight.iNumSamples); if (res == 0) return aLeft.iId - aRight.iId; // make sure there is a total ordering in event of tie break return res; }void CCmdTop::UpdateL() { // First, sort iThreads iThreads.Sort(TLinearOrder<SThreadData>(&SortReverse)); TInt numSamples = iReadBuf.Size() / sizeof(TUint32); iBuffer->Zero(); iFormatter->Zero(); iBuffer->AppendL(_L("Tid\tThread name\tCPU usage\r\n")); for (TInt i = 0; i < iThreads.Count() && i < iNumConsoleLines-2; i++) // minus one for title, one for last line of screen which I can't seem to figure out how to make use of { SThreadData& thread = *iThreads[i]; TReal percent = 100 * thread.iNumSamples / (TReal)numSamples; iBuffer->AppendFormatL(_L("%d\t%S\t%00.2f%%\r\n"), thread.iId, &thread.iName, percent); } Stdout().SetCursorHeight(0); iFormatter->TabulateL(0, 1, iBuffer->Descriptor(), ETruncateLongestColumn); User::LeaveIfError(Stdout().SetCursorPosAbs(TPoint(0, 0))); Stdout().Write(iFormatter->Descriptor()); TInt numLines = 1 + iThreads.Count(); // plus 1 for the title line TInt numOldLines = iNumLinesInLastUpdate - numLines; while (numOldLines > 0) { Stdout().ClearToEndOfLine(); Stdout().SetCursorPosRel(TPoint(0, 1)); --numOldLines; } iNumLinesInLastUpdate = numLines; }