Tidied iocli exports, build macro tweaks.
Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll.
fixed builds on platforms that don't support btrace or any form of tracing.
// btrace_cpuusage.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 "btrace_parser.h"
MBtraceCpuUsageObserver::TCpuUsage::TCpuUsage(const TBtraceThreadId& aId)
: iId(aId), iNumFastTicks(0)
{
}
MBtraceCpuUsageObserver::TCpuUsage::TCpuUsage(const TBtraceThreadId& aId, const TBtraceTickCount& aTickCount)
: iId(aId), iNumFastTicks(0), iSwitchedInAt(aTickCount)
{
}
EXPORT_C CBtraceCpuUsage* CBtraceCpuUsage::NewL(CBtraceReader& aReader, CBtraceContext& aContext)
{
CBtraceCpuUsage* self = new(ELeave) CBtraceCpuUsage(aReader, aContext);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
EXPORT_C CBtraceCpuUsage::~CBtraceCpuUsage()
{
while (iCpuUsageNotifs.Count())
{
iCpuUsageNotifs[0].Close();
iCpuUsageNotifs.Remove(0);
}
iCpuUsageNotifs.Close();
iContextSwitchNotifs.Close();
iThreadIdleNotifs.Close();
iReader.RemoveObserver(BTrace::ECpuUsage, *this);
iReader.RemoveObserver(KAmTraceCategory, *this);
}
EXPORT_C void CBtraceCpuUsage::NotifyCpuUsageL(TUint32 aNanoTickCount, TTimeIntervalMicroSeconds32 aPeriod, MBtraceCpuUsageObserver& aObserver)
{
NotifyCpuUsageL(aNanoTickCount, aPeriod, aObserver, ENotificationOneShot);
}
EXPORT_C void CBtraceCpuUsage::NotifyCpuUsageL(TUint32 aNanoTickCount, TTimeIntervalMicroSeconds32 aPeriod, MBtraceCpuUsageObserver& aObserver, TBtraceNotificationPersistence aPersistence)
{
RCpuUsageNotif notif(aNanoTickCount, TBtraceUtils::MicroSecondsToNanoTicks(aPeriod), aObserver, aPersistence);
User::LeaveIfError(iCpuUsageNotifs.Append(notif));
}
EXPORT_C void CBtraceCpuUsage::NotifyContextSwitchL(const TBtraceThreadId& aId, MBtraceCpuUsageObserver& aObserver)
{
TContextSwitchNotif notif(aId, aObserver);
User::LeaveIfError(iContextSwitchNotifs.InsertInUnsignedKeyOrderAllowRepeats(notif));
}
EXPORT_C void CBtraceCpuUsage::NotifyThreadIdleL(const TBtraceThreadId& aId, const TBtraceTickCount& aFromTickCount, TTimeIntervalMicroSeconds32 aPeriod, MBtraceCpuUsageObserver& aObserver)
{
NotifyThreadIdleL(aId, aFromTickCount, aPeriod, aObserver, ENotificationOneShot);
}
EXPORT_C void CBtraceCpuUsage::NotifyThreadIdleL(const TBtraceThreadId& aId, const TBtraceTickCount& aFromTickCount, TTimeIntervalMicroSeconds32 aPeriod, MBtraceCpuUsageObserver& aObserver, TBtraceNotificationPersistence aPersistence)
{
TThreadIdleNotif notif(aId, aFromTickCount, TBtraceUtils::MicroSecondsToNanoTicks(aPeriod), aObserver, aPersistence);
User::LeaveIfError(iThreadIdleNotifs.InsertInUnsignedKeyOrderAllowRepeats(notif));
}
EXPORT_C void CBtraceCpuUsage::CancelNotifyThreadIdle(MBtraceCpuUsageObserver& aObserver)
{
for (TInt i = iThreadIdleNotifs.Count()-1; i>=0; --i)
{
if (iThreadIdleNotifs[i].iObserver == &aObserver)
{
iThreadIdleNotifs.Remove(i);
}
}
}
CBtraceCpuUsage::CBtraceCpuUsage(CBtraceReader& aReader, CBtraceContext& aContext)
: iReader(aReader), iContext(aContext)
{
}
void CBtraceCpuUsage::ConstructL()
{
iReader.AddObserverL(BTrace::ECpuUsage, *this);
iReader.AddObserverL(KAmTraceCategory, *this); // To ensure we get heartbeat and sync frames, which are needed to flush through and force TestThreadIdlenessL to be called
}
void CBtraceCpuUsage::HandleBtraceFrameL(const TBtraceFrame& aFrame)
{
if (aFrame.iCategory == BTrace::ECpuUsage)
{
switch (aFrame.iSubCategory)
{
case BTrace::ENewThreadContext:
{
++iNumProcessedFrames;
const TBtraceThreadId* btraceThreadId = iContext.FindThread(aFrame.iThreadContext);
// __ASSERT_ALWAYS(btraceThreadId, Panic(EBtpPanicUnknownCpuContext));
if (btraceThreadId)
{
HandleContextSwitchL(aFrame.iTickCount, *btraceThreadId);
}
else
{
iReader.Log(_L("BTrace::ENewThreadContext: Unknown thread context 0x%08x\r\n"), aFrame.iThreadContext);
}
break;
}
default:
{
// Ignore anything we don't know about.
++iNumIgnoredFrames;
break;
}
}
}
TestCpuUsagePeriodL(aFrame.iTickCount);
TestThreadIdlenessL(aFrame.iTickCount);
}
CBtraceCpuUsage::RCpuUsageNotif::RCpuUsageNotif(TUint32 aStartTickCount, TUint32 aNumNanoTicks, MBtraceCpuUsageObserver& aObserver, TBtraceNotificationPersistence aPersistence)
: iStartTickCount(aStartTickCount), iNumNanoTicks(aNumNanoTicks), iObserver(&aObserver), iPersistence(aPersistence)
{
}
void CBtraceCpuUsage::RCpuUsageNotif::RCpuUsageNotif::Close()
{
iUsage.Close();
}
CBtraceCpuUsage::TContextSwitchNotif::TContextSwitchNotif(const TBtraceThreadId& aId)
: iId(aId), iObserver(NULL)
{
}
CBtraceCpuUsage::TContextSwitchNotif::TContextSwitchNotif(const TBtraceThreadId& aId, MBtraceCpuUsageObserver& aObserver)
: iId(aId), iObserver(&aObserver)
{
}
CBtraceCpuUsage::TThreadIdleNotif::TThreadIdleNotif(const TBtraceThreadId& aId)
: iId(aId), iNumNanoTicks(0), iObserver(NULL), iEverScheduled(EFalse), iPersistence(ENotificationOneShot)
{
}
CBtraceCpuUsage::TThreadIdleNotif::TThreadIdleNotif(const TBtraceThreadId& aId, const TBtraceTickCount& aFromTickCount, TUint aNumNanoTicks, MBtraceCpuUsageObserver& aObserver, TBtraceNotificationPersistence aPersistence)
: iId(aId), iNumNanoTicks(aNumNanoTicks), iObserver(&aObserver), iLastSwitchedOut(aFromTickCount), iEverScheduled(EFalse), iPersistence(aPersistence)
{
}
void CBtraceCpuUsage::HandleContextSwitchL(const TBtraceTickCount& aTickCount, const TBtraceThreadId& aNewBtraceThreadId)
{
TBool relevant(EFalse);
if (iLastBtractThreadId.Value() != 0)
{
// Update CPU usage notifications for the thread that has been switched out.
for (TInt i = (iCpuUsageNotifs.Count() - 1); i >= 0; --i)
{
RCpuUsageNotif& notif = iCpuUsageNotifs[i];
TInt pos = notif.iUsage.FindInUnsignedKeyOrder(MBtraceCpuUsageObserver::TCpuUsage(iLastBtractThreadId));
if (pos >= 0)
{
MBtraceCpuUsageObserver::TCpuUsage& usage = notif.iUsage[pos];
usage.iNumFastTicks += aTickCount.IntervalInFastTicks(usage.iSwitchedInAt);
relevant = ETrue;
}
}
}
// Update CPU usage notifications to store this tick count at which this thread was switched in.
for (TInt i = (iCpuUsageNotifs.Count() - 1); i >= 0; --i)
{
relevant = ETrue;
RCpuUsageNotif& notif = iCpuUsageNotifs[i];
TInt pos = notif.iUsage.FindInUnsignedKeyOrder(aNewBtraceThreadId);
if (pos == KErrNotFound)
{
MBtraceCpuUsageObserver::TCpuUsage cpuUsage(aNewBtraceThreadId, aTickCount);
TInt err = notif.iUsage.InsertInUnsignedKeyOrder(cpuUsage);
__ASSERT_ALWAYS(err == KErrNone, Panic(EBtpPanicFailedToInsertCpuUsageObject));
}
else
{
notif.iUsage[pos].iSwitchedInAt = aTickCount;
}
}
// Inform context switch observers that are interested in switches from the previous thread.
TInt pos = iContextSwitchNotifs.SpecificFindInUnsignedKeyOrder(TContextSwitchNotif(iLastBtractThreadId), EArrayFindMode_First);
if (pos >= 0)
{
const TInt numNotifs = iContextSwitchNotifs.Count();
for (TInt i = 0; i < numNotifs; ++i)
{
const TContextSwitchNotif& thisNotif = iContextSwitchNotifs[i];
if (thisNotif.iId == iLastBtractThreadId)
{
relevant = ETrue;
thisNotif.iObserver->HandleContextSwitchL(aTickCount, iLastBtractThreadId, MBtraceCpuUsageObserver::EFromThisThread);
}
else
{
break;
}
}
}
// Inform context switch observers that are interested in switches to this new thread.
pos = iContextSwitchNotifs.SpecificFindInUnsignedKeyOrder(TContextSwitchNotif(aNewBtraceThreadId), EArrayFindMode_First);
if (pos >= 0)
{
const TInt numNotifs = iContextSwitchNotifs.Count();
for (TInt i = pos; i < numNotifs; ++i)
{
const TContextSwitchNotif& thisNotif = iContextSwitchNotifs[i];
if (thisNotif.iId == aNewBtraceThreadId)
{
relevant = ETrue;
thisNotif.iObserver->HandleContextSwitchL(aTickCount, aNewBtraceThreadId, MBtraceCpuUsageObserver::EToThisThread);
}
else
{
break;
}
}
}
// Update thread idle notifications' last switched out time.
pos = iThreadIdleNotifs.SpecificFindInUnsignedKeyOrder(TThreadIdleNotif(iLastBtractThreadId), EArrayFindMode_First);
if (pos >= 0)
{
const TInt numNotifs = iThreadIdleNotifs.Count();
for (TInt i = pos; i < numNotifs; ++i)
{
TThreadIdleNotif& thisNotif = iThreadIdleNotifs[i];
if (thisNotif.iId == iLastBtractThreadId)
{
relevant = ETrue;
thisNotif.iLastSwitchedOut = aTickCount;
}
else
{
break;
}
}
}
// Update thread idle notifications' ever scheduled.
pos = iThreadIdleNotifs.SpecificFindInUnsignedKeyOrder(TThreadIdleNotif(aNewBtraceThreadId), EArrayFindMode_First);
if (pos >= 0)
{
const TInt numNotifs = iThreadIdleNotifs.Count();
for (TInt i = pos; i < numNotifs; ++i)
{
TThreadIdleNotif& thisNotif = iThreadIdleNotifs[i];
if (thisNotif.iId == aNewBtraceThreadId)
{
relevant = ETrue;
thisNotif.iEverScheduled = ETrue;
}
else
{
break;
}
}
}
iLastBtractThreadId = aNewBtraceThreadId;
if (relevant)
{
++iNumRelevantFrames;
}
}
TInt CompareUsage(const MBtraceCpuUsageObserver::TCpuUsage& aFirst,const MBtraceCpuUsageObserver::TCpuUsage& aSecond)
{
if (aFirst.iNumFastTicks > aSecond.iNumFastTicks)
{
return -1;
}
else if (aFirst.iNumFastTicks < aSecond.iNumFastTicks)
{
return 1;
}
else
{
return 0;
}
}
void CBtraceCpuUsage::TestCpuUsagePeriodL(const TBtraceTickCount& aTickCount)
{
for (TInt i = (iCpuUsageNotifs.Count() - 1); i >= 0; --i)
{
RCpuUsageNotif& thisNotif = iCpuUsageNotifs[i];
if ((aTickCount.iNano - thisNotif.iStartTickCount) >= thisNotif.iNumNanoTicks)
{
thisNotif.iUsage.Sort(TLinearOrder<MBtraceCpuUsageObserver::TCpuUsage>(CompareUsage));
TArray<MBtraceCpuUsageObserver::TCpuUsage> array(thisNotif.iUsage.Array());
thisNotif.iObserver->HandleCpuUsageL(aTickCount, array);
if (thisNotif.iPersistence == ENotificationOneShot)
{
thisNotif.Close();
iCpuUsageNotifs.Remove(i);
}
}
}
}
void CBtraceCpuUsage::TestThreadIdlenessL(const TBtraceTickCount& aTickCount)
{
for (TInt i = (iThreadIdleNotifs.Count() - 1); i >= 0; --i)
{
const TThreadIdleNotif& thisNotif = iThreadIdleNotifs[i];
//iReader.Log(_L("CBtraceCpuUsage::TestThreadIdlenessL: now %d, lastswitch %d, remaining %d\r\n"), aTickCount.iNano, thisNotif.iLastSwitchedOut.iNano, thisNotif.iNumNanoTicks - (aTickCount.iNano - thisNotif.iLastSwitchedOut.iNano));
if ((aTickCount.iNano > thisNotif.iLastSwitchedOut.iNano) && ((aTickCount.iNano - thisNotif.iLastSwitchedOut.iNano) >= thisNotif.iNumNanoTicks))
{
MBtraceCpuUsageObserver* observer = thisNotif.iObserver;
TBtraceTickCount lastSwitchedOut = thisNotif.iLastSwitchedOut;
TBtraceThreadId threadId = thisNotif.iId;
MBtraceCpuUsageObserver::TIdleType idleType = thisNotif.iEverScheduled ? MBtraceCpuUsageObserver::EScheduledAtLeastOnce : MBtraceCpuUsageObserver::ENeverScheduled;
if (thisNotif.iPersistence == ENotificationOneShot)
{
iThreadIdleNotifs.Remove(i);
}
observer->HandleThreadIdleL(lastSwitchedOut, threadId, idleType);
}
}
}