tools/profiler/GeckoTaskTracer.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:9028e5c7d8ff
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "GeckoTaskTracer.h"
8 #include "GeckoTaskTracerImpl.h"
9
10 #include "mozilla/StaticMutex.h"
11 #include "mozilla/ThreadLocal.h"
12 #include "mozilla/unused.h"
13
14 #include "nsClassHashtable.h"
15 #include "nsThreadUtils.h"
16
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #if defined(__GLIBC__)
22 // glibc doesn't implement gettid(2).
23 #include <sys/syscall.h>
24 static pid_t gettid()
25 {
26 return (pid_t) syscall(SYS_gettid);
27 }
28 #endif
29
30 #define MAX_USER_LABEL_LEN 512
31
32 namespace mozilla {
33 namespace tasktracer {
34
35 static mozilla::ThreadLocal<TraceInfo*> sTraceInfoTLS;
36 static StaticMutex sMutex;
37 static nsClassHashtable<nsUint32HashKey, TraceInfo>* sTraceInfos = nullptr;
38
39 namespace {
40
41 static TraceInfo*
42 AllocTraceInfo(int aTid)
43 {
44 StaticMutexAutoLock lock(sMutex);
45
46 sTraceInfos->Put(aTid, new TraceInfo(aTid));
47 return sTraceInfos->Get(aTid);
48 }
49
50 static void
51 FreeTraceInfo(int aTid)
52 {
53 StaticMutexAutoLock lock(sMutex);
54
55 sTraceInfos->Remove(aTid);
56 }
57
58 static bool
59 IsInitialized()
60 {
61 return sTraceInfoTLS.initialized();
62 }
63
64 static void
65 SaveCurTraceInfo()
66 {
67 TraceInfo* info = GetOrCreateTraceInfo();
68 NS_ENSURE_TRUE_VOID(info);
69
70 info->mSavedCurTraceSourceId = info->mCurTraceSourceId;
71 info->mSavedCurTraceSourceType = info->mCurTraceSourceType;
72 info->mSavedCurTaskId = info->mCurTaskId;
73 }
74
75 static void
76 RestoreCurTraceInfo()
77 {
78 TraceInfo* info = GetOrCreateTraceInfo();
79 NS_ENSURE_TRUE_VOID(info);
80
81 info->mCurTraceSourceId = info->mSavedCurTraceSourceId;
82 info->mCurTraceSourceType = info->mSavedCurTraceSourceType;
83 info->mCurTaskId = info->mSavedCurTaskId;
84 }
85
86 static void
87 CreateSourceEvent(SourceEventType aType)
88 {
89 NS_ENSURE_TRUE_VOID(IsInitialized());
90
91 // Save the currently traced source event info.
92 SaveCurTraceInfo();
93
94 // Create a new unique task id.
95 uint64_t newId = GenNewUniqueTaskId();
96 TraceInfo* info = GetOrCreateTraceInfo();
97 info->mCurTraceSourceId = newId;
98 info->mCurTraceSourceType = aType;
99 info->mCurTaskId = newId;
100
101 // Log a fake dispatch and start for this source event.
102 LogDispatch(newId, newId,newId, aType);
103 LogBegin(newId, newId);
104 }
105
106 static void
107 DestroySourceEvent()
108 {
109 NS_ENSURE_TRUE_VOID(IsInitialized());
110
111 // Log a fake end for this source event.
112 TraceInfo* info = GetOrCreateTraceInfo();
113 LogEnd(info->mCurTraceSourceId, info->mCurTraceSourceId);
114
115 // Restore the previously saved source event info.
116 RestoreCurTraceInfo();
117 }
118
119 } // namespace anonymous
120
121 void
122 InitTaskTracer()
123 {
124 MOZ_ASSERT(!sTraceInfos);
125
126 sTraceInfos = new nsClassHashtable<nsUint32HashKey, TraceInfo>();
127
128 if (!sTraceInfoTLS.initialized()) {
129 unused << sTraceInfoTLS.init();
130 }
131 }
132
133 void
134 ShutdownTaskTracer()
135 {
136 delete sTraceInfos;
137 sTraceInfos = nullptr;
138 }
139
140 TraceInfo*
141 GetOrCreateTraceInfo()
142 {
143 NS_ENSURE_TRUE(IsInitialized(), nullptr);
144
145 TraceInfo* info = sTraceInfoTLS.get();
146 if (!info) {
147 info = AllocTraceInfo(gettid());
148 sTraceInfoTLS.set(info);
149 }
150
151 return info;
152 }
153
154 uint64_t
155 GenNewUniqueTaskId()
156 {
157 TraceInfo* info = GetOrCreateTraceInfo();
158 NS_ENSURE_TRUE(info, 0);
159
160 pid_t tid = gettid();
161 uint64_t taskid = ((uint64_t)tid << 32) | ++info->mLastUniqueTaskId;
162 return taskid;
163 }
164
165 AutoSaveCurTraceInfo::AutoSaveCurTraceInfo()
166 {
167 SaveCurTraceInfo();
168 }
169
170 AutoSaveCurTraceInfo::~AutoSaveCurTraceInfo()
171 {
172 RestoreCurTraceInfo();
173 }
174
175 void
176 SetCurTraceInfo(uint64_t aSourceEventId, uint64_t aParentTaskId,
177 SourceEventType aSourceEventType)
178 {
179 TraceInfo* info = GetOrCreateTraceInfo();
180 NS_ENSURE_TRUE_VOID(info);
181
182 info->mCurTraceSourceId = aSourceEventId;
183 info->mCurTaskId = aParentTaskId;
184 info->mCurTraceSourceType = aSourceEventType;
185 }
186
187 void
188 GetCurTraceInfo(uint64_t* aOutSourceEventId, uint64_t* aOutParentTaskId,
189 SourceEventType* aOutSourceEventType)
190 {
191 TraceInfo* info = GetOrCreateTraceInfo();
192 NS_ENSURE_TRUE_VOID(info);
193
194 *aOutSourceEventId = info->mCurTraceSourceId;
195 *aOutParentTaskId = info->mCurTaskId;
196 *aOutSourceEventType = info->mCurTraceSourceType;
197 }
198
199 void
200 LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
201 SourceEventType aSourceEventType)
202 {
203 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
204
205 // Log format:
206 // [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId]
207 }
208
209 void
210 LogBegin(uint64_t aTaskId, uint64_t aSourceEventId)
211 {
212 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
213
214 // Log format:
215 // [1 taskId beginTime processId threadId]
216 }
217
218 void
219 LogEnd(uint64_t aTaskId, uint64_t aSourceEventId)
220 {
221 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
222
223 // Log format:
224 // [2 taskId endTime]
225 }
226
227 void
228 LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId, int* aVptr)
229 {
230 NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
231
232 // Log format:
233 // [4 taskId address]
234 }
235
236 void
237 FreeTraceInfo()
238 {
239 NS_ENSURE_TRUE_VOID(IsInitialized());
240
241 FreeTraceInfo(gettid());
242 }
243
244 AutoSourceEvent::AutoSourceEvent(SourceEventType aType)
245 {
246 CreateSourceEvent(aType);
247 }
248
249 AutoSourceEvent::~AutoSourceEvent()
250 {
251 DestroySourceEvent();
252 }
253
254 void AddLabel(const char* aFormat, ...)
255 {
256 NS_ENSURE_TRUE_VOID(IsInitialized());
257
258 va_list args;
259 va_start(args, aFormat);
260 char buffer[MAX_USER_LABEL_LEN] = {0};
261 vsnprintf(buffer, MAX_USER_LABEL_LEN, aFormat, args);
262 va_end(args);
263
264 // Log format:
265 // [3 taskId "label"]
266 }
267
268 } // namespace tasktracer
269 } // namespace mozilla

mercurial