359 if (clientProcess) |
397 if (clientProcess) |
360 { |
398 { |
361 //Require Power Management and All Files to use this driver |
399 //Require Power Management and All Files to use this driver |
362 // Not ideal, but better than nothing |
400 // Not ideal, but better than nothing |
363 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) |
401 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) |
|
402 { |
|
403 Kern::Printf("DGeneralsDriver::CurrentThreadHasCapability - denied"); |
364 return KErrPermissionDenied; |
404 return KErrPermissionDenied; |
|
405 } |
365 if(!Kern::CurrentThreadHasCapability(ECapabilityAllFiles,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) |
406 if(!Kern::CurrentThreadHasCapability(ECapabilityAllFiles,__PLATSEC_DIAGNOSTIC_STRING("Checked by GeneralsDriver.ldd"))) |
366 return KErrPermissionDenied; |
407 { |
|
408 Kern::Printf("DGeneralsDriver::CurrentThreadHasCapability - denied"); |
|
409 return KErrPermissionDenied; |
|
410 } |
367 |
411 |
368 SSecurityInfo secureInfo = clientProcess->iS; |
412 SSecurityInfo secureInfo = clientProcess->iS; |
369 if (secureInfo.iSecureId != KProfilerExeSecurUid) |
413 if (secureInfo.iSecureId != KProfilerExeSecurUid) |
370 { |
414 { |
|
415 Kern::Printf("DGeneralsDriver::security - denied"); |
371 return KErrPermissionDenied; |
416 return KErrPermissionDenied; |
372 } |
417 } |
373 } |
418 } |
374 |
419 |
375 // initiate sample stream ready for collecting the trace data |
420 // initiate sample stream ready for collecting the trace data |
376 iSampleStream.InsertCurrentClient(iClient); |
421 iSampleStream.InsertCurrentClient(iClient); |
377 |
422 |
378 iTimer.Cancel(); |
423 iTimer.Cancel(); |
379 iNewDfc.Cancel(); |
424 iNewDfc.Cancel(); |
380 |
425 |
381 Kern::SetThreadPriority(24); |
426 Kern::SetThreadPriority(KGeneralsDriverThreadPriority); |
382 |
427 |
383 #ifdef SEPARATE_DFC_QUEUE |
428 SetDfcQ(gDfcQ); |
384 err = Kern::DynamicDfcQCreate(iDfcQ, KGeneralsDriverThreadPriority, TBuf8<32>( KGeneralsDriverThread )); |
429 iNewDfc.SetDfcQ(iDfcQ); |
385 if (KErrNone == err) |
430 iMsgQ.Receive(); |
386 { |
431 |
387 SetDfcQ(iDfcQ); |
432 // create the power handler |
388 iNewDfc.SetDfcQ(iDfcQ); |
433 iPowerHandler = new DSamplerPowerHandler(this); |
389 iMsgQ.Receive(); |
434 if (!iPowerHandler) |
390 return err; |
435 { |
391 } |
436 Kern::Printf("DGeneralsDriver::DoCreate() : new DSamplerPowerHandler(this) failed"); |
392 #else |
437 return KErrNoMemory; |
393 SetDfcQ(Kern::DfcQue0()); |
438 } |
394 iNewDfc.SetDfcQ(iDfcQ); |
439 iPowerHandler->Add(); |
395 iMsgQ.Receive(); |
|
396 #endif |
|
397 return err; |
440 return err; |
398 } |
441 } |
399 |
442 |
400 DGeneralsDriver::~DGeneralsDriver() |
443 DGeneralsDriver::~DGeneralsDriver() |
401 { |
444 { |
402 if (iState!=EStopped) |
445 if (iState!=EStopped) |
403 iTimer.Cancel(); |
446 iTimer.Cancel(); |
404 iNewDfc.Cancel(); |
447 iNewDfc.Cancel(); |
405 |
|
406 #ifdef SEPARATE_DFC_QUEUE |
|
407 if(iDfcQ) |
|
408 iDfcQ->Destroy(); |
|
409 #endif |
|
410 |
448 |
411 iSampleStartTimeProp.Close(); |
449 iSampleStartTimeProp.Close(); |
412 Kern::SafeClose((DObject*&)iClient,NULL); |
450 Kern::SafeClose((DObject*&)iClient,NULL); |
413 } |
451 } |
414 |
452 |
448 // always use this rate |
486 // always use this rate |
449 iPeriod = aDelay; |
487 iPeriod = aDelay; |
450 |
488 |
451 #ifdef __SMP__ |
489 #ifdef __SMP__ |
452 /* |
490 /* |
453 * Bind and enable the sampling interupts associated with each core. |
491 * Bind and enable the sampling interrupts |
454 */ |
492 */ |
455 TInt err(0); |
493 TInt err(0); |
456 |
494 TUint32 flags(NKern::EIrqBind_Count); |
457 TUint32 flags = NKern::EIrqBind_Count; |
495 TInt noofCpu(NKern::NumberOfCpus()); |
458 |
496 |
459 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); |
497 //Binding to the interrupt(s) |
460 err = NKern::InterruptBind( KIntProfilerBase - 32 , DGeneralsDriver::Sample, this, flags, 0); |
498 for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) |
461 if(err < 0) |
499 { |
462 Kern::Printf(" InterruptBind KIntProfilerBase - 32 ret = %d", err ); |
500 LOGSTRING3(" > Interrupt::InterruptBind %d + %d - 32", iIntNo, nCpu ); |
463 |
501 err = NKern::InterruptBind( (iIntNo + nCpu - 32) , DGeneralsDriver::Sample, this, flags, 0); |
464 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); |
502 if(err < 0) |
465 err = NKern::InterruptBind( KIntProfilerBase + 1 - 32 , DGeneralsDriver::Sample, this, flags, 0); |
503 { |
466 if(err < 0) |
504 Kern::Printf(" InterruptBind %d + %d - 32 Error = 0x%x", iIntNo, nCpu, err ); |
467 Kern::Printf(" InterruptBind KIntProfilerBase + 1 - 32 ret = %d", err ); |
505 return err; |
468 |
506 } |
469 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); |
507 } |
470 err = NKern::InterruptBind(KIntProfilerBase + 2 - 32 , DGeneralsDriver::Sample, this, flags, 0); |
508 |
471 if(err < 0) |
509 //Enabling Interrupt(s) |
472 Kern::Printf(" InterruptBind KIntProfilerBase + 2 - 32 ret = %d", err ); |
510 for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) |
473 |
511 { |
474 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); |
512 LOGSTRING3(" > NKern::InterruptEnable %d + %d - 32", iIntNo, nCpu ); |
475 err = NKern::InterruptBind(KIntProfilerBase + 3 - 32 , DGeneralsDriver::Sample, this, flags, 0); |
513 err = NKern::InterruptEnable(iIntNo + nCpu - 32); |
476 if(err < 0) |
514 if(err < 0) |
477 Kern::Printf(" InterruptBind KIntProfilerBase + 3 - 32 ret = %d", err ); |
515 { |
478 |
516 Kern::Printf(" InterruptEnable %d + %d - 32 ret = 0x%x", iIntNo, nCpu, err ); |
479 |
517 return err; |
480 err = NKern::InterruptEnable(KIntProfilerBase - 32); |
518 } |
481 if(err < 0) |
|
482 Kern::Printf(" InterruptEnable KIntProfilerBase - 32 ret = %d", err ); |
|
483 |
|
484 err = NKern::InterruptEnable(KIntProfilerBase + 1 - 32); |
|
485 if(err < 0) |
|
486 Kern::Printf(" InterruptEnable KIntProfilerBase + 1 - 32 ret = %d", err ); |
|
487 |
|
488 err = NKern::InterruptEnable(KIntProfilerBase + 2 - 32); |
|
489 if(err < 0) |
|
490 Kern::Printf(" InterruptEnable KIntProfilerBase + 2 - 32 ret = %d", err ); |
|
491 |
|
492 err = NKern::InterruptEnable(KIntProfilerBase + 3 - 32); |
|
493 if(err < 0) |
|
494 Kern::Printf(" InterruptEnable KIntProfilerBase + 3 - 32 ret = %d", err ); |
|
495 |
519 |
|
520 /* For Bridge we enable one single interrupt for CPU 1 */ |
|
521 if(iPlatform == EBridge) |
|
522 break; |
|
523 } |
|
524 |
496 #endif |
525 #endif |
497 |
526 |
498 iTimer.OneShot(aDelay); |
527 iTimer.OneShot(aDelay); |
499 |
528 |
500 iState = ERunning; |
529 iState = ERunning; |
501 |
530 |
502 return KErrNone; |
531 return KErrNone; |
503 } |
532 } |
|
533 |
|
534 void DGeneralsDriver::IncrementSampleNeededState(TInt aId) |
|
535 { |
|
536 LOGSTRING2("DGeneralsDriver::IncrementSampleNeededState() - incrementing sample needed state, caller id: %d", (aId+1)); |
|
537 #ifdef __SMP__ |
|
538 TInt intState(0); |
|
539 intState = __SPIN_LOCK_IRQSAVE(PiSpinLock); |
|
540 #endif |
|
541 postSampleNeeded++; |
|
542 #ifdef __SMP__ |
|
543 __SPIN_UNLOCK_IRQRESTORE(PiSpinLock, intState); |
|
544 #endif |
|
545 } |
|
546 |
|
547 void DGeneralsDriver::DecrementSampleNeededState() |
|
548 { |
|
549 LOGSTRING("DGeneralsDriver::DecrementSampleNeededState() - decrementing sample needed state"); |
|
550 #ifdef __SMP__ |
|
551 TInt intState(0); |
|
552 intState = __SPIN_LOCK_IRQSAVE(PiSpinLock); |
|
553 #endif |
|
554 postSampleNeeded--; |
|
555 #ifdef __SMP__ |
|
556 __SPIN_UNLOCK_IRQRESTORE(PiSpinLock, intState); |
|
557 #endif |
|
558 } |
|
559 |
504 |
560 |
505 /* |
561 /* |
506 * This function is run in each interrupt |
562 * This function is run in each interrupt |
507 */ |
563 */ |
508 // EKA-2 implementation of the sampler method |
564 // EKA-2 implementation of the sampler method |
509 |
565 |
510 void DGeneralsDriver::NewDoProfilerProfile(TAny* aPtr) |
566 void DGeneralsDriver::NewDoProfilerProfile(TAny* aPtr) |
511 { |
567 { |
512 LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - entry"); |
568 LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - entry"); |
513 |
569 DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; |
514 #ifdef __SMP__ |
570 #ifdef __SMP__ |
515 TInt currCpu(NKern::CurrentCpu()); |
571 TInt currCpu(NKern::CurrentCpu()); |
516 #endif |
572 #endif |
517 TInt8 postSampleNeeded(0); |
573 |
|
574 if(!d.iOff) |
|
575 { |
|
576 if (d.iState == ERunning && d.sampleRunning == 0) |
|
577 { |
|
578 // start timer again |
|
579 d.iTimer.Again(d.iPeriod); |
|
580 d.sampleRunning++; |
|
581 |
|
582 #ifdef __SMP__ |
|
583 // print out the sample tick |
|
584 if(d.gppSampler.GetExportData()->sampleNumber% 1000 == 0) |
|
585 { |
|
586 Kern::Printf(("PIPROF SAMPLE TICK, #%d"), d.gppSampler.GetExportData()->sampleNumber); |
|
587 } |
|
588 |
|
589 // call the actual CPU sampling function for CPU 0 (in NaviEngine), later may be on any of the CPUs |
|
590 Sample(aPtr); |
|
591 |
|
592 /* |
|
593 This is the master sampler from the watchdog timer, so |
|
594 send interrupts to the other CPU(s) |
|
595 */ |
|
596 TScheduler *theSched = TScheduler::Ptr(); |
|
597 // GicDistributor* gicDist = (GicDistributor* )theSched->i_GicDistAddr; |
|
598 GicDistributor* gicDist = (GicDistributor* )(theSched->iSX.iGicDistAddr); |
|
599 |
|
600 // post-sampling for NTimer interrupted CPU |
|
601 //d.postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); |
|
602 |
|
603 if (d.iPlatform == EBridge) |
|
604 { |
|
605 /* The Interrupt ID is hardcoded for Bridge to be 108/117, using SPI on ARM GIC |
|
606 * Programming the GIC Distributor Set-Pending Register to raise an interrupt |
|
607 * Programming the GIC Distributor Target Register to set an interrupt in CPU 1 |
|
608 */ |
|
609 |
|
610 /* Interrupt Processor Targets Registers (ICDIPTRn) |
|
611 * target register ICDIPTR number, M, is given by M = N DIV 4 |
|
612 * so M is 27 for N = 108/117 |
|
613 * NTimer interrupt is always defaulted to CPU 0 so we have to interrupt CPU 1 |
|
614 * setting 0bxxxxxx1x CPU interface 1 |
|
615 */ |
|
616 // gicDist->iTarget[27] |= 0x00000002; |
|
617 // gicDist->iTarget[27] &= 0xFE; |
|
618 gicDist->iTarget[29] |= 0x00000200; |
|
619 gicDist->iTarget[29] &= 0xFFFFFEFF; |
|
620 |
|
621 /* Interrupt Set-Pending Registers (ICDISPRn) |
|
622 * the corresponding ICDISPR number, M, is given by M = N DIV 32 |
|
623 * M = 3 for N being 108/117 |
|
624 * the bit number of the required Set-pending bit in this register is N MOD 32 |
|
625 * which in this case is 12 |
|
626 */ |
|
627 // gicDist->iPendingSet[3] = 1<<((12)); // N = 108 |
|
628 gicDist->iPendingSet[3] = 1<<((21)); // N = 117 |
|
629 |
|
630 arm_dsb(); |
|
631 |
|
632 } |
|
633 else if (d.iPlatform == ENaviengine) //naviengine platform |
|
634 { |
|
635 for( TInt nCpu(0); nCpu < NKern::NumberOfCpus(); nCpu++ ) |
|
636 { |
|
637 if( nCpu != currCpu ) |
|
638 { |
|
639 //Kern::Printf(("DProfile::TimerSampleIsr() > iSoftIrq: to cpu%d, 0x%08X"), nCpu, ( 0x10000 << nCpu ) | (d.iIntNo + nCpu)); |
|
640 gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (d.iIntNo + nCpu); |
|
641 } |
|
642 // post-sampling for CPUs with specifically generated interrupts |
|
643 //d.postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); |
|
644 } |
|
645 arm_dsb(); |
|
646 |
|
647 } |
|
648 else |
|
649 { |
|
650 Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - SMP Platform not recognised " ); |
|
651 } |
|
652 |
|
653 #endif |
|
654 // then sample the rest of non-cpu samplers |
|
655 for(TInt i(0);i<KSamplerAmount;i++) |
|
656 { |
|
657 if(d.iSamplers[i]->iEnabled) |
|
658 { |
|
659 d.iSamplers[i]->Sample(aPtr); |
|
660 if(d.iSamplers[i]->PostSampleNeeded()) |
|
661 { |
|
662 d.IncrementSampleNeededState(i); |
|
663 } |
|
664 } |
|
665 } |
|
666 |
|
667 // // check if post sampling is needed for samplers |
|
668 // for(TInt i(0);i<KSamplerAmount;i++) |
|
669 // { |
|
670 // if(d.iSamplers[i]->iEnabled) |
|
671 // { |
|
672 // if(d.iSamplers[i]->PostSampleNeeded()) |
|
673 // { |
|
674 // d.IncrementSampleNeededState(i); |
|
675 // } |
|
676 // } |
|
677 // } |
|
678 |
|
679 if(d.postSampleNeeded > 0 && d.doingDfc == 0) |
|
680 //if(d.postSampleNeeded > 0) |
|
681 { |
|
682 LOGSTRING2("DGeneralsDriver::NewDoProfilerProfile - postSampleNeeded count %d ", d.postSampleNeeded ); |
|
683 d.doingDfc++; |
|
684 d.iNewDfc.Add(); |
|
685 |
|
686 d.sampleRunning--; |
|
687 |
|
688 return; |
|
689 } |
|
690 d.sampleRunning--; |
|
691 } // if (d.iState == ERunning && d.sampleRunning == 0) |
|
692 else if (d.iState == EStopping && d.sampleRunning == 0) |
|
693 { |
|
694 // add a dfc for this final time |
|
695 d.iNewDfc.Add(); |
|
696 LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - sampling added to dfc queue"); |
|
697 } |
|
698 else |
|
699 { |
|
700 // the previous sample has not finished, |
|
701 Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - Profiler Sampler Error - interrupted before finished sampling!!"); |
|
702 } |
|
703 LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - exit"); |
|
704 } // iOff |
|
705 else |
|
706 { |
|
707 Kern::Printf("DGeneralsDriver::iOff"); |
|
708 } |
|
709 } |
|
710 |
|
711 |
|
712 void DGeneralsDriver::Sample(TAny* aPtr) |
|
713 { |
|
714 LOGSTRING("DGeneralsDriver::Sample - entry"); |
|
715 |
|
716 #ifdef __SMP__ |
518 DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; |
717 DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; |
519 |
718 |
520 if (d.iState == ERunning && d.sampleRunning == 0) |
719 TInt currCpu(NKern::CurrentCpu()); |
521 { |
720 ++d.iInterruptCounter[currCpu]; |
522 // start timer again |
721 |
523 d.iTimer.Again(d.iPeriod); |
722 d.iSamplers[currCpu]->Sample(aPtr); |
524 d.sampleRunning++; |
|
525 |
|
526 #ifdef __SMP__ |
|
527 // print out the sample tick |
|
528 if(d.gppSampler.GetExportData()->sampleNumber% 1000 == 0) |
|
529 { |
|
530 Kern::Printf(("PIPROF SAMPLE TICK, #%d"), d.gppSampler.GetExportData()->sampleNumber); |
|
531 } |
|
532 // call the actual CPU sampling function for CPU 0 (in NaviEngine), later may be on any of the CPUs |
|
533 Sample(aPtr); |
|
534 |
|
535 // post-sampling for NTimer interrupted CPU |
|
536 postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); |
|
537 |
|
538 /* |
|
539 This is the master sampler from the watchdog timer, so |
|
540 send interrupts to the other CPUs |
|
541 */ |
|
542 TScheduler *theSched = TScheduler::Ptr(); |
|
543 GicDistributor* gicDist = (GicDistributor* )theSched->i_GicDistAddr; |
|
544 |
|
545 for( TInt nCpu(0); nCpu < d.iMaxCpus; nCpu++ ) |
|
546 { |
|
547 if( nCpu != currCpu ) |
|
548 { |
|
549 gicDist->iSoftIrq = ( 0x10000 << nCpu ) | (KIntProfilerBase + nCpu); |
|
550 } |
|
551 // post-sampling for CPUs with specifically generated interrupts |
|
552 postSampleNeeded += d.iSamplers[nCpu]->PostSampleNeeded(); |
|
553 } |
|
554 arm_dsb(); |
|
555 #endif |
|
556 // then sample the rest of non-cpu samplers |
|
557 for(TInt i(d.iMaxCpus);i<KSamplerAmount;i++) |
|
558 { |
|
559 if(d.iSamplers[i]->iEnabled) |
|
560 { |
|
561 d.iSamplers[i]->Sample(); |
|
562 postSampleNeeded += d.iSamplers[i]->PostSampleNeeded(); |
|
563 } |
|
564 } |
|
565 |
|
566 if(postSampleNeeded > 0 && d.doingDfc == 0) |
|
567 { |
|
568 d.doingDfc++; |
|
569 d.iNewDfc.Add(); |
|
570 |
|
571 d.sampleRunning--; |
|
572 return; |
|
573 } |
|
574 d.sampleRunning--; |
|
575 } |
|
576 else if (d.iState == EStopping && d.sampleRunning == 0) |
|
577 { |
|
578 // add a dfc for this final time |
|
579 d.iNewDfc.Add(); |
|
580 Kern::Printf("DGeneralsDriver::Sample - sampling added to dfc queue"); |
|
581 } |
|
582 else |
|
583 { |
|
584 // the previous sample has not finished, |
|
585 Kern::Printf("DGeneralsDriver::NewDoProfilerProfile - Profiler Sampler Error - interrupted before finished sampling!!"); |
|
586 } |
|
587 LOGSTRING("DGeneralsDriver::NewDoProfilerProfile - exit"); |
|
588 } |
|
589 |
|
590 |
|
591 |
|
592 void DGeneralsDriver::Sample(TAny* aPtr) |
|
593 { |
|
594 LOGSTRING("DGeneralsDriver::Sample - entry"); |
|
595 |
|
596 #ifdef __SMP__ |
|
597 DGeneralsDriver& d=*(DGeneralsDriver*)aPtr; |
|
598 |
|
599 // TInt currCpu(NKern::CurrentCpu()); |
|
600 |
|
601 // sample the current cpu load |
|
602 // if(d.iSamplers[currCpu]->iEnabled) |
|
603 // { |
|
604 d.iSamplers[NKern::CurrentCpu()]->Sample(); |
|
605 // postSampleNeeded += d.iSamplers[currCpu]->PostSampleNeeded(); |
|
606 // } |
|
607 #endif |
723 #endif |
608 LOGSTRING("DGeneralsDriver::Sample - exit"); |
724 LOGSTRING("DGeneralsDriver::Sample - exit"); |
609 } |
725 } |
|
726 |
610 /* |
727 /* |
611 * This function is run when any of the samplers |
728 * This function is run when any of the samplers |
612 * requires post sampling |
729 * requires post sampling |
613 */ |
730 */ |
614 void DGeneralsDriver::NewDoDfc(TAny* pointer) |
731 void DGeneralsDriver::NewDoDfc(TAny* pointer) |
623 { |
740 { |
624 if(d.iSamplers[i]->iEnabled) |
741 if(d.iSamplers[i]->iEnabled) |
625 { |
742 { |
626 if(d.iSamplers[i]->PostSampleNeeded()) |
743 if(d.iSamplers[i]->PostSampleNeeded()) |
627 { |
744 { |
628 d.iSamplers[i]->PostSample(); |
745 LOGSTRING3("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded count %d", i, d.postSampleNeeded); |
|
746 d.iSamplers[i]->PostSample(); |
|
747 d.DecrementSampleNeededState(); |
|
748 LOGSTRING3("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded count %d", i, d.postSampleNeeded); |
629 } |
749 } |
630 } |
750 } |
631 } |
751 } |
632 d.doingDfc--; |
752 d.doingDfc--; |
633 } |
753 } |
634 |
754 |
635 else if(d.iState == EStopping) |
755 else if(d.iState == EStopping) |
636 { |
756 { |
|
757 LOGSTRING("DGeneralsDriver::NewDoDfc state Stopping()"); |
637 // for all enabled samplers, |
758 // for all enabled samplers, |
638 // perform end sampling |
759 // perform end sampling |
639 TBool releaseBuffer(false); |
760 TBool releaseBuffer(false); |
640 for(TInt i(0);i<KSamplerAmount;i++) |
761 for(TInt i(0);i<KSamplerAmount;i++) |
641 { |
762 { |
642 if(d.iSamplers[i]->iEnabled) |
763 if(d.iSamplers[i]->iEnabled) |
643 { |
764 { |
644 LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); |
765 LOGSTRING("DGeneralsDriver::NewDoDfc() - ending"); |
|
766 if(d.iSamplers[i]->PostSampleNeeded()) |
|
767 { |
|
768 LOGSTRING2("DGeneralsDriver::NewDoDfc iSamplers[%d] PostSampleNeeded still", i); |
|
769 d.iSamplers[i]->PostSample(); |
|
770 } |
645 // perform end sampling for all samplers |
771 // perform end sampling for all samplers |
646 // stream mode samplers may be pending, if they |
772 // stream mode samplers may be pending, if they |
647 // are still waiting for another client buffer |
773 // are still waiting for another client buffer |
648 if(d.iSamplers[i]->EndSampling() == KErrNotReady) |
774 if(d.iSamplers[i]->EndSampling() == KErrNotReady) |
649 { |
775 { |
650 LOGSTRING("DGeneralsDriver::NewDoDfc() - stream data pending"); |
776 LOGSTRING("DGeneralsDriver::NewDoDfc() - stream data pending"); |
651 releaseBuffer = true; |
777 releaseBuffer = true; |
652 } |
778 } |
653 else |
779 else |
654 { |
780 { |
655 LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); |
781 LOGSTRING("DGeneralsDriver::NewDoDfc() - no data pending"); |
656 releaseBuffer = true; |
782 releaseBuffer = true; |
657 } |
783 } |
658 } |
784 } |
659 } |
785 } |
660 |
786 |
661 // At the end, once all the samplers are gone through, the buffer should be released |
787 // At the end, once all the samplers are gone through, the buffer should be released |
662 if (true == releaseBuffer) |
788 if (true == releaseBuffer) |
663 { |
789 { |
664 LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); |
790 LOGSTRING("DGeneralsDriver::NewDoDfc() - release the buffer"); |
665 d.iSampleStream.ReleaseIfPending(); |
791 d.iSampleStream.ReleaseIfPending(); |
666 } |
792 } |
667 |
793 |
668 d.iState = EStopped; |
794 d.iState = EStopped; |
669 if(d.iEndRequestStatus != 0 && d.iClient != 0) |
795 if(d.iEndRequestStatus != 0 && d.iClient != 0) |
670 { |
796 { |
671 // sampling has ended |
797 // sampling has ended |
672 Kern::RequestComplete(d.iClient,d.iEndRequestStatus,KErrNone); |
798 Kern::RequestComplete(d.iClient,d.iEndRequestStatus,KErrNone); |
|
799 LOGSTRING("DGeneralsDriver::NewDoDfc() - request complete, stopped"); |
673 } |
800 } |
674 } |
801 } |
675 } |
802 } |
676 |
803 |
677 |
804 |
796 |
925 |
797 #ifdef __SMP__ |
926 #ifdef __SMP__ |
798 inline void DGeneralsDriver::UnbindInterrupts() |
927 inline void DGeneralsDriver::UnbindInterrupts() |
799 { |
928 { |
800 TInt err(0); |
929 TInt err(0); |
801 |
930 /* |
802 // disable interrupts when sampling stops, enabled again on start |
931 * Disable and unbind the sampling interrupts associated with each core. |
803 err = NKern::InterruptDisable(KIntProfilerBase - 32); |
932 */ |
804 if(err < 0) |
933 TInt noofCpu(NKern::NumberOfCpus()); |
805 Kern::Printf(" InterruptDisable KIntProfilerBase - 32 ret = %d", err ); |
934 //Disabling Interrupt(s) |
806 |
935 for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) |
807 err = NKern::InterruptDisable(KIntProfilerBase + 1 - 32); |
936 { |
808 if(err < 0) |
937 err = NKern::InterruptDisable(iIntNo + nCpu - 32); |
809 Kern::Printf(" InterruptDisable KIntProfilerBase + 1 - 32 ret = %d", err ); |
938 if(err < 0) |
810 |
939 { |
811 err = NKern::InterruptDisable(KIntProfilerBase + 2 - 32); |
940 Kern::Printf(" Interrupt Disable iIntNo + %d - 32 ret = %d", nCpu, err ); |
812 if(err < 0) |
941 } |
813 Kern::Printf(" InterruptDisable KIntProfilerBase + 2 - 32 ret = %d", err ); |
942 } |
814 |
943 |
815 err = NKern::InterruptDisable(KIntProfilerBase + 3 - 32); |
944 //UnBinding to the interrupt(s) |
816 if(err < 0) |
945 for( TInt nCpu(0); nCpu < noofCpu; nCpu++ ) |
817 Kern::Printf(" InterruptDisable KIntProfilerBase + 3 - 32 ret = %d", err ); |
946 { |
818 |
947 LOGSTRING3(" > Interrupt::InterruptUnBind + %d -32 =%d", nCpu, iIntNo + nCpu -32 ); |
819 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase - 32=%d", KIntProfilerBase -32 ); |
948 err = NKern::InterruptUnbind( (iIntNo + nCpu - 32) ); |
820 err = NKern::InterruptUnbind( KIntProfilerBase - 32); |
949 if(err < 0) |
821 if(err < 0) |
950 { |
822 Kern::Printf(" InterruptUnbind KIntProfilerBase - 32 ret = %d", err ); |
951 Kern::Printf(" InterruptUnBind iIntNo + %d - 32 Error = %d", nCpu, err ); |
823 |
952 } |
824 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 1 - 32=%d", KIntProfilerBase + 1-32 ); |
953 } |
825 err = NKern::InterruptUnbind( KIntProfilerBase + 1 - 32); |
|
826 if(err < 0) |
|
827 Kern::Printf(" InterruptUnbind KIntProfilerBase + 1 - 32 ret = %d", err ); |
|
828 |
|
829 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 2 - 32=%d", KIntProfilerBase + 2 - 32 ); |
|
830 err = NKern::InterruptUnbind(KIntProfilerBase + 2 - 32); |
|
831 if(err < 0) |
|
832 Kern::Printf(" InterruptUnbind KIntProfilerBase + 2 - 32 ret = %d", err ); |
|
833 |
|
834 // Kern::Printf(" > Interrupt::InterruptBind KIntProfilerBase + 3 - 32=%d", KIntProfilerBase + 3 - 32 ); |
|
835 err = NKern::InterruptUnbind(KIntProfilerBase + 3 - 32); |
|
836 if(err < 0) |
|
837 Kern::Printf(" InterruptUnbind KIntProfilerBase + 3 - 32 ret = %d", err ); |
|
838 |
|
839 } |
954 } |
840 #endif |
955 #endif |
841 |
956 |
842 inline TInt DGeneralsDriver::ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus) |
957 inline TInt DGeneralsDriver::ProcessStreamReadRequest(TBapBuf* aBuf,TRequestStatus* aStatus) |
843 { |
958 { |
1097 { |
1213 { |
1098 if(iSamplers[i]->iEnabled) |
1214 if(iSamplers[i]->iEnabled) |
1099 { |
1215 { |
1100 // reset with stream option |
1216 // reset with stream option |
1101 #ifndef __SMP__ |
1217 #ifndef __SMP__ |
1102 Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, sync offset %d"), 0); |
1218 LOGSTRING2(("DGeneralsDriver::StartSampling - stream reset for generals driver, sync offset %d"), 0); |
1103 iSamplers[i]->Reset(&iSampleStream, 0); |
1219 iSamplers[i]->Reset(&iSampleStream, 0); |
1104 #else |
1220 #else |
1105 Kern::Printf(("DGeneralsDriver::StartSampling - stream reset for generals driver, start time %d"), iStartTime); |
1221 LOGSTRING2(("DGeneralsDriver::StartSampling - stream reset for generals driver, start time %d"), iStartTime); |
1106 iSamplers[i]->Reset(&iSampleStream, iStartTime); |
1222 iSamplers[i]->Reset(&iSampleStream, iStartTime); |
1107 #endif |
1223 #endif |
1108 } |
1224 } |
1109 } |
1225 } |
1110 |
1226 #ifdef __SMP__ |
|
1227 iRate = aRate; |
|
1228 iIntNo = aInterruptNumber; |
|
1229 // use HAL to understand the underlying hardware |
|
1230 // not so elegant but used for two SMP pltaforms Bridge and Naviengine |
|
1231 TVariantInfoV01 info; |
|
1232 TPckg<TVariantInfoV01> infoPckg(info); |
|
1233 err = Kern::HalFunction(EHalGroupVariant, EVariantHalVariantInfo, (TAny*)&infoPckg, NULL); |
|
1234 |
|
1235 if(err != KErrNone) |
|
1236 { |
|
1237 Kern::Printf("Error in reading HAL Entry EVariantHalVariantInfo %r ", err); |
|
1238 } |
|
1239 if (info.iMachineUniqueId.iData[0] == KBridgeMachineUID) |
|
1240 { |
|
1241 iPlatform = EBridge; |
|
1242 LOGSTRING("DGeneralsDriver::StartSampling() - Bridge HW"); |
|
1243 } |
|
1244 else if (info.iMachineUniqueId.iData[0] == KNaviengineMachineUID) |
|
1245 { |
|
1246 iPlatform = ENaviengine; |
|
1247 LOGSTRING("DGeneralsDriver::StartSampling() - NaviEngine HW"); |
|
1248 } |
|
1249 else |
|
1250 { |
|
1251 Kern::Printf("DGeneralsDriver::StartSampling() - Unknown HW, 0x%x", info.iMachineUniqueId.iData[0]); |
|
1252 } |
|
1253 |
|
1254 //users are restricted to use the default Interrupt Number for Bridge |
|
1255 if ((iPlatform == EBridge) && (aInterruptNumber != KValueZero) && (aInterruptNumber != KBridgeProfilerInterruptId) ) |
|
1256 { |
|
1257 Kern::Printf("Invalid Interrupt Number for Bridge used %d interrupt...Please use %d Interrupt Number", iIntNo, KBridgeProfilerInterruptId); |
|
1258 return KErrNotSupported; |
|
1259 } |
|
1260 if (aInterruptNumber == KValueZero) |
|
1261 iIntNo = KDefaultInterruptNumber; |
|
1262 |
|
1263 if (iPlatform == EBridge) |
|
1264 /* By default for Bridge we are using KBridgeProfilerInterruptId */ |
|
1265 iIntNo = KBridgeProfilerInterruptId; |
|
1266 #endif |
1111 NewStart(gppSampler.GetPeriod()); |
1267 NewStart(gppSampler.GetPeriod()); |
1112 return KErrNone; |
1268 return KErrNone; |
1113 } |
1269 } |
1114 else |
1270 else |
1115 { |
1271 { |
1122 * only if sampling is not running |
1278 * only if sampling is not running |
1123 */ |
1279 */ |
1124 |
1280 |
1125 TInt DGeneralsDriver::StopSampling() |
1281 TInt DGeneralsDriver::StopSampling() |
1126 { |
1282 { |
1127 LOGSTRING("DGeneralsDriver::StopSampling"); |
1283 LOGSTRING2("DGeneralsDriver::StopSampling - iState %", iState); |
|
1284 TInt noofCpu(NKern::NumberOfCpus()); |
1128 |
1285 |
1129 if(iState == ERunning) |
1286 if(iState == ERunning) |
1130 { |
1287 { |
1131 this->iState = EStopping; |
1288 this->iState = EStopping; |
1132 // reset all enabled samplers |
1289 // reset all enabled samplers |
1133 for(TInt i(0);i<KSamplerAmount;i++) |
1290 for(TInt i(0);i<KSamplerAmount;i++) |
1134 { |
1291 { |
1135 // do the reset only for memory sampler |
1292 // do the reset only for memory and itt samplers |
1136 if(iSamplers[i]->iEnabled && iSamplers[i]->iSamplerId == 4) |
1293 if(iSamplers[i]->iEnabled && |
|
1294 (iSamplers[i]->iSamplerId == PROFILER_ITT_SAMPLER_ID || |
|
1295 iSamplers[i]->iSamplerId == PROFILER_MEM_SAMPLER_ID )) |
1137 { |
1296 { |
1138 // reset with stream option |
1297 // reset with stream option |
1139 LOGTEXT(("DGeneralsDriver::StopSampling - stream reset for samplers")); |
1298 LOGSTRING(("DGeneralsDriver::StopSampling - stream reset for samplers")); |
1140 iSamplers[i]->Reset(&iSampleStream, 999999); |
1299 iSamplers[i]->Reset(&iSampleStream, KStateSamplingEnding); |
1141 } |
1300 } |
1142 } |
1301 } |
|
1302 LOGSTRING2("\nDGeneralsDriver::StopSampling - Number of times the Timer counter expired on CPU 0 = %d ", iInterruptCounter[0]); |
|
1303 |
|
1304 for(TInt nCpu(1); nCpu < noofCpu; nCpu++) |
|
1305 { |
|
1306 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])); |
|
1307 Kern::Printf( "\n Number of times CPU sampler[0] accessed: %d", gppSampler.GetExportData()->sampleNumber); |
|
1308 #ifdef __SMP__ |
|
1309 Kern::Printf( "\n Number of times CPU sampler[1] accessed: %d", gppSampler2.GetExportData()->sampleNumber); |
|
1310 #endif |
|
1311 } |
1143 |
1312 |
1144 return KErrNone; |
1313 return KErrNone; |
1145 } |
1314 } |
1146 else |
1315 else |
1147 { |
1316 { |
1148 return KErrGeneral; |
1317 return KErrGeneral; |
1149 } |
1318 } |
1150 } |
1319 } |
1151 |
1320 |
1152 |
1321 DSamplerPowerHandler::DSamplerPowerHandler(DGeneralsDriver* aChannel) |
|
1322 : DPowerHandler(KPluginSamplerName), |
|
1323 iChannel(aChannel) |
|
1324 { |
|
1325 LOGSTRING("DSamplerPowerHandler::DSamplerPowerHandler\n"); |
|
1326 } |
|
1327 |
|
1328 void DSamplerPowerHandler::PowerUp() |
|
1329 { |
|
1330 LOGSTRING("DSamplerPowerHandler::PowerUp()1\n"); |
|
1331 iChannel->iOff = (TUint8)EFalse; |
|
1332 if (iChannel->iStarted) |
|
1333 { |
|
1334 LOGSTRING("DSamplerPowerHandler::PowerUp()2\n"); |
|
1335 iChannel->StartSampling(iChannel->iRate, iChannel->iIntNo); |
|
1336 } |
|
1337 PowerUpDone(); |
|
1338 } |
|
1339 |
|
1340 void DSamplerPowerHandler::PowerDown(TPowerState) |
|
1341 { |
|
1342 LOGSTRING("DSamplerPowerHandler::PowerDown()\n"); |
|
1343 iChannel->iOff = (TUint8)ETrue; |
|
1344 //iChannel->iState = EStopped; |
|
1345 iChannel->StopSampling(); |
|
1346 PowerDownDone(); |
|
1347 } |
|
1348 |