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.
// sampler.cpp
//
// Copyright (c) 1999 - 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 <platform.h>
#include "sampler.h"
//#include <nkern.h>
//#include <kernel.h>
#include <kern_priv.h>
_LIT(KLddName,"topsampler");
const TInt KMinRate=10;
const TInt KMaxRate=1000;
const TInt KRawBufSize = 20000; // Enough for 20 seconds of samples - since max expected refresh rate in UI is 10s we can do everything nice and simply with one buffer
class DDeviceSampler : public DLogicalDevice
{
public:
DDeviceSampler();
virtual TInt Install();
virtual void GetCaps(TDes8& aDes) const;
virtual TInt Create(DLogicalChannelBase*& aChannel);
};
class DProfile : public DLogicalChannel
{
public:
DProfile();
~DProfile();
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 Reset();
//TInt GetErrors(TDes8* aDes);
TInt ProcessReadRequest();
void Complete(TInt aResult);
inline TBool Running()
{return iTimer.iState!=NTimer::EIdle;}
private:
static void Sample(TAny*);
void DoSample();
private:
TUint32 iStartTime;
TInt iRepeat;
TInt iPeriod;
DThread* iClient;
TRequestStatus* iReqStatus;
TDes8* iClientDes; // client des pointer
TUint32 iBuf1[KRawBufSize]; // First word is the current position in the buffer
TUint32 iBuf2[KRawBufSize]; // Have two buffers that we can switch between, this avoids us having to stop the sampler timer, or disable interrupts or whatever, when we want to drain the buffer
TUint32* iCurrentBuf; // Pointer to either iBuf1 or iBuf2
struct TReport
{
TUint iRawBufferErrCounter;
TUint iCodeSegErrCounter;
TInt iReportMask;
} iReport;
NTimer iTimer;
};
DECLARE_STANDARD_LDD()
{
return new DDeviceSampler;
}
DDeviceSampler::DDeviceSampler()
//
// Constructor
//
{
//iParseMask=0;
//iUnitsMask=0;
iVersion=TVersion(1,0,0);
}
TInt DDeviceSampler::Install()
//
// Install the device driver.
//
{
TInt r=SetName(&KLddName);
return r;
}
void DDeviceSampler::GetCaps(TDes8& /*aDes*/) const
//
// Return the capabilities.
//
{
}
TInt DDeviceSampler::Create(DLogicalChannelBase*& aChannel)
//
// Create a channel on the device.
//
{
aChannel=new DProfile;
return aChannel?KErrNone:KErrNoMemory;
}
DProfile::DProfile()
: iTimer(Sample,this)
//
// Constructor
//
{
iCurrentBuf = iBuf1;
iCurrentBuf[0] = 1;
}
DProfile::~DProfile()
//
// Destructor
//
{
iTimer.Cancel();
Kern::SafeClose((DObject*&)iClient, NULL);
}
TInt DProfile::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
//
// Create the channel from the passed info.
//
{
if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer))
return KErrNotSupported;
iClient=&Kern::CurrentThread();
iClient->Open();
//Kern::SetThreadPriority(24);
SetDfcQ(Kern::DfcQue0());
iMsgQ.Receive();
return KErrNone;
}
void DProfile::Complete(TInt aResult)
//Completes user request
{
DEBUG_PROFILER(Kern::Printf("C");)
Kern::RequestComplete(iClient,iReqStatus,aResult);
}
TInt DProfile::StartSampling(TInt aRate)
{
DEBUG_PROFILER(Kern::Printf("START");)
//Activate timer
aRate=Min(KMaxRate, Max(KMinRate, aRate));
iPeriod=1000/aRate;
if (!Running())
{
iCurrentBuf = iBuf1;
iCurrentBuf[0] = 1;
iTimer.OneShot(iPeriod);
}
DEBUG_PROFILER(Kern::Printf("START end");)
return KErrNone;
}
TInt DProfile::Reset()
{
//
// Resets the device. It is the first message sent by profiler application.
//
if (Running())
return KErrGeneral;
DEBUG_PROFILER(Kern::Printf("RST %d", aXIPOnly);)
iTimer.Cancel();
iPeriod=1;
iReqStatus=NULL;
iClientDes=NULL;
iReport.iRawBufferErrCounter = 0;
iReport.iCodeSegErrCounter = 0;
iReport.iReportMask = 0;
DEBUG_PROFILER(Kern::Printf("RST end");)
return KErrNone;
}
TInt DProfile::StopSampling()
//
// Stops sampling
//
{
DEBUG_PROFILER(Kern::Printf("STOP");)
if (Running())
{
iTimer.Cancel();
}
if (iReqStatus)
Complete(KErrNone);
DEBUG_PROFILER(Kern::Printf("STOP end");)
return KErrNone;
}
TInt DProfile::ProcessReadRequest()
{
// Whatever the status of the profiler, return the contents of the current sampling buffer
DEBUG_PROFILER(Kern::Printf("READ");)
TInt max=Kern::ThreadGetDesMaxLength(iClient, iClientDes);
if (max<0)
return max;
if (max==0)
return KErrArgument;
TUint32* otherBuf = (iCurrentBuf == iBuf1 ? iBuf2 : iBuf1);
otherBuf[0] = 1; // Reset other buf
TUint32* bufToWrite = iCurrentBuf;
iCurrentBuf = otherBuf; // And switch do it, so we can safely mess with bufToWrite without the sampling ISR adding more data under our feet
TInt numSamples = bufToWrite[0] - 1; // Because bufToWrite[0] is an index and the data actually starts at index 1
TPtrC8 desToWrite((TUint8*)&bufToWrite[1], (numSamples)*sizeof(TUint32));
TInt r = Kern::ThreadDesWrite(iClient, iClientDes, desToWrite, 0, 0, iClient);
return r;
}
void DProfile::HandleMsg(TMessageBase* aMsg)
//
// Client requests
//
{
TInt r=KErrNone;
TThreadMessage& m=*(TThreadMessage*)aMsg;
//BEGIN TOMSCI commented out this check as it is too strict
/*
if (m.Client()!=iClient)
{
m.PanicClient(_L("SAMPLER"),EAccessDenied);
return;
}
*/
//END TOMSCI
TInt id=m.iValue;
if (id==(TInt)ECloseMsg)
{
DEBUG_PROFILER(Kern::Printf("CLOSE");)
iTimer.Cancel();
m.Complete(KErrNone,EFalse);
iMsgQ.CompleteAll(KErrServerTerminated);
DEBUG_PROFILER(Kern::Printf("CLOSE end");)
return;
}
else if (id<0)
{
if (id!=~RSampler::ERequestRead)
{
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
Kern::RequestComplete(iClient,pS,KErrNotSupported);
}
if (iReqStatus)
{
m.PanicClient(_L("SAMPLER"),ERequestAlreadyPending);
return;
}
iReqStatus=(TRequestStatus*)m.Ptr0();
iClientDes=(TDes8*)m.Ptr1();
TInt err = ProcessReadRequest();
Complete(err);
}
else if (id==KMaxTInt)
{
TInt mask=m.Int0();
if (mask & (1<<RSampler::ERequestRead))
{
Complete(KErrCancel);
}
}
else
{
switch(id)
{
case RSampler::EControlStartProfile:
r=StartSampling(m.Int0());
break;
case RSampler::EControlStopProfile:
r=StopSampling();
break;
case RSampler::EControlResetProfile:
r=Reset();
break;
//case RSampler::EControlGetErrors:
// r=GetErrors((TDes8*)m.Ptr0());
// break;
default:
r=KErrNotSupported;
break;
}
}
m.Complete(r,ETrue);
}
void DProfile::Sample(TAny* aPtr)
{
DProfile& d=*(DProfile*)aPtr;
d.DoSample();
}
void DProfile::DoSample()
{
iTimer.Again(iPeriod);
TUint32& currentPos = iCurrentBuf[0];
if (currentPos < (TUint)KRawBufSize) // space in buffer
{
DThread* pT=Kern::NThreadToDThread(NKern::CurrentThread());
if (pT!=NULL)
{
iCurrentBuf[currentPos] = pT->iId;
currentPos++;
}
}
else
iReport.iRawBufferErrCounter++;
}