diff -r aa2539c91954 -r 1c2bb2fc7c87 perfsrv/piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp --- a/perfsrv/piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp Fri Oct 08 14:56:39 2010 +0300 +++ b/perfsrv/piprofiler/plugins/GeneralsPlugin/src/GeneralsDriver.cpp Tue Oct 26 16:20:32 2010 +0300 @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef __SMP__ #include @@ -51,36 +52,24 @@ static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy); static _LIT_SECURITY_POLICY_FAIL( KDenyAllPolicy ); -#define SEPARATE_DFC_QUEUE // CONSTANTS - //_LIT(DProfilerThread,"DProfilerThread"); -//const TInt KDProfilerThreadPriority = 27; +const TInt KDSamplerThreadPriority = 27; -#ifdef SEPARATE_DFC_QUEUE const TInt KGeneralsDriverThreadPriority = 24; _LIT(KGeneralsDriverThread, "PIGeneralsDriver"); -#endif - // global Dfc Que -//TDynamicDfcQue* gDfcQ; +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 +#ifdef __SMP__ +static TSpinLock PiSpinLock = TSpinLock(TSpinLock::EOrderGenericIrqLow2); +#endif /* * * - * Class DGfcProfilerFactory definition + * Class DGeneralsProfilerFactory definition * * */ @@ -100,11 +89,12 @@ /* * * - * Class DGfcDriver definition + * Class DGeneralsDriver definition * * */ class DPluginDriver; +class DSamplerPowerHandler; class DGeneralsDriver : public DPluginDriver { @@ -112,20 +102,22 @@ public: DGeneralsDriver(); ~DGeneralsDriver(); - + TInt StartSampling(TInt aRate, TInt aInterruptNumber); + TInt StopSampling(); private: - TInt NewStart(TInt aRate); + TInt isExecuted; + TInt NewStart(TInt aRate); + void IncrementSampleNeededState(TInt aId); + void DecrementSampleNeededState(); static void NewDoProfilerProfile(TAny*); static void NewDoDfc(TAny*); // called by each core - static void Sample(TAny*); + static void Sample(TAny* aPtr); TInt GetSampleTime(TUint32* time); //TInt Test(TUint32 testCase); - TInt StartSampling(); - TInt StopSampling(); void InitialiseSamplerList(); @@ -169,7 +161,7 @@ #endif DProfilerGfcSampler<10000> gfcSampler; DProfilerIttSampler<10000> ittSampler; - DProfilerMemSampler<40000> memSampler; + DProfilerMemSampler<10000> memSampler; DProfilerPriSampler<10000> priSampler; #ifdef __SMP__ // DProfilerPriSampler<10000> priSampler2; @@ -183,13 +175,46 @@ static const TInt KSamplerAmount = 8; #endif DProfilerSamplerBase* iSamplers[KSamplerAmount]; + TUint iInterruptCounter[KMaxCpus]; TInt iMaxCpus; TUint32 iStartTime; - -#ifdef SEPARATE_DFC_QUEUE - TDynamicDfcQue* iDfcQ; -#endif + TInt8 postSampleNeeded; + DSamplerPowerHandler* iPowerHandler; + + /* using the HAL machine UID we determine the platform Bridge/Naviengine */ + enum TPlatform + { + /* Bridge Platform STE500*/ + EBridge, + /* Naviengine Platform NE1_TB */ + ENaviengine, + /* Not recognised platform */ + ENotRecognised, + /* Spare */ + ESpare + }; + TPlatform iPlatform; + +public: + TUint8 iStarted; + TUint8 iOff; + TInt iRate; + TInt iIntNo; // Interrupt Number }; +/* + * PowerHandler + */ +class DSamplerPowerHandler : public DPowerHandler + { +public: // from DPowerHandler + void PowerUp(); + void PowerDown(TPowerState); +public: + DSamplerPowerHandler(DGeneralsDriver* aChannel); +public: + DGeneralsDriver* iChannel; + }; + /* * @@ -219,14 +244,21 @@ DGeneralsProfilerFactory::~DGeneralsProfilerFactory() { -// if (gDfcQ) -// { -// gDfcQ->Destroy(); -// } + if (gDfcQ) + { + gDfcQ->Destroy(); + } } TInt DGeneralsProfilerFactory::Install() { + // Allocate a kernel thread to run the DFC + TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDSamplerThreadPriority, KGeneralsDriverThread); + if (r != KErrNone) + { + return r; + } + return(SetName(&KPluginSamplerName)); } @@ -275,6 +307,7 @@ sampleRunning = 0; iSyncOffset = 0; iStartTime = 0; + postSampleNeeded = 0; InitialiseSamplerList(); } @@ -306,6 +339,11 @@ #ifdef __SMP__ // get the number of cpus iMaxCpus = NKern::NumberOfCpus(); + for(TInt nCpu(0); nCpu < iMaxCpus; nCpu++) + { + iInterruptCounter[nCpu] = 0; + } + #else iMaxCpus = 0; #endif @@ -315,14 +353,14 @@ TInt r(iSampleStartTimeProp.Attach(KGppPropertyCat, EGppPropertySyncSampleNumber)); if (r!=KErrNone) { - LOGSTRING2("DGeneralsDriver::InitialiseSamplerList() - error in attaching counter property, error %d", r); + Kern::Printf("DGeneralsDriver::InitialiseSamplerList() - error in attaching counter property, error %d", r); } LOGSTRING("DGeneralsDriver::InitialiseSamplerList() - defining properties"); r = iSampleStartTimeProp.Define(RProperty::EInt, KAllowAllPolicy, KDenyAllPolicy, 0, NULL); if (r!=KErrNone) { - LOGSTRING2("DGeneralsDriver::InitialiseSamplerList() - error in defining counter property, error %d", r); - } + Kern::Printf("DGeneralsDriver::InitialiseSamplerList() - error in defining counter property, error %d", r); + } } @@ -341,7 +379,7 @@ TInt DGeneralsDriver::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer) { TUint8 err(KErrNone); - + LOGSTRING("DGeneralsDriver::DoCreate()"); if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer)) return KErrNotSupported; @@ -361,13 +399,20 @@ //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"))) + { + Kern::Printf("DGeneralsDriver::CurrentThreadHasCapability - denied"); return KErrPermissionDenied; + } if(!Kern::CurrentThreadHasCapability(ECapabilityAllFiles,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) - return KErrPermissionDenied; + { + Kern::Printf("DGeneralsDriver::CurrentThreadHasCapability - denied"); + return KErrPermissionDenied; + } SSecurityInfo secureInfo = clientProcess->iS; if (secureInfo.iSecureId != KProfilerExeSecurUid) { + Kern::Printf("DGeneralsDriver::security - denied"); return KErrPermissionDenied; } } @@ -378,22 +423,20 @@ iTimer.Cancel(); iNewDfc.Cancel(); - Kern::SetThreadPriority(24); + Kern::SetThreadPriority(KGeneralsDriverThreadPriority); -#ifdef SEPARATE_DFC_QUEUE - err = Kern::DynamicDfcQCreate(iDfcQ, KGeneralsDriverThreadPriority, TBuf8<32>( KGeneralsDriverThread )); - if (KErrNone == err) + SetDfcQ(gDfcQ); + iNewDfc.SetDfcQ(iDfcQ); + iMsgQ.Receive(); + + // create the power handler + iPowerHandler = new DSamplerPowerHandler(this); + if (!iPowerHandler) { - SetDfcQ(iDfcQ); - iNewDfc.SetDfcQ(iDfcQ); - iMsgQ.Receive(); - return err; + Kern::Printf("DGeneralsDriver::DoCreate() : new DSamplerPowerHandler(this) failed"); + return KErrNoMemory; } -#else - SetDfcQ(Kern::DfcQue0()); - iNewDfc.SetDfcQ(iDfcQ); - iMsgQ.Receive(); -#endif + iPowerHandler->Add(); return err; } @@ -403,11 +446,6 @@ iTimer.Cancel(); iNewDfc.Cancel(); -#ifdef SEPARATE_DFC_QUEUE - if(iDfcQ) - iDfcQ->Destroy(); -#endif - iSampleStartTimeProp.Close(); Kern::SafeClose((DObject*&)iClient,NULL); } @@ -450,48 +488,39 @@ #ifdef __SMP__ /* - * Bind and enable the sampling interupts associated with each core. + * Bind and enable the sampling interrupts */ 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 ); + TUint32 flags(NKern::EIrqBind_Count); + TInt noofCpu(NKern::NumberOfCpus()); -// 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 ); + //Binding to the interrupt(s) + for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) + { + LOGSTRING3(" > Interrupt::InterruptBind %d + %d - 32", iIntNo, nCpu ); + err = NKern::InterruptBind( (iIntNo + nCpu - 32) , DGeneralsDriver::Sample, this, flags, 0); + if(err < 0) + { + Kern::Printf(" InterruptBind %d + %d - 32 Error = 0x%x", iIntNo, nCpu, err ); + return err; + } + } + + //Enabling Interrupt(s) + for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) + { + LOGSTRING3(" > NKern::InterruptEnable %d + %d - 32", iIntNo, nCpu ); + err = NKern::InterruptEnable(iIntNo + nCpu - 32); + if(err < 0) + { + Kern::Printf(" InterruptEnable %d + %d - 32 ret = 0x%x", iIntNo, nCpu, err ); + return err; + } + + /* For Bridge we enable one single interrupt for CPU 1 */ + if(iPlatform == EBridge) + break; + } #endif @@ -502,6 +531,33 @@ return KErrNone; } +void DGeneralsDriver::IncrementSampleNeededState(TInt aId) + { + LOGSTRING2("DGeneralsDriver::IncrementSampleNeededState() - incrementing sample needed state, caller id: %d", (aId+1)); +#ifdef __SMP__ + TInt intState(0); + intState = __SPIN_LOCK_IRQSAVE(PiSpinLock); +#endif + postSampleNeeded++; +#ifdef __SMP__ + __SPIN_UNLOCK_IRQRESTORE(PiSpinLock, intState); +#endif + } + +void DGeneralsDriver::DecrementSampleNeededState() + { + LOGSTRING("DGeneralsDriver::DecrementSampleNeededState() - decrementing sample needed state"); +#ifdef __SMP__ + TInt intState(0); + intState = __SPIN_LOCK_IRQSAVE(PiSpinLock); +#endif + postSampleNeeded--; +#ifdef __SMP__ + __SPIN_UNLOCK_IRQRESTORE(PiSpinLock, intState); +#endif + } + + /* * This function is run in each interrupt */ @@ -510,83 +566,147 @@ void DGeneralsDriver::NewDoProfilerProfile(TAny* aPtr) { LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - entry"); - + DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; #ifdef __SMP__ TInt currCpu(NKern::CurrentCpu()); #endif - TInt8 postSampleNeeded(0); - DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; + + if(!d.iOff) + { + 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); + + /* + This is the master sampler from the watchdog timer, so + send interrupts to the other CPU(s) + */ + TScheduler *theSched = TScheduler::Ptr(); +// GicDistributor* gicDist = (GicDistributor* )theSched->i_GicDistAddr; + GicDistributor* gicDist = (GicDistributor* )(theSched->iSX.iGicDistAddr); + + // post-sampling for NTimer interrupted CPU + //d.postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); + + if (d.iPlatform == EBridge) + { + /* The Interrupt ID is hardcoded for Bridge to be 108/117, using SPI on ARM GIC + * Programming the GIC Distributor Set-Pending Register to raise an interrupt + * Programming the GIC Distributor Target Register to set an interrupt in CPU 1 + */ + + /* Interrupt Processor Targets Registers (ICDIPTRn) + * target register ICDIPTR number, M, is given by M = N DIV 4 + * so M is 27 for N = 108/117 + * NTimer interrupt is always defaulted to CPU 0 so we have to interrupt CPU 1 + * setting 0bxxxxxx1x CPU interface 1 + */ +// gicDist->iTarget[27] |= 0x00000002; +// gicDist->iTarget[27] &= 0xFE; + gicDist->iTarget[29] |= 0x00000200; + gicDist->iTarget[29] &= 0xFFFFFEFF; - 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); + /* Interrupt Set-Pending Registers (ICDISPRn) + * the corresponding ICDISPR number, M, is given by M = N DIV 32 + * M = 3 for N being 108/117 + * the bit number of the required Set-pending bit in this register is N MOD 32 + * which in this case is 12 + */ +// gicDist->iPendingSet[3] = 1<<((12)); // N = 108 + gicDist->iPendingSet[3] = 1<<((21)); // N = 117 + + arm_dsb(); + + } + else if (d.iPlatform == ENaviengine) //naviengine platform + { + for( TInt nCpu(0); nCpu < NKern::NumberOfCpus(); nCpu++ ) + { + if( nCpu != currCpu ) + { + //Kern::Printf(("DProfile::TimerSampleIsr() > iSoftIrq: to cpu%d, 0x%08X"), nCpu, ( 0x10000 << nCpu ) | (d.iIntNo + nCpu)); + gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (d.iIntNo + nCpu); + } + // post-sampling for CPUs with specifically generated interrupts + //d.postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); + } + arm_dsb(); + + } + else + { + Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - SMP Platform not recognised " ); + } + +#endif + // then sample the rest of non-cpu samplers + for(TInt i(0);iiEnabled) + { + d.iSamplers[i]->Sample(aPtr); + if(d.iSamplers[i]->PostSampleNeeded()) + { + d.IncrementSampleNeededState(i); + } + } + } + +// // check if post sampling is needed for samplers +// for(TInt i(0);iiEnabled) +// { +// if(d.iSamplers[i]->PostSampleNeeded()) +// { +// d.IncrementSampleNeededState(i); +// } +// } +// } + + if(d.postSampleNeeded > 0 && d.doingDfc == 0) + //if(d.postSampleNeeded > 0) + { + LOGSTRING2("DGeneralsDriver::NewDoProfilerProfile - postSampleNeeded count %d ", d.postSampleNeeded ); + d.doingDfc++; + d.iNewDfc.Add(); - // post-sampling for NTimer interrupted CPU - postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); + d.sampleRunning--; - /* - 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++ ) + return; + } + d.sampleRunning--; + } // if (d.iState == ERunning && d.sampleRunning == 0) + else if (d.iState == EStopping && d.sampleRunning == 0) { - if( nCpu != currCpu ) - { - gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (KIntProfilerBase + nCpu); - } - // post-sampling for CPUs with specifically generated interrupts - postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); + // add a dfc for this final time + d.iNewDfc.Add(); + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - sampling added to dfc queue"); } - 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(); - } + // the previous sample has not finished, + Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - Profiler Sampler Error - interrupted before finished sampling!!"); } - - if(postSampleNeeded > 0 && d.doingDfc == 0) - { - d.doingDfc++; - d.iNewDfc.Add(); - - d.sampleRunning--; - return; - } - d.sampleRunning--; + LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - exit"); + } // iOff + else + { + Kern::Printf("DGeneralsDriver::iOff"); } - 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) @@ -596,17 +716,14 @@ #ifdef __SMP__ DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; -// TInt currCpu(NKern::CurrentCpu()); + TInt currCpu(NKern::CurrentCpu()); + ++d.iInterruptCounter[currCpu]; - // sample the current cpu load -// if(d.iSamplers[currCpu]->iEnabled) -// { - d.iSamplers[NKern::CurrentCpu()]->Sample(); -// postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); -// } + d.iSamplers[currCpu]->Sample(aPtr); #endif LOGSTRING("DGeneralsDriver::Sample - exit"); } + /* * This function is run when any of the samplers * requires post sampling @@ -625,7 +742,10 @@ { if(d.iSamplers[i]->PostSampleNeeded()) { - d.iSamplers[i]->PostSample(); + LOGSTRING3("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded count %d", i, d.postSampleNeeded); + d.iSamplers[i]->PostSample(); + d.DecrementSampleNeededState(); + LOGSTRING3("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded count %d", i, d.postSampleNeeded); } } } @@ -634,6 +754,7 @@ else if(d.iState == EStopping) { + LOGSTRING("DGeneralsDriver::NewDoDfc state Stopping()"); // for all enabled samplers, // perform end sampling TBool releaseBuffer(false); @@ -641,18 +762,23 @@ { if(d.iSamplers[i]->iEnabled) { - LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); + LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); + if(d.iSamplers[i]->PostSampleNeeded()) + { + LOGSTRING2("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded still", i); + d.iSamplers[i]->PostSample(); + } // 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"); + LOGSTRING("DGeneralsDriver::NewDoDfc() - stream data pending"); releaseBuffer = true; } else { - LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); + LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); releaseBuffer = true; } } @@ -661,7 +787,7 @@ // At the end, once all the samplers are gone through, the buffer should be released if (true == releaseBuffer) { - LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); + LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); d.iSampleStream.ReleaseIfPending(); } @@ -670,6 +796,7 @@ { // sampling has ended Kern::RequestComplete(d.iClient,d.iEndRequestStatus,KErrNone); + LOGSTRING("DGeneralsDriver::NewDoDfc() - request complete, stopped"); } } } @@ -746,8 +873,10 @@ break; case RPluginSampler::EStartSampling: - LOGSTRING("DGeneralsDriver::HandleMsg - EStartSampling"); - r = StartSampling(); + LOGSTRING("DGeneralsDriver::HandleMsg - EStartSampling"); + iStarted = (TUint8)ETrue; + r=StartSampling(m.Int0(),m.Int1()); + //r = StartSampling(); break; case RPluginSampler::EGetSampleTime: @@ -770,7 +899,7 @@ // Requests are handled here case ~RPluginSampler::EStopAndWaitForEnd: - LOGSTRING("DGeneralsDriver::HandleMsg - EStopAndWaitForEnd"); + LOGSTRING("DGeneralsDriver::HandleMsg - EStopAndWaitForEnd"); iEndRequestStatus = reinterpret_cast(m.Ptr0()); r = StopSampling(); #ifdef __SMP__ @@ -785,7 +914,7 @@ break; default: - LOGSTRING2("DGeneralsDriver::HandleMsg - ERROR, unknown command %d",id); + Kern::Printf("DGeneralsDriver::HandleMsg - ERROR, unknown command %d",id); r = KErrNotSupported; break; } @@ -798,44 +927,30 @@ 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 ); - + /* + * Disable and unbind the sampling interrupts associated with each core. + */ + TInt noofCpu(NKern::NumberOfCpus()); + //Disabling Interrupt(s) + for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) + { + err = NKern::InterruptDisable(iIntNo + nCpu - 32); + if(err < 0) + { + Kern::Printf(" Interrupt Disable iIntNo + %d - 32 ret = %d", nCpu, err ); + } + } + + //UnBinding to the interrupt(s) + for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) + { + LOGSTRING3(" > Interrupt::InterruptUnBind + %d -32 =%d", nCpu, iIntNo + nCpu -32 ); + err = NKern::InterruptUnbind( (iIntNo + nCpu - 32) ); + if(err < 0) + { + Kern::Printf(" InterruptUnBind iIntNo + %d - 32 Error = %d", nCpu, err ); + } + } } #endif @@ -865,12 +980,12 @@ // in that case, the request should be completed already if(iSamplers[i]->EndSampling() == KErrNotReady) { - LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - still data pending"); - releaseBuffer = true; + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - still data pending"); + releaseBuffer = false; } else { - LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - no data pending"); + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - no data pending"); releaseBuffer = true; } } @@ -878,7 +993,7 @@ // 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"); + LOGSTRING("DGeneralsDriver::ProcessStreamReadRequest - all data copied, release the buffer"); iSampleStream.ReleaseIfPending(); } } @@ -903,10 +1018,10 @@ if( samplerIdToActivate == PROFILER_GPP_SAMPLER_ID ) { for(TInt cpu(0);cpuSetEnabledFlag(true); - } + { + LOGSTRING2("DGeneralsDriver::MarkTraceActive - activating CPU %d",cpu); + iSamplers[cpu]->SetEnabledFlag(true); + } return KErrNone; } #endif @@ -919,7 +1034,7 @@ } } - LOGSTRING2("DGeneralsDriver::MarkTraceActive - %d not supported",samplerIdToActivate); + Kern::Printf("DGeneralsDriver::MarkTraceActive - %d not supported",samplerIdToActivate); return KErrNotSupported; } @@ -948,7 +1063,7 @@ } } - LOGSTRING2("DGeneralsDriver::MarkTraceInactive - %d not supported",samplerIdToDisable); + Kern::Printf("DGeneralsDriver::MarkTraceInactive - %d not supported",samplerIdToDisable); return KErrNotSupported; } @@ -1077,7 +1192,7 @@ * only if sampling is not running */ -TInt DGeneralsDriver::StartSampling() +TInt DGeneralsDriver::StartSampling(TInt aRate, TInt aInterruptNumber) { LOGSTRING("DGeneralsDriver::StartSampling"); @@ -1086,6 +1201,7 @@ // reset iSampleStartTimeProp property value iSampleStartTime = NKern::TickCount(); // get the system tick value for sync purposes #ifdef __SMP__ + TInt err; iStartTime = (iSampleStartTime & 0xfffffff0); #endif TInt r(iSampleStartTimeProp.Set(iSampleStartTime)); @@ -1099,15 +1215,55 @@ { // reset with stream option #ifndef __SMP__ - Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, sync offset %d"), 0); + LOGSTRING2(("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); + LOGSTRING2(("DGeneralsDriver::StartSampling - stream reset for generals driver, start time %d"), iStartTime); iSamplers[i]->Reset(&iSampleStream, iStartTime); #endif } } - +#ifdef __SMP__ + iRate = aRate; + iIntNo = aInterruptNumber; + // use HAL to understand the underlying hardware + // not so elegant but used for two SMP pltaforms Bridge and Naviengine + TVariantInfoV01 info; + TPckg infoPckg(info); + err = Kern::HalFunction(EHalGroupVariant, EVariantHalVariantInfo, (TAny*)&infoPckg, NULL); + + if(err != KErrNone) + { + Kern::Printf("Error in reading HAL Entry EVariantHalVariantInfo %r ", err); + } + if (info.iMachineUniqueId.iData[0] == KBridgeMachineUID) + { + iPlatform = EBridge; + LOGSTRING("DGeneralsDriver::StartSampling() - Bridge HW"); + } + else if (info.iMachineUniqueId.iData[0] == KNaviengineMachineUID) + { + iPlatform = ENaviengine; + LOGSTRING("DGeneralsDriver::StartSampling() - NaviEngine HW"); + } + else + { + Kern::Printf("DGeneralsDriver::StartSampling() - Unknown HW, 0x%x", info.iMachineUniqueId.iData[0]); + } + + //users are restricted to use the default Interrupt Number for Bridge + if ((iPlatform == EBridge) && (aInterruptNumber != KValueZero) && (aInterruptNumber != KBridgeProfilerInterruptId) ) + { + Kern::Printf("Invalid Interrupt Number for Bridge used %d interrupt...Please use %d Interrupt Number", iIntNo, KBridgeProfilerInterruptId); + return KErrNotSupported; + } + if (aInterruptNumber == KValueZero) + iIntNo = KDefaultInterruptNumber; + + if (iPlatform == EBridge) + /* By default for Bridge we are using KBridgeProfilerInterruptId */ + iIntNo = KBridgeProfilerInterruptId; +#endif NewStart(gppSampler.GetPeriod()); return KErrNone; } @@ -1124,7 +1280,8 @@ TInt DGeneralsDriver::StopSampling() { - LOGSTRING("DGeneralsDriver::StopSampling"); + LOGSTRING2("DGeneralsDriver::StopSampling - iState %", iState); + TInt noofCpu(NKern::NumberOfCpus()); if(iState == ERunning) { @@ -1132,14 +1289,26 @@ // reset all enabled samplers for(TInt i(0);iiEnabled && iSamplers[i]->iSamplerId == 4) + // do the reset only for memory and itt samplers + if(iSamplers[i]->iEnabled && + (iSamplers[i]->iSamplerId == PROFILER_ITT_SAMPLER_ID || + iSamplers[i]->iSamplerId == PROFILER_MEM_SAMPLER_ID )) { // reset with stream option - LOGTEXT(("DGeneralsDriver::StopSampling - stream reset for samplers")); - iSamplers[i]->Reset(&iSampleStream, 999999); + LOGSTRING(("DGeneralsDriver::StopSampling - stream reset for samplers")); + iSamplers[i]->Reset(&iSampleStream, KStateSamplingEnding); } } + LOGSTRING2("\nDGeneralsDriver::StopSampling - Number of times the Timer counter expired on CPU 0 = %d ", iInterruptCounter[0]); + + for(TInt nCpu(1); nCpu < noofCpu; nCpu++) + { + Kern::Printf( "\n Number of times we interrupted CPU[%d] = %d and Number of Missed CPU interrupts = %d", nCpu, iInterruptCounter[nCpu],(iInterruptCounter[0] - iInterruptCounter[nCpu])); + Kern::Printf( "\n Number of times CPU sampler[0] accessed: %d", gppSampler.GetExportData()->sampleNumber); +#ifdef __SMP__ + Kern::Printf( "\n Number of times CPU sampler[1] accessed: %d", gppSampler2.GetExportData()->sampleNumber); +#endif + } return KErrNone; } @@ -1149,4 +1318,31 @@ } } +DSamplerPowerHandler::DSamplerPowerHandler(DGeneralsDriver* aChannel) + : DPowerHandler(KPluginSamplerName), + iChannel(aChannel) + { + LOGSTRING("DSamplerPowerHandler::DSamplerPowerHandler\n"); + } + +void DSamplerPowerHandler::PowerUp() + { + LOGSTRING("DSamplerPowerHandler::PowerUp()1\n"); + iChannel->iOff = (TUint8)EFalse; + if (iChannel->iStarted) + { + LOGSTRING("DSamplerPowerHandler::PowerUp()2\n"); + iChannel->StartSampling(iChannel->iRate, iChannel->iIntNo); + } + PowerUpDone(); + } + +void DSamplerPowerHandler::PowerDown(TPowerState) + { + LOGSTRING("DSamplerPowerHandler::PowerDown()\n"); + iChannel->iOff = (TUint8)ETrue; + //iChannel->iState = EStopped; + iChannel->StopSampling(); + PowerDownDone(); + }