138 Kern::SafeClose(iExtTempObj,NULL); |
138 Kern::SafeClose(iExtTempObj,NULL); |
139 if (iNThread.iExtraContextSize > 0) |
139 if (iNThread.iExtraContextSize > 0) |
140 Kern::Free(iNThread.iExtraContext); |
140 Kern::Free(iNThread.iExtraContext); |
141 } |
141 } |
142 |
142 |
|
143 #if defined(__EPOC32__) && defined(KTHREAD) |
|
144 void CheckSupervisorStackUsage(DThread* aT) |
|
145 { |
|
146 const TUint32* p = (const TUint32*)aT->iSupervisorStack; |
|
147 TUint32 used = 0; |
|
148 TUint32 free = 0; |
|
149 if (p) |
|
150 { |
|
151 const TUint32* pE = p + (aT->iSupervisorStackSize / sizeof(TUint32)); |
|
152 while(p<pE && *p==0xeeeeeeeeu) |
|
153 ++p; |
|
154 used = (pE - p) * sizeof(TUint32); |
|
155 free = TUint32(aT->iSupervisorStackSize) - used; |
|
156 } |
|
157 Kern::Printf("Thread %O used %d bytes of kernel stack (%d bytes free)", aT, used, free); |
|
158 } |
|
159 #endif |
|
160 |
143 // Enter and return with system unlocked. |
161 // Enter and return with system unlocked. |
144 void DThread::Release() |
162 void DThread::Release() |
145 { |
163 { |
146 __KTRACE_OPT(KTHREAD,Kern::Printf("Thread %O Release()",this)); |
164 __KTRACE_OPT(KTHREAD,Kern::Printf("Thread %O Release()",this)); |
147 if (iWaitListReserved) |
165 if (iWaitListReserved) |
183 // cancel the timer |
201 // cancel the timer |
184 __KTRACE_OPT(KTHREAD,Kern::Printf("Cancelling timer")); |
202 __KTRACE_OPT(KTHREAD,Kern::Printf("Cancelling timer")); |
185 iTimer.Cancel(NULL); |
203 iTimer.Cancel(NULL); |
186 |
204 |
187 __KTRACE_OPT(KTHREAD,Kern::Printf("Freeing supervisor-mode stack")); |
205 __KTRACE_OPT(KTHREAD,Kern::Printf("Freeing supervisor-mode stack")); |
|
206 #if defined(__EPOC32__) && defined(KTHREAD) |
|
207 __KTRACE_OPT(KTHREAD,CheckSupervisorStackUsage(this)); |
|
208 #endif |
188 FreeSupervisorStack(); |
209 FreeSupervisorStack(); |
189 #ifdef BTRACE_THREAD_IDENTIFICATION |
210 #ifdef BTRACE_THREAD_IDENTIFICATION |
190 BTrace12(BTrace::EThreadIdentification,BTrace::EThreadDestroy,&iNThread,iOwningProcess,iId); |
211 BTrace12(BTrace::EThreadIdentification,BTrace::EThreadDestroy,&iNThread,iOwningProcess,iId); |
191 #endif |
212 #endif |
192 __DEBUG_EVENT(EEventRemoveThread, this); |
213 __DEBUG_EVENT(EEventRemoveThread, this); |
663 TUint64 sec = aTicks / e6; |
684 TUint64 sec = aTicks / e6; |
664 return (sec<<32)|us; |
685 return (sec<<32)|us; |
665 } |
686 } |
666 #endif |
687 #endif |
667 |
688 |
|
689 #if defined(__SMP__) && defined(KTIMING) |
|
690 void TraceStatsOnThreadExit(DThread* aT) |
|
691 { |
|
692 TUint64 rc = aT->iNThread.iRunCount.i64; |
|
693 NSchedulable::SCpuStats stats; |
|
694 NKern::Lock(); |
|
695 aT->iNThread.GetCpuStats(NSchedulable::E_RunTime|NSchedulable::E_ActiveTime, stats); |
|
696 NKern::Unlock(); |
|
697 TUint64 cputime = stats.iRunTime; |
|
698 TUint64 acttime = stats.iActiveTime; |
|
699 TUint32 f = NKern::CpuTimeMeasFreq(); |
|
700 TUint64 avgcpu = rc ? cputime / rc : 0; |
|
701 TUint64 ratio = (acttime*100)/cputime; |
|
702 TUint64 cpud = tix2us(cputime, f); |
|
703 TUint64 actd = tix2us(acttime, f); |
|
704 TUint64 avgd = tix2us(avgcpu, f); |
|
705 Kern::Printf("Thread %O RC=%u CPU=%u.%06us ACT=%u.%06us AVG=%u.%06us RATIO=%d%%", |
|
706 aT, TUint32(rc), |
|
707 I64HIGH(cpud), I64LOW(cpud), |
|
708 I64HIGH(actd), I64LOW(actd), |
|
709 I64HIGH(avgd), I64LOW(avgd), |
|
710 TUint32(ratio)); |
|
711 } |
|
712 #endif |
|
713 |
668 void DThread::Exit() |
714 void DThread::Exit() |
669 // |
715 // |
670 // This function runs in the context of the exiting thread |
716 // This function runs in the context of the exiting thread |
671 // Enter and leave with system unlocked |
717 // Enter and leave with system unlocked |
672 // |
718 // |
673 { |
719 { |
674 #if defined(__SMP__) && defined(KTIMING) |
720 #if defined(__SMP__) && defined(KTIMING) |
675 if (KDebugNum(KTIMING)) |
721 if (KDebugNum(KTIMING)) |
676 { |
722 TraceStatsOnThreadExit(this); |
677 TUint64 rc = iNThread.iRunCount.i64; |
|
678 NSchedulable::SCpuStats stats; |
|
679 NKern::Lock(); |
|
680 iNThread.GetCpuStats(NSchedulable::E_RunTime|NSchedulable::E_ActiveTime, stats); |
|
681 NKern::Unlock(); |
|
682 TUint64 cputime = stats.iRunTime; |
|
683 TUint64 acttime = stats.iActiveTime; |
|
684 TUint32 f = NKern::CpuTimeMeasFreq(); |
|
685 TUint64 avgcpu = rc ? cputime / rc : 0; |
|
686 TUint64 ratio = (acttime*100)/cputime; |
|
687 TUint64 cpud = tix2us(cputime, f); |
|
688 TUint64 actd = tix2us(acttime, f); |
|
689 TUint64 avgd = tix2us(avgcpu, f); |
|
690 Kern::Printf("Thread %O RC=%u CPU=%u.%06us ACT=%u.%06us AVG=%u.%06us RATIO=%d%%", |
|
691 this, TUint32(rc), |
|
692 I64HIGH(cpud), I64LOW(cpud), |
|
693 I64HIGH(actd), I64LOW(actd), |
|
694 I64HIGH(avgd), I64LOW(avgd), |
|
695 TUint32(ratio)); |
|
696 } |
|
697 #endif |
723 #endif |
698 #ifdef KPANIC |
724 #ifdef KPANIC |
699 if (iExitType==EExitPanic) |
725 if (iExitType==EExitPanic) |
700 { |
726 { |
701 __KTRACE_OPT2(KPANIC,KSCHED,Kern::Printf("Thread %O Panic %S %d",this,&iExitCategory,iExitReason)); |
727 __KTRACE_OPT2(KPANIC,KSCHED,Kern::Printf("Thread %O Panic %S %d",this,&iExitCategory,iExitReason)); |