72 iIsaOsTaskRunning.Close(); |
91 iIsaOsTaskRunning.Close(); |
73 } |
92 } |
74 |
93 |
75 void DGppSamplerImpl::Reset() |
94 void DGppSamplerImpl::Reset() |
76 { |
95 { |
77 LOGTEXT("GppSamplerImpl::Reset"); |
96 LOGSTRING("GppSamplerImpl::Reset() - entry"); |
78 iLastPc = 0; |
97 iLastPc = 0; |
79 iLastThread = 0xfffffffe; |
98 iLastThread = 0xfffffffe; |
80 iRepeat = 0; |
99 iRepeat = 0; |
81 iIsaStatus = 0; |
100 iIsaStatus = 0; |
82 iIsaStart = 0; |
101 iIsaStart = 0; |
83 iIsaEnd = 0; |
102 iIsaEnd = 0; |
84 // isaOsTaskRunningAddr = 0; |
103 // isaOsTaskRunningAddr = 0; |
|
104 iPrevTS = NKern::TickCount(); // get the system tick value for sync purposes |
85 |
105 |
86 // in SMP start time common with all CPUs, provided by DGeneralsDriver class |
106 // in SMP start time common with all CPUs, provided by DGeneralsDriver class |
87 #ifndef __SMP__ |
107 #ifndef __SMP__ |
88 iStartTime = ( NKern::TickCount() & 0xfffffffc ); |
108 iStartTime = ( iPrevTS & 0xfffffffc ); |
89 #endif |
109 #else |
90 |
110 iStartTime = ( iPrevTS & 0xfffffff0 ); |
91 TPropertyStatus status; |
111 #endif |
92 TInt osAddr = 0; |
112 |
93 |
113 TInt osAddr(0); |
94 LOGTEXT("GppSamplerImpl::Reset - getting status"); |
114 |
95 |
115 LOGSTRING("GppSamplerImpl::Reset - getting status"); |
96 // get status of ISA plug-in |
|
97 if(iIsaPluginStatus.GetStatus(status)) |
|
98 { |
|
99 iIsaPluginStatus.Get(iIsaStatus); |
|
100 LOGSTRING2("GppSamplerImpl::Reset - ISA plug-in status %d", iIsaStatus); |
|
101 } |
|
102 |
116 |
103 if(iIsaStatus > 0) |
117 if(iIsaStatus > 0) |
104 { |
118 { |
105 LOGTEXT("GppSamplerImpl::Reset - get isa start address"); |
119 LOGSTRING("GppSamplerImpl::Reset - get isa start address"); |
106 iIsaStartAddr.Get(iIsaStart); |
120 iIsaStartAddr.Get(iIsaStart); |
107 LOGTEXT("GppSamplerImpl::Reset - get isa end address"); |
121 LOGSTRING("GppSamplerImpl::Reset - get isa end address"); |
108 iIsaEndAddr.Get(iIsaEnd); |
122 iIsaEndAddr.Get(iIsaEnd); |
109 LOGTEXT("GppSamplerImpl::Reset - get isa os_task_running address"); |
123 LOGSTRING("GppSamplerImpl::Reset - get isa os_task_running address"); |
110 iIsaOsTaskRunning.Get(osAddr); |
124 iIsaOsTaskRunning.Get(osAddr); |
111 isaOsTaskRunningAddr = reinterpret_cast<TInt*>(osAddr); |
125 isaOsTaskRunningAddr = reinterpret_cast<TInt*>(osAddr); |
112 LOGSTRING2("GppSamplerImpl::Reset - got isa os_task_running address 0x%X", osAddr); |
126 LOGSTRING2("GppSamplerImpl::Reset - got isa os_task_running address 0x%X", osAddr); |
113 } |
127 } |
114 |
128 |
115 LOGTEXT("GppSamplerImpl::Reset - initializing isa task list"); |
129 LOGSTRING("GppSamplerImpl::Reset - initializing isa task list"); |
116 |
130 |
117 iIsaSample = false; |
131 iIsaSample = false; |
118 |
132 |
119 for(TInt i=0;i<256;i++) |
133 for(TInt i(0);i<256;i++) |
120 knownIsaTasks[i] = -1; |
134 knownIsaTasks[i] = -1; |
121 |
135 |
122 knownIsaTaskCount = 0; |
136 knownIsaTaskCount = 0; |
123 |
137 |
124 iCpuSelector = 0x3; |
138 iCpuSelector = 0x3; |
428 // This extracts the thread and PC that was current when the interrupt went off and |
463 // This extracts the thread and PC that was current when the interrupt went off and |
429 // encodes it into the sample data buffer. If enough data has been generated, the |
464 // encodes it into the sample data buffer. If enough data has been generated, the |
430 // DFC is triggered to complete a read request |
465 // DFC is triggered to complete a read request |
431 // |
466 // |
432 { |
467 { |
433 TUint8* w(this->tempBuf); |
468 NThread* pN(NKern::CurrentThread()); |
434 |
469 TUint8* w(this->tempBuf); |
435 // Kern::Printf(("Got thread 0x%08x"), &t); |
470 //TInt currCpu(NKern::CurrentCpu()); |
436 #ifdef __SMP__ |
471 TInt mySampleStartTime(NKern::TickCount()); // get the system tick value for sync purposes, in ms |
437 // get the program counter of irq mode |
472 // TInt tickdiff(mySampleStartTime-iPrevTS); |
438 TUint32 pc = (TUint32)Arm::IrqReturnAddress(); |
473 |
|
474 if (Kern::NThreadToDThread(pN)==NULL) |
|
475 { |
|
476 LOGSTRING("Kern::NThreadToDThread is null"); |
|
477 } |
|
478 |
|
479 else |
|
480 { |
|
481 // check timestamp & compare to previous |
|
482 // if out of sync, encode unknown::unknown thread |
|
483 |
|
484 /* |
|
485 // In SMP environment there have been missing ticks. These prints are for helping debug this issue |
|
486 // but solution might not work. |
|
487 if(tickdiff > 1) |
|
488 { |
|
489 Kern::Printf(("DGppSamplerImpl::SampleImpl() - Current time tick %d"), mySampleStartTime); |
|
490 Kern::Printf(("DGppSamplerImpl::SampleImpl() - Previous time tick %d"), iPrevTS); |
|
491 // Kern::Printf(("DGppSamplerImpl::SampleImpl() - Tick period %d"),NKern::TickPeriod()); |
|
492 Kern::Printf(("DGppSamplerImpl::SampleImpl() - Tick difference %d"),tickdiff); |
|
493 Kern::Printf(("DGppSamplerImpl::SampleImpl() - Current cpu %d"),NKern::CurrentCpu()); |
|
494 } |
|
495 // else |
|
496 // { |
|
497 // Kern::Printf(("DGppSamplerImpl::SampleImpl() - Tick differance <= 1: %d"),tickdiff); |
|
498 // } |
|
499 */ |
|
500 |
|
501 TLinAddr pC; |
|
502 |
|
503 #ifdef __SMP__ |
|
504 pC = Arm::IrqReturnAddress(); |
439 #else |
505 #else |
440 // get program counter of irq mode |
506 // get program counter of irq mode |
441 TUint32 pc = iInterruptStack[-1]; |
507 pC = iInterruptStack[-1]; // ignore the low bit being set for THUMB mode - we use for something else |
442 #endif |
508 #endif |
443 //LOGSTRING3("pc value 0x%x sp 0x%x",pc,iInterruptStack); |
509 //Kern::Printf(("pc value 0x%x sp 0x%x"),pc,iInterruptStack); |
444 |
510 pC &= ~1; |
445 // ignore the low bit being set for THUMB mode - we use for something else |
511 TInt diff(pC - iLastPc); |
446 pc &= ~1; |
512 iLastPc = pC; |
447 TInt diff = pc - iLastPc; |
513 |
448 iLastPc = pc; |
514 if(iIsaStatus > 0) |
449 |
515 { |
450 if(iIsaStatus > 0) |
516 if((TUint32)pC > (TUint32)iIsaStart && (TUint32)pC < (TUint32)iIsaEnd) |
451 { |
517 { |
452 if((TUint32)pc > (TUint32)iIsaStart && (TUint32)pc < (TUint32)iIsaEnd) |
518 iIsaSample = true; |
453 { |
519 } |
454 LOGSTRING2("Identified ISA execution at 0x%x",pc); |
520 else |
455 iIsaSample = true; |
521 { |
456 } |
522 iIsaSample = false; |
457 else |
523 } |
458 { |
524 } |
459 LOGSTRING2("Normal sample at 0x%x",pc); |
525 |
460 iIsaSample = false; |
526 // if((TUint32)pC < 0x80000000 || (TUint32)pC > 0x8FFFFFFF) |
461 } |
527 // { |
462 } |
528 // //Kern::Printf("DGppSamplerImpl::SampleImpl() - wrong PC value, 0x%x", (TUint32)pC); |
463 |
529 // iIsaSample = true; |
464 // request for current thread from kernel |
530 // } |
465 DThread& t = ((DThread&)*Kern::NThreadToDThread(NKern::CurrentThread())); |
531 |
466 |
532 // request for current thread from kernel |
467 TUint tid; |
533 DThread& t(((DThread&)*Kern::NThreadToDThread(pN))); |
468 TUint8 isaTask = 0; |
534 |
469 if(iIsaSample) |
535 TUint tid; |
470 { |
536 TUint8 isaTask(0); |
471 LOGSTRING2("Reading ISA task number from 0x%x",isaOsTaskRunningAddr); |
537 if(iIsaSample) |
472 |
538 { |
473 // if we don't get reasonable ISA address to read, skip ISA task handling |
539 //Kern::Printf(("Reading ISA task number from 0x%x"),isaOsTaskRunningAddr); |
474 if(isaOsTaskRunningAddr == 0) |
540 // if we don't get reasonable ISA address to read, skip ISA task handling |
475 { |
541 if(isaOsTaskRunningAddr == 0) |
476 tid = 100000; // to tell the difference from SOS threads |
542 { |
477 iIsaSample = false; |
543 tid = 100000; // to tell the difference from SOS threads |
478 } |
544 iIsaSample = false; |
479 else // normal ISA task parsing process |
545 } |
480 { |
546 else // normal ISA task parsing process |
481 isaTask = *isaOsTaskRunningAddr; |
547 { |
482 LOGSTRING2("ISA task = %d",isaTask); |
548 isaTask = *isaOsTaskRunningAddr; |
483 tid = isaTask; |
549 LOGSTRING2("ISA task = %d",isaTask); |
484 // this will make sure we don't mix ISA tasks and normal tasks |
550 tid = isaTask; |
485 tid += 100000; |
551 // this will make sure we don't mix ISA tasks and normal tasks |
486 } |
552 tid += 100000; |
487 |
553 } |
488 } |
554 } |
489 else |
555 else |
490 { |
556 { |
491 tid = t.iId; |
557 tid = t.iId; |
492 } |
558 } |
493 |
559 |
494 if (tid != iLastThread) |
560 if (tid != iLastThread) |
495 { |
561 { |
496 // Change of thread is marked in the low bit of the PC difference |
562 diff |= 1; // Change of thread is marked in the low bit of the PC difference |
497 diff |= 1; |
563 } |
498 } |
564 TUint rp(iRepeat); |
499 TUint rp = iRepeat; |
565 if (diff == 0) |
500 if (diff == 0) |
566 { |
501 { |
567 iRepeat = rp + 1; // Identical sample, bump up the repeat count |
502 // Identical sample, bump up the repeat count |
568 } |
503 iRepeat = rp + 1; |
569 else |
504 } |
570 { |
505 else |
571 if (rp) |
506 { |
572 { |
507 if (rp) |
573 w = EncodeRepeat(w); // Encode the repeat data |
508 { |
574 } |
509 // Encode the repeat data |
575 w = EncodeInt(w, diff); // Encode the PC difference |
510 w = EncodeRepeat(w); |
576 //if (diff & 0x1 == 1) |
511 } |
577 if (diff & 1) |
512 // Encode the PC difference |
578 { |
513 w = EncodeInt(w, diff); |
579 // LOGSTRING3("Encode pc diff curr cpu %d diff %d", currCpu, diff); |
514 if (diff & 1) |
580 if(iIsaSample) // Encode the new thread ID |
515 { |
581 { |
516 // Encode the new thread ID |
582 iLastThread = tid; |
517 if(iIsaSample) |
583 // LOGSTRING2("Encode thread id UINT curr cpu %d", currCpu); |
518 { |
584 w = EncodeUint(w,tid); |
519 iLastThread = tid; |
585 if(!this->IsaTaskKnown(isaTask)) |
520 w = EncodeUint(w,tid); |
586 { |
521 |
587 //Kern::Printf("Encode isa task"); |
522 if(!this->IsaTaskKnown(isaTask)) |
588 w = EncodeIsaTask(w,iLastThread); |
523 { |
589 } |
524 w = EncodeIsaTask(w,iLastThread); |
590 //LOGSTRING2("Sample total length: %d",w-tempBuf); |
525 } |
591 TInt length = w-tempBuf; |
526 //LOGSTRING2("Sample total length: %d",w-tempBuf); |
592 return length; // encoded isa task, return here |
527 TInt length = w-tempBuf; |
593 } |
528 // encoded isa task, return here |
594 iLastThread = tid; |
529 return length; |
595 // LOGSTRING2("Encode lastthread id UinT curr cpu %d", currCpu); |
530 } |
596 w = EncodeUint(w, tid); |
531 |
597 |
532 iLastThread = tid; |
598 #ifdef __SMP__ |
533 w = EncodeUint(w, tid); |
599 // iStartTime format: 0xXXXXXXX0, the last byte set to zero |
534 |
600 // iMask = 0xfffffff0(0b111....1110000), last bits reserved for the CPUs bit0=CPU0 etc. |
535 #ifdef __SMP__ |
601 // iCpuSelector = 0x1(0b0001), 0x2(0b0010), 0x4(0b0100) or 0x8(0b1000), to use against the mask |
536 // iStartTime format: 0xXXXXXXX0, the last byte set to zero |
602 //#define TAG(obj) (*(TUint32*)&(obj.iAsyncDeleteNext)) |
537 // iMask = 0xfffffff0(0b111....1110000) |
603 // check first time founding |
538 // iCpuSelector = 0x1(0b0001), 0x2(0b0010), 0x4(0b0100) or 0x8(0b1000) |
604 LOGSTRING4("TAG(t) 0x%x, iMask 0x%x, AND 0x%x ",TAG(t),iMask, (TAG(t)& iMask)); |
539 |
605 if ((TAG(t) & iMask) != iStartTime) |
540 // check first time founding |
606 { |
541 if ((TAG(t) & iMask) != iStartTime) |
607 // mark tagged for this CPU |
542 { |
608 TAG(t) = (iStartTime | iCpuSelector); |
543 // mark tagged for this CPU |
609 |
544 TAG(t) = (iStartTime | iCpuSelector); |
610 // The thread is 'unknown' to this sample, so encode the thread name |
545 |
611 // LOGSTRING2("Encode SMP thread start time curr cpu %d", currCpu); |
546 // The thread is 'unknown' to this sample, so encode the thread name |
612 w = EncodeThread(w, t); |
547 w = EncodeThread(w, t); |
613 } |
548 } |
614 // check if thread appeared on this CPU |
549 // check if thread appeared on this CPU |
615 else if((TAG(t) & iCpuSelector) != iCpuSelector) |
550 else if((TAG(t) & iCpuSelector) != iCpuSelector) |
616 { |
551 { |
617 TAG(t) = (TAG(t) | iCpuSelector); |
552 TAG(t) = (TAG(t) | iCpuSelector); |
618 // The thread is 'unknown' to this sample, so encode the thread name |
553 // The thread is 'unknown' to this sample, so encode the thread name |
619 // LOGSTRING2("Encode SMP thread cpu selector curr cpu %d", currCpu); |
554 w = EncodeThread(w, t); |
620 w = EncodeThread(w, t); |
555 } |
621 } |
556 #else |
622 #else |
557 // check if tag has not been set, neither original nor |
623 // check if tag has not been set, neither original nor |
558 if ((TAG(t) & 0xfffffffc) != iStartTime) |
624 if ((TAG(t) & 0xfffffffc) != iStartTime) |
559 { |
625 { |
560 TAG(t) = ((TAG(t) & 0x3) | iStartTime); |
626 TAG(t) = ((TAG(t) & 0x3) | iStartTime); |
561 // The thread is 'unknown' to this sample, so encode the thread name |
627 // The thread is 'unknown' to this sample, so encode the thread name |
562 w = EncodeThread(w, t); |
628 w = EncodeThread(w, t); |
|
629 } |
|
630 |
|
631 #endif |
563 } |
632 } |
564 #endif |
633 } |
565 } |
634 } |
566 } |
635 |
567 LOGSTRING2("Sample total length: %d",w-tempBuf); |
636 TInt length(w-tempBuf); |
568 TInt length = w-tempBuf; |
637 LOGSTRING2("Sample total length: %d",length); |
569 |
638 iPrevTS = mySampleStartTime; // get the system tick value for sync purposes |
570 return length; |
639 return length; |
571 } |
640 } |
572 |
641 |