|
1 // btrace_context.cpp |
|
2 // |
|
3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <e32debug.h> |
|
14 #include "btrace_parser.h" |
|
15 |
|
16 |
|
17 _LIT(KUnknown, "unknown"); |
|
18 |
|
19 |
|
20 EXPORT_C TBtraceIdBase::TBtraceIdBase() |
|
21 : iId(0) |
|
22 { |
|
23 } |
|
24 |
|
25 EXPORT_C TBtraceIdBase::TBtraceIdBase(TUint aId) |
|
26 : iId(aId) |
|
27 { |
|
28 } |
|
29 |
|
30 EXPORT_C TBtraceIdBase::TBtraceIdBase(const TBtraceIdBase& aId) |
|
31 : iId(aId.Value()) |
|
32 { |
|
33 } |
|
34 |
|
35 EXPORT_C void TBtraceIdBase::Set(TUint aValue) |
|
36 { |
|
37 iId = aValue; |
|
38 } |
|
39 |
|
40 EXPORT_C TUint TBtraceIdBase::Value() const |
|
41 { |
|
42 return iId; |
|
43 } |
|
44 |
|
45 EXPORT_C TBool TBtraceIdBase::operator==(const TBtraceIdBase& aId) const |
|
46 { |
|
47 return (aId.iId == iId); |
|
48 } |
|
49 |
|
50 EXPORT_C TBtraceThreadId::TBtraceThreadId() |
|
51 { |
|
52 } |
|
53 |
|
54 EXPORT_C TBtraceThreadId::TBtraceThreadId(TUint aId) |
|
55 : TBtraceIdBase(aId) |
|
56 { |
|
57 } |
|
58 |
|
59 EXPORT_C TBtraceThreadId::TBtraceThreadId(const TBtraceThreadId& aId) |
|
60 : TBtraceIdBase(aId) |
|
61 { |
|
62 } |
|
63 |
|
64 EXPORT_C TBtraceProcessId::TBtraceProcessId() |
|
65 { |
|
66 } |
|
67 |
|
68 EXPORT_C TBtraceProcessId::TBtraceProcessId(TUint aId) |
|
69 : TBtraceIdBase(aId) |
|
70 { |
|
71 } |
|
72 |
|
73 EXPORT_C TBtraceProcessId::TBtraceProcessId(const TBtraceProcessId& aId) |
|
74 : TBtraceIdBase(aId) |
|
75 { |
|
76 } |
|
77 |
|
78 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId() |
|
79 { |
|
80 } |
|
81 |
|
82 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(TUint aId) |
|
83 : TBtraceIdBase(aId) |
|
84 { |
|
85 } |
|
86 |
|
87 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(const TBtraceWindowGroupId& aId) |
|
88 : TBtraceIdBase(aId) |
|
89 { |
|
90 } |
|
91 |
|
92 EXPORT_C void MBtraceContextObserver::HandleThreadSeenL(const TBtraceTickCount&, const TBtraceThreadId&, TUint) |
|
93 { |
|
94 Panic(EBtpPanicUndefinedCallBack); |
|
95 } |
|
96 |
|
97 EXPORT_C void MBtraceContextObserver::HandleThreadGoneL(const TBtraceTickCount&, const TBtraceThreadId&, TUint) |
|
98 { |
|
99 Panic(EBtpPanicUndefinedCallBack); |
|
100 } |
|
101 |
|
102 EXPORT_C void MBtraceContextObserver::HandleThreadExitL(const TBtraceTickCount&, const TBtraceThreadId&, TExitType, TInt, const TDesC&, TUint) |
|
103 { |
|
104 Panic(EBtpPanicUndefinedCallBack); |
|
105 } |
|
106 |
|
107 EXPORT_C void MBtraceContextObserver::HandleWindowGroupSeenL(const TBtraceTickCount&, const TBtraceWindowGroupId&, TUint) |
|
108 { |
|
109 Panic(EBtpPanicUndefinedCallBack); |
|
110 } |
|
111 |
|
112 EXPORT_C CBtraceContext* CBtraceContext::NewL(CBtraceReader& aReader, TMode aMode) |
|
113 { |
|
114 CBtraceContext* self = new(ELeave) CBtraceContext(aReader, aMode); |
|
115 CleanupStack::PushL(self); |
|
116 self->ConstructL(); |
|
117 CleanupStack::Pop(self); |
|
118 return self; |
|
119 } |
|
120 |
|
121 EXPORT_C CBtraceContext::~CBtraceContext() |
|
122 { |
|
123 iWindowGroupSeenNotifs.Close(); |
|
124 iThreadExitNotifs.Close(); |
|
125 iThreadGoneNotifs.Close(); |
|
126 iThreadSeenNotifs.Close(); |
|
127 iWindowGroups.Close(); |
|
128 iThreads.Close(); |
|
129 iProcesses.Close(); |
|
130 iReader.RemoveObserver(BTrace::EThreadIdentification, *this); |
|
131 iReader.RemoveObserver(KAmTraceCategory, *this); |
|
132 } |
|
133 |
|
134 |
|
135 TBool CBtraceContext::ThreadMatchesId(const TThread& aLeft, const TThread& aRight) |
|
136 { |
|
137 return (aLeft.iId == aRight.iId); |
|
138 } |
|
139 |
|
140 TBool CBtraceContext::ThreadMatchesKernelId(const TThread& aLeft, const TThread& aRight) |
|
141 { |
|
142 return (aLeft.iKernelId == aRight.iKernelId); |
|
143 } |
|
144 |
|
145 TBool CBtraceContext::ThreadMatchesNThreadAddress(const TThread& aLeft, const TThread& aRight) |
|
146 { |
|
147 return (aLeft.iNThreadAddress == aRight.iNThreadAddress); |
|
148 } |
|
149 |
|
150 TBool CBtraceContext::ProcessMatchesId(const TProcess& aLeft, const TProcess& aRight) |
|
151 { |
|
152 return (aLeft.iId == aRight.iId); |
|
153 } |
|
154 |
|
155 TBool CBtraceContext::ProcessMatchesDProcessAddress(const TProcess& aLeft, const TProcess& aRight) |
|
156 { |
|
157 return (aLeft.iDProcessAddress == aRight.iDProcessAddress); |
|
158 } |
|
159 |
|
160 TBool CBtraceContext::WindowGroupMatchesId(const TWindowGroup& aLeft, const TWindowGroup& aRight) |
|
161 { |
|
162 return (aLeft.iId == aRight.iId); |
|
163 } |
|
164 |
|
165 TBool CBtraceContext::WindowGroupMatchesThreadId(const TWindowGroup& aLeft, const TWindowGroup& aRight) |
|
166 { |
|
167 return (aLeft.iThreadId == aRight.iThreadId); |
|
168 } |
|
169 |
|
170 TBool CBtraceContext::WindowGroupMatchesWServId(const TWindowGroup& aLeft, const TWindowGroup& aRight) |
|
171 { |
|
172 return (aLeft.iWindowGroupId == aRight.iWindowGroupId); |
|
173 } |
|
174 |
|
175 EXPORT_C const TDesC& CBtraceContext::ThreadName(const TBtraceThreadId& aId) const |
|
176 { |
|
177 TThread findKey(0, 0, KNullDesC8); |
|
178 findKey.iId = aId; |
|
179 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId)); |
|
180 if (pos >= 0) |
|
181 { |
|
182 return iThreads[pos].iName; |
|
183 } |
|
184 else |
|
185 { |
|
186 return KUnknown; |
|
187 } |
|
188 } |
|
189 |
|
190 EXPORT_C void CBtraceContext::GetFullThreadName(const TBtraceThreadId& aId, TDes& aFullName) const |
|
191 { |
|
192 TThread findKey(0, 0, KNullDesC8); |
|
193 findKey.iId = aId; |
|
194 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId)); |
|
195 if (pos >= 0) |
|
196 { |
|
197 const TThread& thread = iThreads[pos]; |
|
198 TProcess findKey(thread.iOwningProcess); |
|
199 TInt processPos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress)); |
|
200 __ASSERT_ALWAYS(processPos >= 0, Panic(EBtpPanicFailedToFindProcess)); |
|
201 aFullName.Zero(); |
|
202 aFullName.Append(ProcessName(iProcesses[processPos].iId)); |
|
203 aFullName.Append(_L("::")); |
|
204 aFullName.Append(thread.iName); |
|
205 } |
|
206 else |
|
207 { |
|
208 aFullName = KUnknown; |
|
209 } |
|
210 } |
|
211 |
|
212 EXPORT_C TThreadId CBtraceContext::ThreadId(const TBtraceThreadId& aId) const |
|
213 { |
|
214 TThread findKey(0, 0, KNullDesC8); |
|
215 findKey.iId = aId; |
|
216 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId)); |
|
217 __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadIdNotFound)); |
|
218 return iThreads[pos].iKernelId; |
|
219 } |
|
220 |
|
221 EXPORT_C const TDesC& CBtraceContext::ProcessName(const TBtraceProcessId& aId) const |
|
222 { |
|
223 TProcess findKey(0); |
|
224 findKey.iId = aId; |
|
225 TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesId)); |
|
226 __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicProcessNameNotFound)); |
|
227 return iProcesses[pos].iName; |
|
228 } |
|
229 |
|
230 EXPORT_C TInt CBtraceContext::WindowGroupId(const TBtraceWindowGroupId& aId) const |
|
231 { |
|
232 TWindowGroup findKey(0, 0, KNullDesC); |
|
233 findKey.iId = aId; |
|
234 TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesId)); |
|
235 __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound)); |
|
236 return iWindowGroups[pos].iWindowGroupId; |
|
237 } |
|
238 |
|
239 EXPORT_C const TDesC& CBtraceContext::WindowGroupName(const TBtraceWindowGroupId& aId) const |
|
240 { |
|
241 TWindowGroup findKey(0, 0, KNullDesC); |
|
242 findKey.iId = aId; |
|
243 TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesId)); |
|
244 __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound)); |
|
245 return iWindowGroups[pos].iName; |
|
246 } |
|
247 |
|
248 EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(TUint32 aNThreadAddress) const |
|
249 { |
|
250 TThread findKey(aNThreadAddress, 0, KNullDesC8); |
|
251 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress)); |
|
252 if (pos >= 0) |
|
253 { |
|
254 return &iThreads[pos].iId; |
|
255 } |
|
256 else |
|
257 { |
|
258 return NULL; |
|
259 } |
|
260 } |
|
261 |
|
262 EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(const TThreadId& aId) const |
|
263 { |
|
264 TThread findKey(0, 0, KNullDesC8); |
|
265 findKey.iKernelId = TUint(aId); |
|
266 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId)); |
|
267 if (pos >= 0) |
|
268 { |
|
269 return &iThreads[pos].iId; |
|
270 } |
|
271 else |
|
272 { |
|
273 return NULL; |
|
274 } |
|
275 } |
|
276 |
|
277 EXPORT_C const TBtraceWindowGroupId* CBtraceContext::FindWindowGroup(TInt aWServWgId) const |
|
278 { |
|
279 TWindowGroup findKey(aWServWgId); |
|
280 TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesWServId)); |
|
281 if (pos >= 0) |
|
282 { |
|
283 return &iWindowGroups[pos].iId; |
|
284 } |
|
285 else |
|
286 { |
|
287 return NULL; |
|
288 } |
|
289 } |
|
290 |
|
291 EXPORT_C void CBtraceContext::FindThreadsL(const TDesC& aPattern, RArray<TBtraceThreadId>& aThreads) const |
|
292 { |
|
293 TInt count = iThreads.Count(); |
|
294 while (--count >= 0) |
|
295 { |
|
296 const TThread& thread = iThreads[count]; |
|
297 TFullName name; |
|
298 GetFullThreadName(thread.iId, name); |
|
299 if (name.MatchF(aPattern) != KErrNotFound) |
|
300 { |
|
301 aThreads.AppendL(thread.iId); |
|
302 } |
|
303 } |
|
304 } |
|
305 |
|
306 EXPORT_C void CBtraceContext::FindWindowGroupsL(const TDesC& aPattern, RArray<TBtraceWindowGroupId>& aWindowGroups) const |
|
307 { |
|
308 TInt count = iWindowGroups.Count(); |
|
309 while (--count >= 0) |
|
310 { |
|
311 const TWindowGroup& windowGroup = iWindowGroups[count]; |
|
312 if (windowGroup.iName.MatchF(aPattern) != KErrNotFound) |
|
313 { |
|
314 aWindowGroups.AppendL(windowGroup.iId); |
|
315 } |
|
316 } |
|
317 } |
|
318 |
|
319 EXPORT_C void CBtraceContext::FindWindowGroupsByThreadName(const TDesC& aPattern, RArray<TBtraceWindowGroupId>& aWindowGroups) const |
|
320 { |
|
321 TInt count = iThreads.Count(); |
|
322 while (--count >= 0) |
|
323 { |
|
324 const TThread& thread = iThreads[count]; |
|
325 TFullName name; |
|
326 GetFullThreadName(thread.iId, name); |
|
327 if (name.MatchF(aPattern) != KErrNotFound) |
|
328 { |
|
329 for (TInt i = (iWindowGroups.Count() - 1); i >= 0; --i) |
|
330 { |
|
331 const TWindowGroup& thisWindowGroup = iWindowGroups[i]; |
|
332 if (thisWindowGroup.iThreadId.Id() == thread.iKernelId) |
|
333 { |
|
334 aWindowGroups.AppendL(thisWindowGroup.iId); |
|
335 } |
|
336 } |
|
337 } |
|
338 } |
|
339 } |
|
340 |
|
341 EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId) |
|
342 { |
|
343 NotifyThreadSeenL(aPattern, aObserver, aId, ENotificationOneShot); |
|
344 } |
|
345 |
|
346 EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) |
|
347 { |
|
348 iThreadSeenNotifs.AppendL(TThreadSeenNotif(aId, aPattern, aObserver, aPersistence)); |
|
349 } |
|
350 |
|
351 EXPORT_C void CBtraceContext::CancelNotifyThreadSeen(MBtraceContextObserver& aObserver) |
|
352 { |
|
353 for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i) |
|
354 { |
|
355 if (&iThreadSeenNotifs[i].iObserver == &aObserver) |
|
356 { |
|
357 iThreadSeenNotifs.Remove(i); |
|
358 } |
|
359 } |
|
360 } |
|
361 |
|
362 EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId) |
|
363 { |
|
364 return NotifyThreadGoneL(aPattern, aObserver, aId, ENotificationOneShot); |
|
365 } |
|
366 |
|
367 EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) |
|
368 { |
|
369 iThreadGoneNotifs.AppendL(TThreadGoneNotif(aId, aPattern, aObserver, aPersistence)); |
|
370 } |
|
371 |
|
372 EXPORT_C void CBtraceContext::CancelNotifyThreadGone(MBtraceContextObserver& aObserver) |
|
373 { |
|
374 for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i) |
|
375 { |
|
376 if (&iThreadGoneNotifs[i].iObserver == &aObserver) |
|
377 { |
|
378 iThreadGoneNotifs.Remove(i); |
|
379 } |
|
380 } |
|
381 } |
|
382 |
|
383 EXPORT_C void CBtraceContext::NotifyThreadExitL(const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) |
|
384 { |
|
385 iThreadExitNotifs.AppendL(TThreadExitNotif(aId, aPattern, aExitTypes, aReason, aCategory, aObserver, aPersistence)); |
|
386 } |
|
387 |
|
388 EXPORT_C void CBtraceContext::CancelNotifyThreadExit(MBtraceContextObserver& aObserver) |
|
389 { |
|
390 for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i) |
|
391 { |
|
392 if (&iThreadExitNotifs[i].iObserver == &aObserver) |
|
393 { |
|
394 iThreadExitNotifs.Remove(i); |
|
395 } |
|
396 } |
|
397 } |
|
398 |
|
399 EXPORT_C void CBtraceContext::NotifyWindowGroupSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) |
|
400 { |
|
401 iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EWindowGroupName, aObserver, aPersistence)); |
|
402 } |
|
403 |
|
404 EXPORT_C void CBtraceContext::NotifyWindowGroupSeenByThreadNameL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence) |
|
405 { |
|
406 iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EThreadName, aObserver, aPersistence)); |
|
407 } |
|
408 |
|
409 EXPORT_C void CBtraceContext::CancelNotifyWindowGroupSeen(MBtraceContextObserver& aObserver) |
|
410 { |
|
411 for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i) |
|
412 { |
|
413 if (&iWindowGroupSeenNotifs[i].iObserver == &aObserver) |
|
414 { |
|
415 iWindowGroupSeenNotifs.Remove(i); |
|
416 } |
|
417 } |
|
418 } |
|
419 |
|
420 CBtraceContext::CBtraceContext(CBtraceReader& aReader, TMode aMode) |
|
421 : iMode(aMode), iReader(aReader), iNextBtraceThreadId(KMaxTUint), iNextBtraceProcessId(KMaxTUint) |
|
422 { |
|
423 } |
|
424 |
|
425 void CBtraceContext::ConstructL() |
|
426 { |
|
427 iReader.AddObserverL(BTrace::EThreadIdentification, *this, CBtraceReader::EIncludeSynchronizationFrames); |
|
428 iReader.AddObserverL(KAmTraceCategory, *this); |
|
429 } |
|
430 |
|
431 TUint CBtraceContext::GetNextThreadId() |
|
432 { |
|
433 TUint id = iNextBtraceThreadId--; |
|
434 __ASSERT_ALWAYS(iNextBtraceThreadId > 0, Panic(EBtpPanicBtraceThreadIdOverflow)); |
|
435 return id; |
|
436 } |
|
437 |
|
438 TUint CBtraceContext::GetNextProcessId() |
|
439 { |
|
440 TUint id = iNextBtraceProcessId--; |
|
441 __ASSERT_ALWAYS(iNextBtraceProcessId > 0, Panic(EBtpPanicBtraceProcessIdOverflow)); |
|
442 return id; |
|
443 } |
|
444 |
|
445 TUint CBtraceContext::GetNextWindowGroupId() |
|
446 { |
|
447 TUint id = iNextBtraceWindowGroupId--; |
|
448 __ASSERT_ALWAYS(iNextBtraceWindowGroupId > 0, Panic(EBtpPanicBtraceWindowGroupIdOverflow)); |
|
449 return id; |
|
450 } |
|
451 |
|
452 void CBtraceContext::SeenL(const TThread& aThread, const TBtraceTickCount& aTickCount) |
|
453 { |
|
454 TFullName name; |
|
455 GetFullThreadName(aThread.iId, name); |
|
456 for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i) |
|
457 { |
|
458 const TThreadSeenNotif& thisNotif = iThreadSeenNotifs[i]; |
|
459 if (name.MatchF(thisNotif.iPattern) != KErrNotFound) |
|
460 { |
|
461 MBtraceContextObserver& observer = thisNotif.iObserver; |
|
462 TUint id = thisNotif.iId; |
|
463 if (thisNotif.iPersistence == ENotificationOneShot) |
|
464 { |
|
465 iThreadSeenNotifs.Remove(i); |
|
466 } |
|
467 observer.HandleThreadSeenL(aTickCount, aThread.iId, id); |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 void CBtraceContext::GoneL(const TThread& aThread, const TBtraceTickCount& aTickCount) |
|
473 { |
|
474 TFullName name; |
|
475 GetFullThreadName(aThread.iId, name); |
|
476 for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i) |
|
477 { |
|
478 const TThreadGoneNotif& notif = iThreadGoneNotifs[i]; |
|
479 if (name.MatchF(notif.iPattern) != KErrNotFound) |
|
480 { |
|
481 MBtraceContextObserver& observer = notif.iObserver; |
|
482 TUint id = notif.iId; |
|
483 if (notif.iPersistence == ENotificationOneShot) |
|
484 { |
|
485 iThreadGoneNotifs.Remove(i); |
|
486 } |
|
487 observer.HandleThreadGoneL(aTickCount, aThread.iId, id); |
|
488 } |
|
489 } |
|
490 } |
|
491 |
|
492 void CBtraceContext::ExitedL(const TThread& aThread, TExitType aExitType, TInt aReason, const TDesC& aCategory, const TBtraceTickCount& aTickCount) |
|
493 { |
|
494 TFullName name; |
|
495 GetFullThreadName(aThread.iId, name); |
|
496 for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i) |
|
497 { |
|
498 const TThreadExitNotif& notif = iThreadExitNotifs[i]; |
|
499 if (notif.Matches(name, aExitType, aReason, aCategory)) |
|
500 { |
|
501 MBtraceContextObserver& observer = notif.iObserver; |
|
502 TUint id = notif.iId; |
|
503 if (notif.iPersistence == ENotificationOneShot) |
|
504 { |
|
505 iThreadExitNotifs.Remove(i); |
|
506 } |
|
507 observer.HandleThreadExitL(aTickCount, aThread.iId, aExitType, aReason, aCategory, id); |
|
508 } |
|
509 } |
|
510 } |
|
511 |
|
512 void CBtraceContext::SeenL(const TWindowGroup& aWindowGroup, const TBtraceTickCount& aTickCount) |
|
513 { |
|
514 for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i) |
|
515 { |
|
516 const TWindowGroupSeenNotif& thisNotif = iWindowGroupSeenNotifs[i]; |
|
517 if (thisNotif.iPatternType == TWindowGroupSeenNotif::EWindowGroupName) |
|
518 { |
|
519 if (aWindowGroup.iName.MatchF(thisNotif.iPattern) != KErrNotFound) |
|
520 { |
|
521 MBtraceContextObserver& observer = thisNotif.iObserver; |
|
522 TUint id = thisNotif.iId; |
|
523 if (thisNotif.iPersistence == ENotificationOneShot) |
|
524 { |
|
525 iWindowGroupSeenNotifs.Remove(i); |
|
526 } |
|
527 observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id); |
|
528 } |
|
529 } |
|
530 else |
|
531 { |
|
532 TThread findKey(0, 0, KNullDesC8); |
|
533 findKey.iKernelId = TUint(aWindowGroup.iThreadId); |
|
534 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId)); |
|
535 if (pos >= 0) |
|
536 { |
|
537 TFullName threadName; |
|
538 GetFullThreadName(iThreads[pos].iId, threadName); |
|
539 if (threadName.MatchF(thisNotif.iPattern)) |
|
540 { |
|
541 MBtraceContextObserver& observer = thisNotif.iObserver; |
|
542 TUint id = thisNotif.iId; |
|
543 if (thisNotif.iPersistence == ENotificationOneShot) |
|
544 { |
|
545 iWindowGroupSeenNotifs.Remove(i); |
|
546 } |
|
547 observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id); |
|
548 } |
|
549 } |
|
550 } |
|
551 } |
|
552 } |
|
553 |
|
554 void CBtraceContext::HandleBtraceFrameL(const TBtraceFrame& aFrame) |
|
555 { |
|
556 const TUint8* data = aFrame.iData.Ptr(); |
|
557 |
|
558 if (aFrame.iCategory == BTrace::EThreadIdentification) |
|
559 { |
|
560 switch (aFrame.iSubCategory) |
|
561 { |
|
562 case BTrace::EThreadCreate: |
|
563 { |
|
564 TUint32 nthreadAddress = *(TUint32*)data; |
|
565 TUint32 dprocessAddress = *((TUint32*)data + 1); |
|
566 TPtrC8 name(aFrame.iData.Mid(8)); |
|
567 |
|
568 #ifdef BTRACE_CONTEXT_DEBUG |
|
569 TFullName name16; |
|
570 name16.Copy(name); |
|
571 RDebug::Print(_L("BTrace::EThreadCreate: 0x%08x \"%S\""), nthreadAddress, &name16); |
|
572 #endif |
|
573 |
|
574 TThread thread(nthreadAddress, dprocessAddress, name); |
|
575 AppendL(thread, aFrame.iTickCount); |
|
576 break; |
|
577 } |
|
578 case BTrace::EThreadDestroy: |
|
579 { |
|
580 TUint32 nthreadAddress = *(TUint32*)data; |
|
581 TThread findKey(nthreadAddress, 0, KNullDesC8); |
|
582 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress)); |
|
583 if (pos >= 0) |
|
584 { |
|
585 #ifdef BTRACE_CONTEXT_DEBUG |
|
586 RDebug::Print(_L("BTrace::EThreadDestroy: %u %u 0x%08x \"%S\""), iThreads[pos].iId.Value(), iThreads[pos].iKernelId, nthreadAddress, &iThreads[pos].iName); |
|
587 #endif |
|
588 GoneL(iThreads[pos], aFrame.iTickCount); |
|
589 RemoveThread(pos); |
|
590 } |
|
591 else |
|
592 { |
|
593 // This can happen if a thread is destroyed after the btrace buffer has been enabled but before the BTrace::EThreadIdentification category has been enabled. |
|
594 iReader.Log(_L("Destroyed thread 0x%08x not found\r\n"), nthreadAddress); |
|
595 } |
|
596 break; |
|
597 } |
|
598 case BTrace::EThreadName: |
|
599 { |
|
600 TUint32 nthreadAddress = *(TUint32*)data; |
|
601 TUint32 dprocessAddress = *((TUint32*)data + 1); |
|
602 TPtrC8 name(aFrame.iData.Mid(8)); |
|
603 |
|
604 #ifdef BTRACE_CONTEXT_DEBUG |
|
605 TFullName name16; |
|
606 name16.Copy(name); |
|
607 RDebug::Print(_L("BTrace::EThreadName: 0x%08x \"%S\""), nthreadAddress, &name16); |
|
608 #endif |
|
609 TThread findKey(nthreadAddress, 0, KNullDesC8); |
|
610 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress)); |
|
611 if (pos >= 0) |
|
612 { |
|
613 iThreads[pos].iName.Copy(name); |
|
614 SeenL(iThreads[pos], aFrame.iTickCount); |
|
615 } |
|
616 else |
|
617 { |
|
618 TThread thread(nthreadAddress, dprocessAddress, name); |
|
619 AppendL(thread, aFrame.iTickCount); |
|
620 } |
|
621 break; |
|
622 } |
|
623 case BTrace::EProcessCreate: |
|
624 { |
|
625 TUint32 dprocessAddress = *(TUint32*)data; |
|
626 #ifdef BTRACE_CONTEXT_DEBUG |
|
627 RDebug::Print(_L("BTrace::EProcessCreate: 0x%08x"), dprocessAddress); |
|
628 #endif |
|
629 TProcess process(dprocessAddress); |
|
630 AppendL(process, aFrame.iTickCount); |
|
631 break; |
|
632 } |
|
633 case BTrace::EProcessName: |
|
634 { |
|
635 TUint32 dprocessAddress = *((TUint32*)data + 1); |
|
636 TPtrC8 name(aFrame.iData.Mid(8)); |
|
637 |
|
638 #ifdef BTRACE_CONTEXT_DEBUG |
|
639 TFullName name16; |
|
640 name16.Copy(name); |
|
641 RDebug::Print(_L("BTrace::EProcessName: 0x%08x \"%S\""), dprocessAddress, &name16); |
|
642 #endif |
|
643 TProcess findKey(dprocessAddress); |
|
644 TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress)); |
|
645 if (pos >= 0) |
|
646 { |
|
647 iProcesses[pos].iName.Copy(name); |
|
648 SeenAllThreadsL(iProcesses[pos], aFrame.iTickCount); |
|
649 } |
|
650 else |
|
651 { |
|
652 TProcess process(dprocessAddress, name); |
|
653 AppendL(process, aFrame.iTickCount); |
|
654 } |
|
655 break; |
|
656 } |
|
657 case BTrace::EThreadId: |
|
658 { |
|
659 TUint32 nthreadAddress = *(TUint32*)data; |
|
660 TUint32 threadId = *((TUint32*)data + 2); |
|
661 TThread findKey(nthreadAddress, 0, KNullDesC8); |
|
662 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress)); |
|
663 __ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadNotFoundForId)); |
|
664 iThreads[pos].iKernelId = threadId; |
|
665 #ifdef BTRACE_CONTEXT_DEBUG |
|
666 RDebug::Print(_L("BTrace::EThreadId: %u 0x%08x \"%S\""), threadId, nthreadAddress, &iThreads[pos].iName); |
|
667 #endif |
|
668 break; |
|
669 } |
|
670 default: |
|
671 { |
|
672 // Ignore anything we don't know about. |
|
673 break; |
|
674 } |
|
675 } |
|
676 } |
|
677 else if (aFrame.iCategory == KAmTraceCategory) |
|
678 { |
|
679 if (aFrame.iSubCategory == EAmTraceSubCategoryWindowGroupName) |
|
680 { |
|
681 TUint wgId = *(TUint32*)data; |
|
682 TInt kernelThreadId = *((TInt32*)data + 1); |
|
683 TPtrC8 nameData = aFrame.iData.Mid(8); |
|
684 TPtrC name((TUint16*)nameData.Ptr(), nameData.Length() / 2); |
|
685 TWindowGroup findKey(wgId); |
|
686 TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesWServId)); |
|
687 if (pos >= 0) |
|
688 { |
|
689 TWindowGroup& windowGroup = iWindowGroups[pos]; |
|
690 windowGroup.iName = name; |
|
691 SeenL(windowGroup, aFrame.iTickCount); |
|
692 } |
|
693 else |
|
694 { |
|
695 TWindowGroup windowGroup(wgId, TThreadId(kernelThreadId), name); |
|
696 windowGroup.iId.Set(GetNextWindowGroupId()); |
|
697 iWindowGroups.AppendL(windowGroup); |
|
698 SeenL(windowGroup, aFrame.iTickCount); |
|
699 } |
|
700 } |
|
701 else if ((aFrame.iSubCategory >= EAmTraceSubCategoryThreadKilled) && (aFrame.iSubCategory <= EAmTraceSubCategoryThreadPanicked)) |
|
702 { |
|
703 TUint id = *(TUint32*)data; |
|
704 TInt reason = *((TInt32*)data + 1); |
|
705 TThread findKey(0, 0, KNullDesC8); |
|
706 findKey.iKernelId = id; |
|
707 TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId)); |
|
708 if (pos >= 0) |
|
709 { |
|
710 const TThread& thread = iThreads[pos]; |
|
711 switch (aFrame.iSubCategory) |
|
712 { |
|
713 case EAmTraceSubCategoryThreadKilled: |
|
714 { |
|
715 ExitedL(thread, EExitKill, reason, KNullDesC, aFrame.iTickCount); |
|
716 break; |
|
717 } |
|
718 case EAmTraceSubCategoryThreadTerminated: |
|
719 { |
|
720 ExitedL(thread, EExitTerminate, reason, KNullDesC, aFrame.iTickCount); |
|
721 break; |
|
722 } |
|
723 case EAmTraceSubCategoryThreadPanicked: |
|
724 { |
|
725 TPtrC8 narrowCategory(aFrame.iData.Mid(sizeof(TInt) * 2)); |
|
726 TExitCategoryName category; |
|
727 category.Copy(narrowCategory); |
|
728 ExitedL(thread, EExitPanic, reason, category, aFrame.iTickCount); |
|
729 break; |
|
730 } |
|
731 default: |
|
732 { |
|
733 // Ignore anything we don't know about. |
|
734 break; |
|
735 } |
|
736 } |
|
737 } |
|
738 } |
|
739 } |
|
740 } |
|
741 |
|
742 void CBtraceContext::AppendL(const TThread& aThread, const TBtraceTickCount& aTickCount) |
|
743 { |
|
744 iThreads.AppendL(aThread); |
|
745 TThread& thread = iThreads[iThreads.Count() - 1]; |
|
746 thread.iId.Set(GetNextThreadId()); |
|
747 |
|
748 // Increment the reference count of the owning process. |
|
749 TProcess findKey(thread.iOwningProcess); |
|
750 TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress)); |
|
751 if (pos >= 0) |
|
752 { |
|
753 ++(iProcesses[pos].iReferenceCount); |
|
754 } |
|
755 |
|
756 SeenL(thread, aTickCount); |
|
757 } |
|
758 |
|
759 void CBtraceContext::AppendL(const TProcess& aProcess, const TBtraceTickCount& aTickCount) |
|
760 { |
|
761 iProcesses.AppendL(aProcess); |
|
762 TProcess& process = iProcesses[iProcesses.Count() - 1]; |
|
763 process.iId.Set(GetNextProcessId()); |
|
764 |
|
765 // Set the reference count for this process. |
|
766 for (TInt i = (iThreads.Count() - 1); i >= 0; --i) |
|
767 { |
|
768 if (iThreads[i].iOwningProcess == process.iDProcessAddress) |
|
769 { |
|
770 ++process.iReferenceCount; |
|
771 } |
|
772 } |
|
773 |
|
774 SeenAllThreadsL(process, aTickCount); |
|
775 } |
|
776 |
|
777 void CBtraceContext::RemoveThread(TInt aPosition) |
|
778 { |
|
779 TProcess findKey(iThreads[aPosition].iOwningProcess); |
|
780 TInt processPos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress)); |
|
781 if (processPos >= 0) |
|
782 { |
|
783 if (--(iProcesses[processPos].iReferenceCount) == 0) |
|
784 { |
|
785 iProcesses.Remove(processPos); |
|
786 } |
|
787 } |
|
788 iThreads.Remove(aPosition); |
|
789 } |
|
790 |
|
791 void CBtraceContext::SeenAllThreadsL(const TProcess& aProcess, const TBtraceTickCount& aTickCount) |
|
792 { |
|
793 // Call SeenL for each thread belonging to this process because. This is called when a process |
|
794 // is created or altered because this change may allow a TThreadSeenNotif to be completed. |
|
795 const TInt numThreads = iThreads.Count(); |
|
796 for (TInt i = 0; i < numThreads; ++i) |
|
797 { |
|
798 const TThread& thread = iThreads[i]; |
|
799 if (thread.iOwningProcess == aProcess.iDProcessAddress) |
|
800 { |
|
801 SeenL(thread, aTickCount); |
|
802 } |
|
803 } |
|
804 } |
|
805 |
|
806 void CBtraceContext::BtraceBufferHasBeenReset() |
|
807 { |
|
808 iThreads.Close(); |
|
809 iProcesses.Close(); |
|
810 } |
|
811 |
|
812 CBtraceContext::TThread::TThread(TUint32 aNThreadAddress, TUint32 aOwningProcess, const TDesC8& aName) |
|
813 : iNThreadAddress(aNThreadAddress), iOwningProcess(aOwningProcess), iKernelId(0) |
|
814 { |
|
815 iName.Copy(aName); |
|
816 } |
|
817 |
|
818 CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress) |
|
819 : iDProcessAddress(aDProcessAddress), iReferenceCount(0) |
|
820 { |
|
821 } |
|
822 |
|
823 CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress, const TDesC8& aName) |
|
824 : iDProcessAddress(aDProcessAddress), iReferenceCount(0) |
|
825 { |
|
826 iName.Copy(aName); |
|
827 } |
|
828 |
|
829 CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId) |
|
830 : iWindowGroupId(aWindowGroupId), iThreadId(0) |
|
831 { |
|
832 } |
|
833 |
|
834 CBtraceContext::TWindowGroup::TWindowGroup(const TDesC& aName) |
|
835 : iWindowGroupId(0), iThreadId(0), iName(aName) |
|
836 { |
|
837 } |
|
838 |
|
839 CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId, TThreadId aThreadId, const TDesC& aName) |
|
840 : iWindowGroupId(aWindowGroupId), iThreadId(aThreadId), iName(aName) |
|
841 { |
|
842 } |
|
843 |
|
844 CBtraceContext::TThreadSeenNotif::TThreadSeenNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) |
|
845 : iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence) |
|
846 { |
|
847 } |
|
848 |
|
849 CBtraceContext::TThreadGoneNotif::TThreadGoneNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) |
|
850 : iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence) |
|
851 { |
|
852 } |
|
853 |
|
854 CBtraceContext::TThreadExitNotif::TThreadExitNotif(TUint aId, const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) |
|
855 : iId(aId), iPattern(aPattern), iExitTypes(aExitTypes), iReason(aReason), iCategory(aCategory), iObserver(aObserver), iPersistence(aPersistence) |
|
856 { |
|
857 } |
|
858 |
|
859 CBtraceContext::TWindowGroupSeenNotif::TWindowGroupSeenNotif(TUint aId, const TDesC& aPattern, TPatternType aPatternType, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence) |
|
860 : iId(aId), iPattern(aPattern), iPatternType(aPatternType), iObserver(aObserver), iPersistence(aPersistence) |
|
861 { |
|
862 } |
|
863 |
|
864 TBool CBtraceContext::TThreadExitNotif::Matches(const TDesC& aThreadName, TExitType aExitType, TInt aReason, const TDesC& aCategory) const |
|
865 { |
|
866 if (aThreadName.MatchF(iPattern) != KErrNotFound) |
|
867 { |
|
868 if (MatchesType(aExitType)) |
|
869 { |
|
870 if ((iReason == NULL) || (*iReason == aReason)) |
|
871 { |
|
872 if ((aExitType != EExitPanic) || ((iCategory == NULL) || (*iCategory == aCategory))) |
|
873 { |
|
874 return ETrue; |
|
875 } |
|
876 } |
|
877 } |
|
878 } |
|
879 return EFalse; |
|
880 } |
|
881 |
|
882 TBool CBtraceContext::TThreadExitNotif::MatchesType(TExitType aExitType) const |
|
883 { |
|
884 switch (aExitType) |
|
885 { |
|
886 case EExitKill: |
|
887 return (iExitTypes & EKill); |
|
888 case EExitTerminate: |
|
889 return (iExitTypes & ETerminate); |
|
890 case EExitPanic: |
|
891 return (iExitTypes & EPanic); |
|
892 default: |
|
893 ASSERT(EFalse); |
|
894 return EFalse; |
|
895 } |
|
896 } |