diff -r 000000000000 -r 7f656887cf89 libraries/btrace_parser/src/btrace_context.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/btrace_parser/src/btrace_context.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,896 @@ +// btrace_context.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "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: +// Accenture - Initial contribution +// + +#include +#include "btrace_parser.h" + + +_LIT(KUnknown, "unknown"); + + +EXPORT_C TBtraceIdBase::TBtraceIdBase() + : iId(0) + { + } + +EXPORT_C TBtraceIdBase::TBtraceIdBase(TUint aId) + : iId(aId) + { + } + +EXPORT_C TBtraceIdBase::TBtraceIdBase(const TBtraceIdBase& aId) + : iId(aId.Value()) + { + } + +EXPORT_C void TBtraceIdBase::Set(TUint aValue) + { + iId = aValue; + } + +EXPORT_C TUint TBtraceIdBase::Value() const + { + return iId; + } + +EXPORT_C TBool TBtraceIdBase::operator==(const TBtraceIdBase& aId) const + { + return (aId.iId == iId); + } + +EXPORT_C TBtraceThreadId::TBtraceThreadId() + { + } + +EXPORT_C TBtraceThreadId::TBtraceThreadId(TUint aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C TBtraceThreadId::TBtraceThreadId(const TBtraceThreadId& aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C TBtraceProcessId::TBtraceProcessId() + { + } + +EXPORT_C TBtraceProcessId::TBtraceProcessId(TUint aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C TBtraceProcessId::TBtraceProcessId(const TBtraceProcessId& aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId() + { + } + +EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(TUint aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(const TBtraceWindowGroupId& aId) + : TBtraceIdBase(aId) + { + } + +EXPORT_C void MBtraceContextObserver::HandleThreadSeenL(const TBtraceTickCount&, const TBtraceThreadId&, TUint) + { + Panic(EBtpPanicUndefinedCallBack); + } + +EXPORT_C void MBtraceContextObserver::HandleThreadGoneL(const TBtraceTickCount&, const TBtraceThreadId&, TUint) + { + Panic(EBtpPanicUndefinedCallBack); + } + +EXPORT_C void MBtraceContextObserver::HandleThreadExitL(const TBtraceTickCount&, const TBtraceThreadId&, TExitType, TInt, const TDesC&, TUint) + { + Panic(EBtpPanicUndefinedCallBack); + } + +EXPORT_C void MBtraceContextObserver::HandleWindowGroupSeenL(const TBtraceTickCount&, const TBtraceWindowGroupId&, TUint) + { + Panic(EBtpPanicUndefinedCallBack); + } + +EXPORT_C CBtraceContext* CBtraceContext::NewL(CBtraceReader& aReader, TMode aMode) + { + CBtraceContext* self = new(ELeave) CBtraceContext(aReader, aMode); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CBtraceContext::~CBtraceContext() + { + iWindowGroupSeenNotifs.Close(); + iThreadExitNotifs.Close(); + iThreadGoneNotifs.Close(); + iThreadSeenNotifs.Close(); + iWindowGroups.Close(); + iThreads.Close(); + iProcesses.Close(); + iReader.RemoveObserver(BTrace::EThreadIdentification, *this); + iReader.RemoveObserver(KAmTraceCategory, *this); + } + + +TBool CBtraceContext::ThreadMatchesId(const TThread& aLeft, const TThread& aRight) + { + return (aLeft.iId == aRight.iId); + } + +TBool CBtraceContext::ThreadMatchesKernelId(const TThread& aLeft, const TThread& aRight) + { + return (aLeft.iKernelId == aRight.iKernelId); + } + +TBool CBtraceContext::ThreadMatchesNThreadAddress(const TThread& aLeft, const TThread& aRight) + { + return (aLeft.iNThreadAddress == aRight.iNThreadAddress); + } + +TBool CBtraceContext::ProcessMatchesId(const TProcess& aLeft, const TProcess& aRight) + { + return (aLeft.iId == aRight.iId); + } + +TBool CBtraceContext::ProcessMatchesDProcessAddress(const TProcess& aLeft, const TProcess& aRight) + { + return (aLeft.iDProcessAddress == aRight.iDProcessAddress); + } + +TBool CBtraceContext::WindowGroupMatchesId(const TWindowGroup& aLeft, const TWindowGroup& aRight) + { + return (aLeft.iId == aRight.iId); + } + +TBool CBtraceContext::WindowGroupMatchesThreadId(const TWindowGroup& aLeft, const TWindowGroup& aRight) + { + return (aLeft.iThreadId == aRight.iThreadId); + } + +TBool CBtraceContext::WindowGroupMatchesWServId(const TWindowGroup& aLeft, const TWindowGroup& aRight) + { + return (aLeft.iWindowGroupId == aRight.iWindowGroupId); + } + +EXPORT_C const TDesC& CBtraceContext::ThreadName(const TBtraceThreadId& aId) const + { + TThread findKey(0, 0, KNullDesC8); + findKey.iId = aId; + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesId)); + if (pos >= 0) + { + return iThreads[pos].iName; + } + else + { + return KUnknown; + } + } + +EXPORT_C void CBtraceContext::GetFullThreadName(const TBtraceThreadId& aId, TDes& aFullName) const + { + TThread findKey(0, 0, KNullDesC8); + findKey.iId = aId; + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesId)); + if (pos >= 0) + { + const TThread& thread = iThreads[pos]; + TProcess findKey(thread.iOwningProcess); + TInt processPos = iProcesses.Find(findKey, TIdentityRelation(ProcessMatchesDProcessAddress)); + __ASSERT_ALWAYS(processPos >= 0, Panic(EBtpPanicFailedToFindProcess)); + aFullName.Zero(); + aFullName.Append(ProcessName(iProcesses[processPos].iId)); + aFullName.Append(_L("::")); + aFullName.Append(thread.iName); + } + else + { + aFullName = KUnknown; + } + } + +EXPORT_C TThreadId CBtraceContext::ThreadId(const TBtraceThreadId& aId) const + { + TThread findKey(0, 0, KNullDesC8); + findKey.iId = aId; + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesId)); + __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadIdNotFound)); + return iThreads[pos].iKernelId; + } + +EXPORT_C const TDesC& CBtraceContext::ProcessName(const TBtraceProcessId& aId) const + { + TProcess findKey(0); + findKey.iId = aId; + TInt pos = iProcesses.Find(findKey, TIdentityRelation(ProcessMatchesId)); + __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicProcessNameNotFound)); + return iProcesses[pos].iName; + } + +EXPORT_C TInt CBtraceContext::WindowGroupId(const TBtraceWindowGroupId& aId) const + { + TWindowGroup findKey(0, 0, KNullDesC); + findKey.iId = aId; + TInt pos = iWindowGroups.Find(findKey, TIdentityRelation(WindowGroupMatchesId)); + __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound)); + return iWindowGroups[pos].iWindowGroupId; + } + +EXPORT_C const TDesC& CBtraceContext::WindowGroupName(const TBtraceWindowGroupId& aId) const + { + TWindowGroup findKey(0, 0, KNullDesC); + findKey.iId = aId; + TInt pos = iWindowGroups.Find(findKey, TIdentityRelation(WindowGroupMatchesId)); + __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound)); + return iWindowGroups[pos].iName; + } + +EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(TUint32 aNThreadAddress) const + { + TThread findKey(aNThreadAddress, 0, KNullDesC8); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesNThreadAddress)); + if (pos >= 0) + { + return &iThreads[pos].iId; + } + else + { + return NULL; + } + } + +EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(const TThreadId& aId) const + { + TThread findKey(0, 0, KNullDesC8); + findKey.iKernelId = TUint(aId); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesKernelId)); + if (pos >= 0) + { + return &iThreads[pos].iId; + } + else + { + return NULL; + } + } + +EXPORT_C const TBtraceWindowGroupId* CBtraceContext::FindWindowGroup(TInt aWServWgId) const + { + TWindowGroup findKey(aWServWgId); + TInt pos = iWindowGroups.Find(findKey, TIdentityRelation(WindowGroupMatchesWServId)); + if (pos >= 0) + { + return &iWindowGroups[pos].iId; + } + else + { + return NULL; + } + } + +EXPORT_C void CBtraceContext::FindThreadsL(const TDesC& aPattern, RArray& aThreads) const + { + TInt count = iThreads.Count(); + while (--count >= 0) + { + const TThread& thread = iThreads[count]; + TFullName name; + GetFullThreadName(thread.iId, name); + if (name.MatchF(aPattern) != KErrNotFound) + { + aThreads.AppendL(thread.iId); + } + } + } + +EXPORT_C void CBtraceContext::FindWindowGroupsL(const TDesC& aPattern, RArray& aWindowGroups) const + { + TInt count = iWindowGroups.Count(); + while (--count >= 0) + { + const TWindowGroup& windowGroup = iWindowGroups[count]; + if (windowGroup.iName.MatchF(aPattern) != KErrNotFound) + { + aWindowGroups.AppendL(windowGroup.iId); + } + } + } + +EXPORT_C void CBtraceContext::FindWindowGroupsByThreadName(const TDesC& aPattern, RArray& aWindowGroups) const + { + TInt count = iThreads.Count(); + while (--count >= 0) + { + const TThread& thread = iThreads[count]; + TFullName name; + GetFullThreadName(thread.iId, name); + if (name.MatchF(aPattern) != KErrNotFound) + { + for (TInt i = (iWindowGroups.Count() - 1); i >= 0; --i) + { + const TWindowGroup& thisWindowGroup = iWindowGroups[i]; + if (thisWindowGroup.iThreadId.Id() == thread.iKernelId) + { + aWindowGroups.AppendL(thisWindowGroup.iId); + } + } + } + } + } + +EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId) + { + NotifyThreadSeenL(aPattern, aObserver, aId, ENotificationOneShot); + } + +EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) + { + iThreadSeenNotifs.AppendL(TThreadSeenNotif(aId, aPattern, aObserver, aPersistence)); + } + +EXPORT_C void CBtraceContext::CancelNotifyThreadSeen(MBtraceContextObserver& aObserver) + { + for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i) + { + if (&iThreadSeenNotifs[i].iObserver == &aObserver) + { + iThreadSeenNotifs.Remove(i); + } + } + } + +EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId) + { + return NotifyThreadGoneL(aPattern, aObserver, aId, ENotificationOneShot); + } + +EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) + { + iThreadGoneNotifs.AppendL(TThreadGoneNotif(aId, aPattern, aObserver, aPersistence)); + } + +EXPORT_C void CBtraceContext::CancelNotifyThreadGone(MBtraceContextObserver& aObserver) + { + for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i) + { + if (&iThreadGoneNotifs[i].iObserver == &aObserver) + { + iThreadGoneNotifs.Remove(i); + } + } + } + +EXPORT_C void CBtraceContext::NotifyThreadExitL(const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) + { + iThreadExitNotifs.AppendL(TThreadExitNotif(aId, aPattern, aExitTypes, aReason, aCategory, aObserver, aPersistence)); + } + +EXPORT_C void CBtraceContext::CancelNotifyThreadExit(MBtraceContextObserver& aObserver) + { + for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i) + { + if (&iThreadExitNotifs[i].iObserver == &aObserver) + { + iThreadExitNotifs.Remove(i); + } + } + } + +EXPORT_C void CBtraceContext::NotifyWindowGroupSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) + { + iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EWindowGroupName, aObserver, aPersistence)); + } + +EXPORT_C void CBtraceContext::NotifyWindowGroupSeenByThreadNameL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) + { + iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EThreadName, aObserver, aPersistence)); + } + +EXPORT_C void CBtraceContext::CancelNotifyWindowGroupSeen(MBtraceContextObserver& aObserver) + { + for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i) + { + if (&iWindowGroupSeenNotifs[i].iObserver == &aObserver) + { + iWindowGroupSeenNotifs.Remove(i); + } + } + } + +CBtraceContext::CBtraceContext(CBtraceReader& aReader, TMode aMode) + : iMode(aMode), iReader(aReader), iNextBtraceThreadId(KMaxTUint), iNextBtraceProcessId(KMaxTUint) + { + } + +void CBtraceContext::ConstructL() + { + iReader.AddObserverL(BTrace::EThreadIdentification, *this, CBtraceReader::EIncludeSynchronizationFrames); + iReader.AddObserverL(KAmTraceCategory, *this); + } + +TUint CBtraceContext::GetNextThreadId() + { + TUint id = iNextBtraceThreadId--; + __ASSERT_ALWAYS(iNextBtraceThreadId > 0, Panic(EBtpPanicBtraceThreadIdOverflow)); + return id; + } + +TUint CBtraceContext::GetNextProcessId() + { + TUint id = iNextBtraceProcessId--; + __ASSERT_ALWAYS(iNextBtraceProcessId > 0, Panic(EBtpPanicBtraceProcessIdOverflow)); + return id; + } + +TUint CBtraceContext::GetNextWindowGroupId() + { + TUint id = iNextBtraceWindowGroupId--; + __ASSERT_ALWAYS(iNextBtraceWindowGroupId > 0, Panic(EBtpPanicBtraceWindowGroupIdOverflow)); + return id; + } + +void CBtraceContext::SeenL(const TThread& aThread, const TBtraceTickCount& aTickCount) + { + TFullName name; + GetFullThreadName(aThread.iId, name); + for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i) + { + const TThreadSeenNotif& thisNotif = iThreadSeenNotifs[i]; + if (name.MatchF(thisNotif.iPattern) != KErrNotFound) + { + MBtraceContextObserver& observer = thisNotif.iObserver; + TUint id = thisNotif.iId; + if (thisNotif.iPersistence == ENotificationOneShot) + { + iThreadSeenNotifs.Remove(i); + } + observer.HandleThreadSeenL(aTickCount, aThread.iId, id); + } + } + } + +void CBtraceContext::GoneL(const TThread& aThread, const TBtraceTickCount& aTickCount) + { + TFullName name; + GetFullThreadName(aThread.iId, name); + for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i) + { + const TThreadGoneNotif& notif = iThreadGoneNotifs[i]; + if (name.MatchF(notif.iPattern) != KErrNotFound) + { + MBtraceContextObserver& observer = notif.iObserver; + TUint id = notif.iId; + if (notif.iPersistence == ENotificationOneShot) + { + iThreadGoneNotifs.Remove(i); + } + observer.HandleThreadGoneL(aTickCount, aThread.iId, id); + } + } + } + +void CBtraceContext::ExitedL(const TThread& aThread, TExitType aExitType, TInt aReason, const TDesC& aCategory, const TBtraceTickCount& aTickCount) + { + TFullName name; + GetFullThreadName(aThread.iId, name); + for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i) + { + const TThreadExitNotif& notif = iThreadExitNotifs[i]; + if (notif.Matches(name, aExitType, aReason, aCategory)) + { + MBtraceContextObserver& observer = notif.iObserver; + TUint id = notif.iId; + if (notif.iPersistence == ENotificationOneShot) + { + iThreadExitNotifs.Remove(i); + } + observer.HandleThreadExitL(aTickCount, aThread.iId, aExitType, aReason, aCategory, id); + } + } + } + +void CBtraceContext::SeenL(const TWindowGroup& aWindowGroup, const TBtraceTickCount& aTickCount) + { + for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i) + { + const TWindowGroupSeenNotif& thisNotif = iWindowGroupSeenNotifs[i]; + if (thisNotif.iPatternType == TWindowGroupSeenNotif::EWindowGroupName) + { + if (aWindowGroup.iName.MatchF(thisNotif.iPattern) != KErrNotFound) + { + MBtraceContextObserver& observer = thisNotif.iObserver; + TUint id = thisNotif.iId; + if (thisNotif.iPersistence == ENotificationOneShot) + { + iWindowGroupSeenNotifs.Remove(i); + } + observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id); + } + } + else + { + TThread findKey(0, 0, KNullDesC8); + findKey.iKernelId = TUint(aWindowGroup.iThreadId); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesKernelId)); + if (pos >= 0) + { + TFullName threadName; + GetFullThreadName(iThreads[pos].iId, threadName); + if (threadName.MatchF(thisNotif.iPattern)) + { + MBtraceContextObserver& observer = thisNotif.iObserver; + TUint id = thisNotif.iId; + if (thisNotif.iPersistence == ENotificationOneShot) + { + iWindowGroupSeenNotifs.Remove(i); + } + observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id); + } + } + } + } + } + +void CBtraceContext::HandleBtraceFrameL(const TBtraceFrame& aFrame) + { + const TUint8* data = aFrame.iData.Ptr(); + + if (aFrame.iCategory == BTrace::EThreadIdentification) + { + switch (aFrame.iSubCategory) + { + case BTrace::EThreadCreate: + { + TUint32 nthreadAddress = *(TUint32*)data; + TUint32 dprocessAddress = *((TUint32*)data + 1); + TPtrC8 name(aFrame.iData.Mid(8)); + +#ifdef BTRACE_CONTEXT_DEBUG + TFullName name16; + name16.Copy(name); + RDebug::Print(_L("BTrace::EThreadCreate: 0x%08x \"%S\""), nthreadAddress, &name16); +#endif + + TThread thread(nthreadAddress, dprocessAddress, name); + AppendL(thread, aFrame.iTickCount); + break; + } + case BTrace::EThreadDestroy: + { + TUint32 nthreadAddress = *(TUint32*)data; + TThread findKey(nthreadAddress, 0, KNullDesC8); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesNThreadAddress)); + if (pos >= 0) + { +#ifdef BTRACE_CONTEXT_DEBUG + RDebug::Print(_L("BTrace::EThreadDestroy: %u %u 0x%08x \"%S\""), iThreads[pos].iId.Value(), iThreads[pos].iKernelId, nthreadAddress, &iThreads[pos].iName); +#endif + GoneL(iThreads[pos], aFrame.iTickCount); + RemoveThread(pos); + } + else + { + // This can happen if a thread is destroyed after the btrace buffer has been enabled but before the BTrace::EThreadIdentification category has been enabled. + iReader.Log(_L("Destroyed thread 0x%08x not found\r\n"), nthreadAddress); + } + break; + } + case BTrace::EThreadName: + { + TUint32 nthreadAddress = *(TUint32*)data; + TUint32 dprocessAddress = *((TUint32*)data + 1); + TPtrC8 name(aFrame.iData.Mid(8)); + +#ifdef BTRACE_CONTEXT_DEBUG + TFullName name16; + name16.Copy(name); + RDebug::Print(_L("BTrace::EThreadName: 0x%08x \"%S\""), nthreadAddress, &name16); +#endif + TThread findKey(nthreadAddress, 0, KNullDesC8); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesNThreadAddress)); + if (pos >= 0) + { + iThreads[pos].iName.Copy(name); + SeenL(iThreads[pos], aFrame.iTickCount); + } + else + { + TThread thread(nthreadAddress, dprocessAddress, name); + AppendL(thread, aFrame.iTickCount); + } + break; + } + case BTrace::EProcessCreate: + { + TUint32 dprocessAddress = *(TUint32*)data; +#ifdef BTRACE_CONTEXT_DEBUG + RDebug::Print(_L("BTrace::EProcessCreate: 0x%08x"), dprocessAddress); +#endif + TProcess process(dprocessAddress); + AppendL(process, aFrame.iTickCount); + break; + } + case BTrace::EProcessName: + { + TUint32 dprocessAddress = *((TUint32*)data + 1); + TPtrC8 name(aFrame.iData.Mid(8)); + +#ifdef BTRACE_CONTEXT_DEBUG + TFullName name16; + name16.Copy(name); + RDebug::Print(_L("BTrace::EProcessName: 0x%08x \"%S\""), dprocessAddress, &name16); +#endif + TProcess findKey(dprocessAddress); + TInt pos = iProcesses.Find(findKey, TIdentityRelation(ProcessMatchesDProcessAddress)); + if (pos >= 0) + { + iProcesses[pos].iName.Copy(name); + SeenAllThreadsL(iProcesses[pos], aFrame.iTickCount); + } + else + { + TProcess process(dprocessAddress, name); + AppendL(process, aFrame.iTickCount); + } + break; + } + case BTrace::EThreadId: + { + TUint32 nthreadAddress = *(TUint32*)data; + TUint32 threadId = *((TUint32*)data + 2); + TThread findKey(nthreadAddress, 0, KNullDesC8); + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesNThreadAddress)); + __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadNotFoundForId)); + iThreads[pos].iKernelId = threadId; +#ifdef BTRACE_CONTEXT_DEBUG + RDebug::Print(_L("BTrace::EThreadId: %u 0x%08x \"%S\""), threadId, nthreadAddress, &iThreads[pos].iName); +#endif + break; + } + default: + { + // Ignore anything we don't know about. + break; + } + } + } + else if (aFrame.iCategory == KAmTraceCategory) + { + if (aFrame.iSubCategory == EAmTraceSubCategoryWindowGroupName) + { + TUint wgId = *(TUint32*)data; + TInt kernelThreadId = *((TInt32*)data + 1); + TPtrC8 nameData = aFrame.iData.Mid(8); + TPtrC name((TUint16*)nameData.Ptr(), nameData.Length() / 2); + TWindowGroup findKey(wgId); + TInt pos = iWindowGroups.Find(findKey, TIdentityRelation(WindowGroupMatchesWServId)); + if (pos >= 0) + { + TWindowGroup& windowGroup = iWindowGroups[pos]; + windowGroup.iName = name; + SeenL(windowGroup, aFrame.iTickCount); + } + else + { + TWindowGroup windowGroup(wgId, TThreadId(kernelThreadId), name); + windowGroup.iId.Set(GetNextWindowGroupId()); + iWindowGroups.AppendL(windowGroup); + SeenL(windowGroup, aFrame.iTickCount); + } + } + else if ((aFrame.iSubCategory >= EAmTraceSubCategoryThreadKilled) && (aFrame.iSubCategory <= EAmTraceSubCategoryThreadPanicked)) + { + TUint id = *(TUint32*)data; + TInt reason = *((TInt32*)data + 1); + TThread findKey(0, 0, KNullDesC8); + findKey.iKernelId = id; + TInt pos = iThreads.Find(findKey, TIdentityRelation(ThreadMatchesKernelId)); + if (pos >= 0) + { + const TThread& thread = iThreads[pos]; + switch (aFrame.iSubCategory) + { + case EAmTraceSubCategoryThreadKilled: + { + ExitedL(thread, EExitKill, reason, KNullDesC, aFrame.iTickCount); + break; + } + case EAmTraceSubCategoryThreadTerminated: + { + ExitedL(thread, EExitTerminate, reason, KNullDesC, aFrame.iTickCount); + break; + } + case EAmTraceSubCategoryThreadPanicked: + { + TPtrC8 narrowCategory(aFrame.iData.Mid(sizeof(TInt) * 2)); + TExitCategoryName category; + category.Copy(narrowCategory); + ExitedL(thread, EExitPanic, reason, category, aFrame.iTickCount); + break; + } + default: + { + // Ignore anything we don't know about. + break; + } + } + } + } + } + } + +void CBtraceContext::AppendL(const TThread& aThread, const TBtraceTickCount& aTickCount) + { + iThreads.AppendL(aThread); + TThread& thread = iThreads[iThreads.Count() - 1]; + thread.iId.Set(GetNextThreadId()); + + // Increment the reference count of the owning process. + TProcess findKey(thread.iOwningProcess); + TInt pos = iProcesses.Find(findKey, TIdentityRelation(ProcessMatchesDProcessAddress)); + if (pos >= 0) + { + ++(iProcesses[pos].iReferenceCount); + } + + SeenL(thread, aTickCount); + } + +void CBtraceContext::AppendL(const TProcess& aProcess, const TBtraceTickCount& aTickCount) + { + iProcesses.AppendL(aProcess); + TProcess& process = iProcesses[iProcesses.Count() - 1]; + process.iId.Set(GetNextProcessId()); + + // Set the reference count for this process. + for (TInt i = (iThreads.Count() - 1); i >= 0; --i) + { + if (iThreads[i].iOwningProcess == process.iDProcessAddress) + { + ++process.iReferenceCount; + } + } + + SeenAllThreadsL(process, aTickCount); + } + +void CBtraceContext::RemoveThread(TInt aPosition) + { + TProcess findKey(iThreads[aPosition].iOwningProcess); + TInt processPos = iProcesses.Find(findKey, TIdentityRelation(ProcessMatchesDProcessAddress)); + if (processPos >= 0) + { + if (--(iProcesses[processPos].iReferenceCount) == 0) + { + iProcesses.Remove(processPos); + } + } + iThreads.Remove(aPosition); + } + +void CBtraceContext::SeenAllThreadsL(const TProcess& aProcess, const TBtraceTickCount& aTickCount) + { + // Call SeenL for each thread belonging to this process because. This is called when a process + // is created or altered because this change may allow a TThreadSeenNotif to be completed. + const TInt numThreads = iThreads.Count(); + for (TInt i = 0; i < numThreads; ++i) + { + const TThread& thread = iThreads[i]; + if (thread.iOwningProcess == aProcess.iDProcessAddress) + { + SeenL(thread, aTickCount); + } + } + } + +void CBtraceContext::BtraceBufferHasBeenReset() + { + iThreads.Close(); + iProcesses.Close(); + } + +CBtraceContext::TThread::TThread(TUint32 aNThreadAddress, TUint32 aOwningProcess, const TDesC8& aName) + : iNThreadAddress(aNThreadAddress), iOwningProcess(aOwningProcess), iKernelId(0) + { + iName.Copy(aName); + } + +CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress) + : iDProcessAddress(aDProcessAddress), iReferenceCount(0) + { + } + +CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress, const TDesC8& aName) + : iDProcessAddress(aDProcessAddress), iReferenceCount(0) + { + iName.Copy(aName); + } + +CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId) + : iWindowGroupId(aWindowGroupId), iThreadId(0) + { + } + +CBtraceContext::TWindowGroup::TWindowGroup(const TDesC& aName) + : iWindowGroupId(0), iThreadId(0), iName(aName) + { + } + +CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId, TThreadId aThreadId, const TDesC& aName) + : iWindowGroupId(aWindowGroupId), iThreadId(aThreadId), iName(aName) + { + } + +CBtraceContext::TThreadSeenNotif::TThreadSeenNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) + : iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence) + { + } + +CBtraceContext::TThreadGoneNotif::TThreadGoneNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) + : iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence) + { + } + +CBtraceContext::TThreadExitNotif::TThreadExitNotif(TUint aId, const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) + : iId(aId), iPattern(aPattern), iExitTypes(aExitTypes), iReason(aReason), iCategory(aCategory), iObserver(aObserver), iPersistence(aPersistence) + { + } + +CBtraceContext::TWindowGroupSeenNotif::TWindowGroupSeenNotif(TUint aId, const TDesC& aPattern, TPatternType aPatternType, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) + : iId(aId), iPattern(aPattern), iPatternType(aPatternType), iObserver(aObserver), iPersistence(aPersistence) + { + } + +TBool CBtraceContext::TThreadExitNotif::Matches(const TDesC& aThreadName, TExitType aExitType, TInt aReason, const TDesC& aCategory) const + { + if (aThreadName.MatchF(iPattern) != KErrNotFound) + { + if (MatchesType(aExitType)) + { + if ((iReason == NULL) || (*iReason == aReason)) + { + if ((aExitType != EExitPanic) || ((iCategory == NULL) || (*iCategory == aCategory))) + { + return ETrue; + } + } + } + } + return EFalse; + } + +TBool CBtraceContext::TThreadExitNotif::MatchesType(TExitType aExitType) const + { + switch (aExitType) + { + case EExitKill: + return (iExitTypes & EKill); + case EExitTerminate: + return (iExitTypes & ETerminate); + case EExitPanic: + return (iExitTypes & EPanic); + default: + ASSERT(EFalse); + return EFalse; + } + }