diff -r d27dfa8884ad -r da2cedce4920 piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp Tue May 25 14:22:58 2010 +0300 @@ -0,0 +1,1152 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +// +// LDD for thread time profiling +// + +#include +#include +#include + +#ifdef __SMP__ +#include +#include +#include +#endif + +#include "GeneralsDriver.h" +#include +#include +#include + +#include "GppSamplerImpl.h" +#include "GfcSamplerImpl.h" +#include "IttSamplerImpl.h" +#include "MemSamplerImpl.h" +#include "PriSamplerImpl.h" + + +#ifndef __SMP__ +extern TUint* IntStackPtr(); +extern void UsrModLr(TUint32*); +#endif +// for security check +#define KProfilerExeSecurUid 0x2001E5AD +static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); +static _LIT_SECURITY_POLICY_FAIL( KDenyAllPolicy ); + +#define SEPARATE_DFC_QUEUE +// CONSTANTS + +//_LIT(DProfilerThread,"DProfilerThread"); +//const TInt KDProfilerThreadPriority = 27; + +#ifdef SEPARATE_DFC_QUEUE +const TInt KGeneralsDriverThreadPriority = 24; +_LIT(KGeneralsDriverThread, "PIGeneralsDriver"); + +#endif + +// global Dfc Que +//TDynamicDfcQue* gDfcQ; + +//#ifdef __SMP__ +// +//enum TNaviEngineAsspInterruptIdExtension +//{ +// KIntProfilerBase = 99 // Sampling profiler interrupt base. +// // Each CPU is assigned a sampling interrupt from this base +// // CPU-0's sampling interrupt is KIntIdSamplingBase + 0 +// // CPU-n's sampling interrupt is KIntIdSamplingBase + n +//}; +//#endif + +/* + * + * + * Class DGfcProfilerFactory definition + * + * + */ + +class DGeneralsProfilerFactory : public DLogicalDevice +{ + public: + DGeneralsProfilerFactory(); + ~DGeneralsProfilerFactory(); + + public: + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); +}; + +/* + * + * + * Class DGfcDriver definition + * + * + */ +class DPluginDriver; + +class DGeneralsDriver : public DPluginDriver +{ + +public: + DGeneralsDriver(); + ~DGeneralsDriver(); + +private: + TInt NewStart(TInt aRate); + static void NewDoProfilerProfile(TAny*); + static void NewDoDfc(TAny*); + + // called by each core + static void Sample(TAny*); + + TInt GetSampleTime(TUint32* time); + //TInt Test(TUint32 testCase); + + TInt StartSampling(); + TInt StopSampling(); + + void InitialiseSamplerList(); + + DProfilerSamplerBase* GetSamplerForId(TInt samplerId); + TInt GetSamplerVersion(TDes* aDes); + +#ifdef __SMP__ + void UnbindInterrupts(); +#endif + TInt ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus); + + TInt MarkTraceActive(TInt samplerIdToActivate); + TInt MarkTraceInactive(TInt samplerIdToDisable); + TInt OutputSettingsForTrace(TInt samplerId,TInt settings); + TInt AdditionalTraceSettings(TInt samplerId,TInt settings); + TInt AdditionalTraceSettings2(TInt samplerId,TInt settings); + TInt SetSamplingPeriod(TInt /*samplerId*/,TInt settings); +private: + // create the driver in EKA-2 version + TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + + // receive commands and control in EKA-2 version + void HandleMsg(TMessageBase* aMsg); +private: + // timer mechanism in EKA-2 version + NTimer iTimer; + TDfc iNewDfc; + TInt iCount; + TInt iLastPcVal; + TInt iPeriod; + + // sync sample number property for synchronizing other samplers + RPropertyRef iSampleStartTimeProp; + TInt iSampleStartTime; + + DProfilerGppSampler<10000> gppSampler; +#ifdef __SMP__ + DProfilerGppSampler<10000> gppSampler2; + DProfilerGppSampler<10000> gppSampler3; + DProfilerGppSampler<10000> gppSampler4; +#endif + DProfilerGfcSampler<10000> gfcSampler; + DProfilerIttSampler<10000> ittSampler; + DProfilerMemSampler<40000> memSampler; + DProfilerPriSampler<10000> priSampler; +#ifdef __SMP__ +// DProfilerPriSampler<10000> priSampler2; +// DProfilerPriSampler<10000> priSampler3; +// DProfilerPriSampler<10000> priSampler4; +#endif + +#ifndef __SMP__ + static const TInt KSamplerAmount = 5; +#else + static const TInt KSamplerAmount = 8; +#endif + DProfilerSamplerBase* iSamplers[KSamplerAmount]; + TInt iMaxCpus; + TUint32 iStartTime; + +#ifdef SEPARATE_DFC_QUEUE + TDynamicDfcQue* iDfcQ; +#endif +}; + +/* + * + * + * Class DGeneralsProfilerFactory implementation + * + * + */ + +DECLARE_STANDARD_LDD() + { + return new DGeneralsProfilerFactory(); + } + +TInt DGeneralsProfilerFactory::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DGeneralsDriver; + return aChannel?KErrNone:KErrNoMemory; + } + + +DGeneralsProfilerFactory::DGeneralsProfilerFactory() + { + // major, minor, and build version number + iVersion=TVersion(1,0,1); + } + +DGeneralsProfilerFactory::~DGeneralsProfilerFactory() + { +// if (gDfcQ) +// { +// gDfcQ->Destroy(); +// } + } + +TInt DGeneralsProfilerFactory::Install() + { + return(SetName(&KPluginSamplerName)); + } + +void DGeneralsProfilerFactory::GetCaps(TDes8& aDes) const + { + TCapsSamplerV01 b; + + b.iVersion=TVersion(1,0,1); + + aDes.FillZ(aDes.MaxLength()); + aDes.Copy((TUint8*)&b,Min(aDes.MaxLength(),sizeof(b))); + } + +/* + * + * + * Class DGeneralsDriver implementation + * + * + */ + +DGeneralsDriver::DGeneralsDriver() : + iTimer(NewDoProfilerProfile,this), + iNewDfc(NewDoDfc,this,NULL,7), +#ifdef __SMP__ + gppSampler(0), + gppSampler2(1), + gppSampler3(2), + gppSampler4(3), +#endif + gfcSampler(gppSampler.GetExportData()), + ittSampler(gppSampler.GetExportData()), + memSampler(gppSampler.GetExportData(), PROFILER_MEM_SAMPLER_ID), + priSampler(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID) +#ifdef __SMP__ +// ,priSampler2(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID), +// priSampler3(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID), +// priSampler4(gppSampler.GetExportData(), PROFILER_PRI_SAMPLER_ID) +#endif + { + LOGSTRING("DGeneralsDriver::DGeneralsDriver()"); + + iState = EStopped; + iEndRequestStatus = 0; + doingDfc = 0; + sampleRunning = 0; + iSyncOffset = 0; + iStartTime = 0; + InitialiseSamplerList(); + } + +/* + * + * This method has to be changed for each new sampler + * + */ +void DGeneralsDriver::InitialiseSamplerList() + { + // initialize all samplers to zero + for(TInt i(0);iiSamplerId == samplerIdToGet) + { + return iSamplers[i]; + } + } + return (DProfilerSamplerBase*)0; + } + +TInt DGeneralsDriver::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) + { + TUint8 err(KErrNone); + + if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer)) + return KErrNotSupported; + + // just for testing +#ifndef __SMP__ + LOGTEXT("Initializing the stack pointer"); + stackTop=(TUint32*)IntStackPtr(); + LOGSTRING2("Got stack pointer 0x%x",(TUint32)stackTop); +#endif + + iClient = &Kern::CurrentThread(); + err = iClient->Open(); + + DProcess* clientProcess(iClient->iOwningProcess); + if (clientProcess) + { + //Require Power Management and All Files to use this driver + // Not ideal, but better than nothing + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) + return KErrPermissionDenied; + if(!Kern::CurrentThreadHasCapability(ECapabilityAllFiles,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) + return KErrPermissionDenied; + + SSecurityInfo secureInfo = clientProcess->iS; + if (secureInfo.iSecureId != KProfilerExeSecurUid) + { + return KErrPermissionDenied; + } + } + + // initiate sample stream ready for collecting the trace data + iSampleStream.InsertCurrentClient(iClient); + + iTimer.Cancel(); + iNewDfc.Cancel(); + + Kern::SetThreadPriority(24); + +#ifdef SEPARATE_DFC_QUEUE + err = Kern::DynamicDfcQCreate(iDfcQ, KGeneralsDriverThreadPriority, TBuf8<32>( KGeneralsDriverThread )); + if (KErrNone == err) + { + SetDfcQ(iDfcQ); + iNewDfc.SetDfcQ(iDfcQ); + iMsgQ.Receive(); + return err; + } +#else + SetDfcQ(Kern::DfcQue0()); + iNewDfc.SetDfcQ(iDfcQ); + iMsgQ.Receive(); +#endif + return err; + } + +DGeneralsDriver::~DGeneralsDriver() + { + if (iState!=EStopped) + iTimer.Cancel(); + iNewDfc.Cancel(); + +#ifdef SEPARATE_DFC_QUEUE + if(iDfcQ) + iDfcQ->Destroy(); +#endif + + iSampleStartTimeProp.Close(); + Kern::SafeClose((DObject*&)iClient,NULL); + } + + +TInt DGeneralsDriver::GetSampleTime(TUint32* time) + { + LOGSTRING("DGeneralsDriver::GetSampleTime - entry"); + + Kern::ThreadRawWrite( iClient,(TAny*)time, + (TAny*)&gppSampler.GetExportData()->sampleNumber, + 4, iClient); + + LOGSTRING("DGeneralsDriver::GetSampleTime - exit"); + + return KErrNone; + } + + +TInt DGeneralsDriver::GetSamplerVersion(TDes* aDes) + { + LOGSTRING2("DGeneralsDriver::GetSamplerVersion - 0x%x",aDes); + + TBuf8<16> aBuf; + aBuf.Append(PROFILER_SAMPLER_VERSION); + Kern::ThreadDesWrite(iClient,aDes,aBuf,0,KChunkShiftBy0,iClient); + LOGSTRING("DGeneralsDriver::GetSamplerVersion - written client descriptor"); + return KErrNone; + } + +TInt DGeneralsDriver::NewStart(TInt aDelay) + { + LOGSTRING("DGeneralsDriver::NewStart"); + iEndRequestStatus = 0; + + aDelay = Min(KMaxDelay, Max(KMinDelay, aDelay)); + + // always use this rate + iPeriod = aDelay; + +#ifdef __SMP__ + /* + * Bind and enable the sampling interupts associated with each core. + */ + TInt err(0); + + TUint32 flags = NKern::EIrqBind_Count; + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); + err = NKern::InterruptBind( KIntProfilerBase - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); + err = NKern::InterruptBind( KIntProfilerBase + 1 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 1 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); + err = NKern::InterruptBind(KIntProfilerBase + 2 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 2 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); + err = NKern::InterruptBind(KIntProfilerBase + 3 - 32 , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + Kern::Printf(" InterruptBind KIntProfilerBase + 3 - 32 ret = %d", err ); + + + err = NKern::InterruptEnable(KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 1 - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 2 - 32 ret = %d", err ); + + err = NKern::InterruptEnable(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptEnable KIntProfilerBase + 3 - 32 ret = %d", err ); + +#endif + + iTimer.OneShot(aDelay); + + iState = ERunning; + + return KErrNone; + } + +/* + * This function is run in each interrupt + */ +// EKA-2 implementation of the sampler method + +void DGeneralsDriver::NewDoProfilerProfile(TAny* aPtr) + { + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - entry"); + +#ifdef __SMP__ + TInt currCpu(NKern::CurrentCpu()); +#endif + TInt8 postSampleNeeded(0); + DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; + + if (d.iState == ERunning && d.sampleRunning == 0) + { + // start timer again + d.iTimer.Again(d.iPeriod); + d.sampleRunning++; + +#ifdef __SMP__ + // print out the sample tick + if(d.gppSampler.GetExportData()->sampleNumber% 1000 == 0) + { + Kern::Printf(("PIPROF SAMPLE TICK, #%d"), d.gppSampler.GetExportData()->sampleNumber); + } + // call the actual CPU sampling function for CPU 0 (in NaviEngine), later may be on any of the CPUs + Sample(aPtr); + + // post-sampling for NTimer interrupted CPU + postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); + + /* + This is the master sampler from the watchdog timer, so + send interrupts to the other CPUs + */ + TScheduler *theSched = TScheduler::Ptr(); + GicDistributor* gicDist = (GicDistributor* )theSched->i_GicDistAddr; + + for( TInt nCpu(0); nCpu < d.iMaxCpus; nCpu++ ) + { + if( nCpu != currCpu ) + { + gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (KIntProfilerBase + nCpu); + } + // post-sampling for CPUs with specifically generated interrupts + postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); + } + arm_dsb(); +#endif + // then sample the rest of non-cpu samplers + for(TInt i(d.iMaxCpus);iiEnabled) + { + d.iSamplers[i]->Sample(); + postSampleNeeded += d.iSamplers[i]->PostSampleNeeded(); + } + } + + if(postSampleNeeded > 0 && d.doingDfc == 0) + { + d.doingDfc++; + d.iNewDfc.Add(); + + d.sampleRunning--; + return; + } + d.sampleRunning--; + } + else if (d.iState == EStopping && d.sampleRunning == 0) + { + // add a dfc for this final time + d.iNewDfc.Add(); + Kern::Printf("DGeneralsDriver::Sample - sampling added to dfc queue"); + } + else + { + // the previous sample has not finished, + Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - Profiler Sampler Error - interrupted before finished sampling!!"); + } + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - exit"); + } + + + +void DGeneralsDriver::Sample(TAny* aPtr) + { + LOGSTRING("DGeneralsDriver::Sample - entry"); + +#ifdef __SMP__ + DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; + +// TInt currCpu(NKern::CurrentCpu()); + + // sample the current cpu load +// if(d.iSamplers[currCpu]->iEnabled) +// { + d.iSamplers[NKern::CurrentCpu()]->Sample(); +// postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); +// } +#endif + LOGSTRING("DGeneralsDriver::Sample - exit"); + } +/* + * This function is run when any of the samplers + * requires post sampling + */ +void DGeneralsDriver::NewDoDfc(TAny* pointer) + { + DGeneralsDriver& d(*((DGeneralsDriver*)pointer)); + + if(d.iState == ERunning) + { + // for all enabled samplers, perform + // post sample if needed + for(TInt i(0);iiEnabled) + { + if(d.iSamplers[i]->PostSampleNeeded()) + { + d.iSamplers[i]->PostSample(); + } + } + } + d.doingDfc--; + } + + else if(d.iState == EStopping) + { + // for all enabled samplers, + // perform end sampling + TBool releaseBuffer(false); + for(TInt i(0);iiEnabled) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); + // perform end sampling for all samplers + // stream mode samplers may be pending, if they + // are still waiting for another client buffer + if(d.iSamplers[i]->EndSampling() == KErrNotReady) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - stream data pending"); + releaseBuffer = true; + } + else + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); + releaseBuffer = true; + } + } + } + + // At the end, once all the samplers are gone through, the buffer should be released + if (true == releaseBuffer) + { + LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); + d.iSampleStream.ReleaseIfPending(); + } + + d.iState = EStopped; + if(d.iEndRequestStatus != 0 && d.iClient != 0) + { + // sampling has ended + Kern::RequestComplete(d.iClient,d.iEndRequestStatus,KErrNone); + } + } + } + + +/* + * All controls are handled here + */ + +void DGeneralsDriver::HandleMsg(TMessageBase* aMsg) + { + TInt r(KErrNone); + TThreadMessage& m(*(TThreadMessage*)aMsg); + + LOGSTRING5("DGeneralsDriver::HandleMsg 0x%x 0x%x 0x%x 0x%x",m.Int0(),m.Int1(),m.Int2(),m.Int3()); + + if(m.iValue == (TInt)ECloseMsg) + { + LOGSTRING("DGeneralsDriver::HandleMsg - received close message"); + iTimer.Cancel(); + iNewDfc.Cancel(); + + m.Complete(KErrNone,EFalse); + iMsgQ.CompleteAll(KErrServerTerminated); + LOGSTRING("DGeneralsDriver::HandleMsg - cleaned up the driver!"); + return; + } + + if (m.Client()!=iClient) + { + LOGSTRING("DGeneralsDriver::HandleMsg - ERROR, wrong client"); + m.PanicClient(_L("GENERALSSAMPLER"),EAccessDenied); + return; + } + + TInt id(m.iValue); + switch(id) + { + //Controls are handled here + case RPluginSampler::EMarkTraceActive: + LOGSTRING("DGeneralsDriver::HandleMsg - EMarkTraceActive"); + r = MarkTraceActive((TInt)m.Int0()); + break; + + case RPluginSampler::EOutputSettingsForTrace: + LOGSTRING("DGeneralsDriver::HandleMsg - EOutputSettingsForTrace"); + r = OutputSettingsForTrace((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EAdditionalTraceSettings: + LOGSTRING("DGeneralsDriver::HandleMsg - EAdditionalTraceSettings"); + r = AdditionalTraceSettings((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EAdditionalTraceSettings2: + LOGSTRING("DGeneralsDriver::HandleMsg - EAdditionalTraceSettings2"); + r = AdditionalTraceSettings2((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::ESetSamplingPeriod: + LOGSTRING2("DGeneralsDriver::HandleMsg - ESetSamplingPeriod %d", (TInt)m.Int1()); + r = SetSamplingPeriod((TInt)m.Int0(),(TInt)m.Int1()); + break; + + case RPluginSampler::EMarkTraceInactive: + LOGSTRING("DGeneralsDriver::HandleMsg - EMarkTraceInactive"); + r = MarkTraceInactive((TInt)m.Int0()); + break; + + case RPluginSampler::ESample: + LOGSTRING("DGeneralsDriver::HandleMsg - ESample"); + //r = Sample(); // hack. Original implementation of sample just returned 0 + r = 0; + break; + + case RPluginSampler::EStartSampling: + LOGSTRING("DGeneralsDriver::HandleMsg - EStartSampling"); + r = StartSampling(); + break; + + case RPluginSampler::EGetSampleTime: + LOGSTRING("DGeneralsDriver::HandleMsg - EGetSampleTime"); + r = GetSampleTime(reinterpret_cast(m.Ptr0())); + break; + + case RPluginSampler::EGetSamplerVersion: + LOGSTRING("DGeneralsDriver::HandleMsg - EGetSamplerVersion"); + r = GetSamplerVersion(reinterpret_cast(m.Ptr0())); + break; + + case RPluginSampler::ECancelStreamRead: + LOGSTRING("DGeneralsDriver::HandleMsg - ECancelStreamRead"); + iStreamReadCancelStatus = reinterpret_cast(m.Ptr0()); + r = ProcessStreamReadCancel(); + break; + + + // Requests are handled here + + case ~RPluginSampler::EStopAndWaitForEnd: + LOGSTRING("DGeneralsDriver::HandleMsg - EStopAndWaitForEnd"); + iEndRequestStatus = reinterpret_cast(m.Ptr0()); + r = StopSampling(); +#ifdef __SMP__ + UnbindInterrupts(); +#endif + break; + + case ~RPluginSampler::ERequestFillThisStreamBuffer: + LOGSTRING("DGeneralsDriver::HandleMsg - ERequestFillThisStreamBuffer"); + r = ProcessStreamReadRequest( reinterpret_cast(m.Ptr1()), + reinterpret_cast(m.Ptr0())); + break; + + default: + LOGSTRING2("DGeneralsDriver::HandleMsg - ERROR, unknown command %d",id); + r = KErrNotSupported; + break; + } + + LOGSTRING("DGeneralsDriver::HandleMsg - Completed"); + m.Complete(r,ETrue); + } + +#ifdef __SMP__ +inline void DGeneralsDriver::UnbindInterrupts() + { + TInt err(0); + + // disable interrupts when sampling stops, enabled again on start + err = NKern::InterruptDisable(KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 1 - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 2 - 32 ret = %d", err ); + + err = NKern::InterruptDisable(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptDisable KIntProfilerBase + 3 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); + err = NKern::InterruptUnbind( KIntProfilerBase - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); + err = NKern::InterruptUnbind( KIntProfilerBase + 1 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 1 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); + err = NKern::InterruptUnbind(KIntProfilerBase + 2 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 2 - 32 ret = %d", err ); + +// Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); + err = NKern::InterruptUnbind(KIntProfilerBase + 3 - 32); + if(err < 0) + Kern::Printf(" InterruptUnbind KIntProfilerBase + 3 - 32 ret = %d", err ); + + } +#endif + +inline TInt DGeneralsDriver::ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - entry"); + + // a new sample buffer has been received from the client + iSampleStream.AddSampleBuffer(aBuf,aStatus); + + // check if we are waiting for the last data to be written to the client + if(iState == EStopped) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest state = EStopped"); + + // sampling has stopped and stream read cancel is pending + // try to perform the end sampling procedure again + TBool releaseBuffer(false); + for(TInt i(0);iiEnabled /*&& samplers[i]->outputMode == 2*/) + { + //TInt pending = 0; + // stream mode samplers may be pending, if they + // are still waiting for another client buffer, + // in that case, the request should be completed already + if(iSamplers[i]->EndSampling() == KErrNotReady) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - still data pending"); + releaseBuffer = true; + } + else + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - no data pending"); + releaseBuffer = true; + } + } + } + // At the end, once all the samplers are gone through, the buffer should be released + if (true == releaseBuffer) + { + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - all data copied, release the buffer"); + iSampleStream.ReleaseIfPending(); + } + } + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - exit"); + + return KErrNone; + } + + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +inline TInt DGeneralsDriver::MarkTraceActive(TInt samplerIdToActivate) + { + LOGSTRING2("DGeneralsDriver::MarkTraceActive %d",samplerIdToActivate); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerIdToActivate == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetEnabledFlag(true); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerIdToActivate) + { + iSamplers[i]->SetEnabledFlag(true); + return KErrNone; + } + } + + LOGSTRING2("DGeneralsDriver::MarkTraceActive - %d not supported",samplerIdToActivate); + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::MarkTraceInactive(TInt samplerIdToDisable) + { + LOGSTRING2("DGeneralsDriver::MarkTraceInactive %d",samplerIdToDisable); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerIdToDisable == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetEnabledFlag(false); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerIdToDisable) + { + iSamplers[i]->SetEnabledFlag(false); + return KErrNone; + } + } + + LOGSTRING2("DGeneralsDriver::MarkTraceInactive - %d not supported",samplerIdToDisable); + return KErrNotSupported; + } + +/* + * Set output settings for a trace + */ + +inline TInt DGeneralsDriver::OutputSettingsForTrace(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::OutputSettingsForTrace id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetOutputCombination(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerId) + { + iSamplers[i]->SetOutputCombination(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +/* + * Set additional settings for a trace + */ + +inline TInt DGeneralsDriver::AdditionalTraceSettings(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::SetAdditionalTraceSettings id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetAdditionalSettings(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerId) + { + iSamplers[i]->SetAdditionalSettings(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::AdditionalTraceSettings2(TInt samplerId,TInt settings) + { + LOGSTRING3("DGeneralsDriver::SetAdditionalTraceSettings id:%d set:%d",samplerId,settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetAdditionalSettings2(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerId) + { + iSamplers[i]->SetAdditionalSettings2(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +inline TInt DGeneralsDriver::SetSamplingPeriod(TInt samplerId,TInt settings) + { + LOGSTRING2("DGeneralsDriver::SetSamplingPeriod - set:%d",settings); + + TInt cpus(0); +#ifdef __SMP__ + cpus = NKern::NumberOfCpus(); + if( samplerId == PROFILER_GPP_SAMPLER_ID ) + { + for(TInt cpu(0);cpuSetSamplingPeriod(settings); + } + return KErrNone; + } +#endif + for(TInt i(cpus);iiSamplerId == samplerId) + { + iSamplers[i]->SetSamplingPeriod(settings); + return KErrNone; + } + } + + return KErrNotSupported; + } + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +TInt DGeneralsDriver::StartSampling() + { + LOGSTRING("DGeneralsDriver::StartSampling"); + + if(iState == EStopped) + { + // reset iSampleStartTimeProp property value + iSampleStartTime = NKern::TickCount(); // get the system tick value for sync purposes +#ifdef __SMP__ + iStartTime = (iSampleStartTime & 0xfffffff0); +#endif + TInt r(iSampleStartTimeProp.Set(iSampleStartTime)); + + Kern::Printf(("PIPROF SAMPLE TICK, #0")); // for remote profiling with Profiler Activator + + // reset all enabled samplers + for(TInt i(0);iiEnabled) + { + // reset with stream option +#ifndef __SMP__ + Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, sync offset %d"), 0); + iSamplers[i]->Reset(&iSampleStream, 0); +#else + Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, start time %d"), iStartTime); + iSamplers[i]->Reset(&iSampleStream, iStartTime); +#endif + } + } + + NewStart(gppSampler.GetPeriod()); + return KErrNone; + } + else + { + return KErrGeneral; + } + } + +/* + * Mark traces active or inactive, this can be done + * only if sampling is not running + */ + +TInt DGeneralsDriver::StopSampling() + { + LOGSTRING("DGeneralsDriver::StopSampling"); + + if(iState == ERunning) + { + this->iState = EStopping; + // reset all enabled samplers + for(TInt i(0);iiEnabled && iSamplers[i]->iSamplerId == 4) + { + // reset with stream option + LOGTEXT(("DGeneralsDriver::StopSampling - stream reset for samplers")); + iSamplers[i]->Reset(&iSampleStream, 999999); + } + } + + return KErrNone; + } + else + { + return KErrGeneral; + } + } + +