1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/common/track_tracker.h"
18
19 #include "src/trace_processor/importers/common/args_tracker.h"
20 #include "src/trace_processor/importers/common/process_tracker.h"
21
22 namespace perfetto {
23 namespace trace_processor {
24
TrackTracker(TraceProcessorContext * context)25 TrackTracker::TrackTracker(TraceProcessorContext* context)
26 : source_key_(context->storage->InternString("source")),
27 source_id_key_(context->storage->InternString("source_id")),
28 source_id_is_process_scoped_key_(
29 context->storage->InternString("source_id_is_process_scoped")),
30 source_scope_key_(context->storage->InternString("source_scope")),
31 category_key_(context->storage->InternString("category")),
32 fuchsia_source_(context->storage->InternString("fuchsia")),
33 chrome_source_(context->storage->InternString("chrome")),
34 context_(context) {}
35
InternThreadTrack(UniqueTid utid)36 TrackId TrackTracker::InternThreadTrack(UniqueTid utid) {
37 auto it = thread_tracks_.find(utid);
38 if (it != thread_tracks_.end())
39 return it->second;
40
41 tables::ThreadTrackTable::Row row;
42 row.utid = utid;
43 auto id = context_->storage->mutable_thread_track_table()->Insert(row).id;
44 thread_tracks_[utid] = id;
45 return id;
46 }
47
InternProcessTrack(UniquePid upid)48 TrackId TrackTracker::InternProcessTrack(UniquePid upid) {
49 auto it = process_tracks_.find(upid);
50 if (it != process_tracks_.end())
51 return it->second;
52
53 tables::ProcessTrackTable::Row row;
54 row.upid = upid;
55 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
56 process_tracks_[upid] = id;
57 return id;
58 }
59
InternFuchsiaAsyncTrack(StringId name,uint32_t upid,int64_t correlation_id)60 TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
61 uint32_t upid,
62 int64_t correlation_id) {
63 return InternLegacyChromeAsyncTrack(name, upid, correlation_id, false,
64 StringId());
65 }
66
InternCpuTrack(StringId name,uint32_t cpu)67 TrackId TrackTracker::InternCpuTrack(StringId name, uint32_t cpu) {
68 auto it = cpu_tracks_.find(std::make_pair(name, cpu));
69 if (it != cpu_tracks_.end()) {
70 return it->second;
71 }
72
73 tables::TrackTable::Row row(name);
74 auto id = context_->storage->mutable_track_table()->Insert(row).id;
75 cpu_tracks_[std::make_pair(name, cpu)] = id;
76
77 return id;
78 }
79
InternGpuTrack(const tables::GpuTrackTable::Row & row)80 TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
81 GpuTrackTuple tuple{row.name, row.scope, row.context_id.value_or(0)};
82
83 auto it = gpu_tracks_.find(tuple);
84 if (it != gpu_tracks_.end())
85 return it->second;
86
87 auto id = context_->storage->mutable_gpu_track_table()->Insert(row).id;
88 gpu_tracks_[tuple] = id;
89 return id;
90 }
91
InternLegacyChromeAsyncTrack(StringId name,uint32_t upid,int64_t source_id,bool source_id_is_process_scoped,StringId source_scope)92 TrackId TrackTracker::InternLegacyChromeAsyncTrack(
93 StringId name,
94 uint32_t upid,
95 int64_t source_id,
96 bool source_id_is_process_scoped,
97 StringId source_scope) {
98 ChromeTrackTuple tuple;
99 if (source_id_is_process_scoped)
100 tuple.upid = upid;
101 tuple.source_id = source_id;
102 tuple.source_scope = source_scope;
103
104 auto it = chrome_tracks_.find(tuple);
105 if (it != chrome_tracks_.end()) {
106 if (name != kNullStringId) {
107 // The track may have been created for an end event without name. In that
108 // case, update it with this event's name.
109 auto* tracks = context_->storage->mutable_track_table();
110 uint32_t track_row = *tracks->id().IndexOf(it->second);
111 if (tracks->name()[track_row] == kNullStringId)
112 tracks->mutable_name()->Set(track_row, name);
113 }
114 return it->second;
115 }
116
117 // Legacy async tracks are always drawn in the context of a process, even if
118 // the ID's scope is global.
119 tables::ProcessTrackTable::Row track(name);
120 track.upid = upid;
121 TrackId id =
122 context_->storage->mutable_process_track_table()->Insert(track).id;
123 chrome_tracks_[tuple] = id;
124
125 context_->args_tracker->AddArgsTo(id)
126 .AddArg(source_key_, Variadic::String(chrome_source_))
127 .AddArg(source_id_key_, Variadic::Integer(source_id))
128 .AddArg(source_id_is_process_scoped_key_,
129 Variadic::Boolean(source_id_is_process_scoped))
130 .AddArg(source_scope_key_, Variadic::String(source_scope));
131
132 return id;
133 }
134
CreateGlobalAsyncTrack(StringId name,StringId source)135 TrackId TrackTracker::CreateGlobalAsyncTrack(StringId name, StringId source) {
136 tables::TrackTable::Row row(name);
137 auto id = context_->storage->mutable_track_table()->Insert(row).id;
138 if (!source.is_null()) {
139 context_->args_tracker->AddArgsTo(id).AddArg(source_key_,
140 Variadic::String(source));
141 }
142 return id;
143 }
144
CreateProcessAsyncTrack(StringId name,UniquePid upid,StringId source)145 TrackId TrackTracker::CreateProcessAsyncTrack(StringId name,
146 UniquePid upid,
147 StringId source) {
148 tables::ProcessTrackTable::Row row(name);
149 row.upid = upid;
150 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
151 if (!source.is_null()) {
152 context_->args_tracker->AddArgsTo(id).AddArg(source_key_,
153 Variadic::String(source));
154 }
155 return id;
156 }
157
InternLegacyChromeProcessInstantTrack(UniquePid upid)158 TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
159 auto it = chrome_process_instant_tracks_.find(upid);
160 if (it != chrome_process_instant_tracks_.end())
161 return it->second;
162
163 tables::ProcessTrackTable::Row row;
164 row.upid = upid;
165 auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
166 chrome_process_instant_tracks_[upid] = id;
167
168 context_->args_tracker->AddArgsTo(id).AddArg(
169 source_key_, Variadic::String(chrome_source_));
170
171 return id;
172 }
173
GetOrCreateLegacyChromeGlobalInstantTrack()174 TrackId TrackTracker::GetOrCreateLegacyChromeGlobalInstantTrack() {
175 if (!chrome_global_instant_track_id_) {
176 chrome_global_instant_track_id_ =
177 context_->storage->mutable_track_table()->Insert({}).id;
178
179 context_->args_tracker->AddArgsTo(*chrome_global_instant_track_id_)
180 .AddArg(source_key_, Variadic::String(chrome_source_));
181 }
182 return *chrome_global_instant_track_id_;
183 }
184
GetOrCreateTriggerTrack()185 TrackId TrackTracker::GetOrCreateTriggerTrack() {
186 if (trigger_track_id_) {
187 return *trigger_track_id_;
188 }
189 tables::TrackTable::Row row;
190 row.name = context_->storage->InternString("Trace Triggers");
191 trigger_track_id_ = context_->storage->mutable_track_table()->Insert(row).id;
192 return *trigger_track_id_;
193 }
194
InternGlobalCounterTrack(StringId name,StringId unit,StringId description)195 TrackId TrackTracker::InternGlobalCounterTrack(StringId name,
196 StringId unit,
197 StringId description) {
198 auto it = global_counter_tracks_by_name_.find(name);
199 if (it != global_counter_tracks_by_name_.end()) {
200 return it->second;
201 }
202
203 tables::CounterTrackTable::Row row(name);
204 row.unit = unit;
205 row.description = description;
206 TrackId track =
207 context_->storage->mutable_counter_track_table()->Insert(row).id;
208 global_counter_tracks_by_name_[name] = track;
209 return track;
210 }
211
InternCpuCounterTrack(StringId name,uint32_t cpu)212 TrackId TrackTracker::InternCpuCounterTrack(StringId name, uint32_t cpu) {
213 auto it = cpu_counter_tracks_.find(std::make_pair(name, cpu));
214 if (it != cpu_counter_tracks_.end()) {
215 return it->second;
216 }
217
218 tables::CpuCounterTrackTable::Row row(name);
219 row.cpu = cpu;
220
221 TrackId track =
222 context_->storage->mutable_cpu_counter_track_table()->Insert(row).id;
223 cpu_counter_tracks_[std::make_pair(name, cpu)] = track;
224 return track;
225 }
226
InternThreadCounterTrack(StringId name,UniqueTid utid)227 TrackId TrackTracker::InternThreadCounterTrack(StringId name, UniqueTid utid) {
228 auto it = utid_counter_tracks_.find(std::make_pair(name, utid));
229 if (it != utid_counter_tracks_.end()) {
230 return it->second;
231 }
232
233 tables::ThreadCounterTrackTable::Row row(name);
234 row.utid = utid;
235
236 TrackId track =
237 context_->storage->mutable_thread_counter_track_table()->Insert(row).id;
238 utid_counter_tracks_[std::make_pair(name, utid)] = track;
239 return track;
240 }
241
InternProcessCounterTrack(StringId name,UniquePid upid,StringId unit,StringId description)242 TrackId TrackTracker::InternProcessCounterTrack(StringId name,
243 UniquePid upid,
244 StringId unit,
245 StringId description) {
246 auto it = upid_counter_tracks_.find(std::make_pair(name, upid));
247 if (it != upid_counter_tracks_.end()) {
248 return it->second;
249 }
250
251 tables::ProcessCounterTrackTable::Row row(name);
252 row.upid = upid;
253 row.unit = unit;
254 row.description = description;
255
256 TrackId track =
257 context_->storage->mutable_process_counter_track_table()->Insert(row).id;
258 upid_counter_tracks_[std::make_pair(name, upid)] = track;
259 return track;
260 }
261
InternIrqCounterTrack(StringId name,int32_t irq)262 TrackId TrackTracker::InternIrqCounterTrack(StringId name, int32_t irq) {
263 auto it = irq_counter_tracks_.find(std::make_pair(name, irq));
264 if (it != irq_counter_tracks_.end()) {
265 return it->second;
266 }
267
268 tables::IrqCounterTrackTable::Row row(name);
269 row.irq = irq;
270
271 TrackId track =
272 context_->storage->mutable_irq_counter_track_table()->Insert(row).id;
273 irq_counter_tracks_[std::make_pair(name, irq)] = track;
274 return track;
275 }
276
InternSoftirqCounterTrack(StringId name,int32_t softirq)277 TrackId TrackTracker::InternSoftirqCounterTrack(StringId name,
278 int32_t softirq) {
279 auto it = softirq_counter_tracks_.find(std::make_pair(name, softirq));
280 if (it != softirq_counter_tracks_.end()) {
281 return it->second;
282 }
283
284 tables::SoftirqCounterTrackTable::Row row(name);
285 row.softirq = softirq;
286
287 TrackId track =
288 context_->storage->mutable_softirq_counter_track_table()->Insert(row).id;
289 softirq_counter_tracks_[std::make_pair(name, softirq)] = track;
290 return track;
291 }
292
InternGpuCounterTrack(StringId name,uint32_t gpu_id)293 TrackId TrackTracker::InternGpuCounterTrack(StringId name, uint32_t gpu_id) {
294 auto it = gpu_counter_tracks_.find(std::make_pair(name, gpu_id));
295 if (it != gpu_counter_tracks_.end()) {
296 return it->second;
297 }
298 TrackId track = CreateGpuCounterTrack(name, gpu_id);
299 gpu_counter_tracks_[std::make_pair(name, gpu_id)] = track;
300 return track;
301 }
302
CreateGpuCounterTrack(StringId name,uint32_t gpu_id,StringId description,StringId unit)303 TrackId TrackTracker::CreateGpuCounterTrack(StringId name,
304 uint32_t gpu_id,
305 StringId description,
306 StringId unit) {
307 tables::GpuCounterTrackTable::Row row(name);
308 row.gpu_id = gpu_id;
309 row.description = description;
310 row.unit = unit;
311
312 return context_->storage->mutable_gpu_counter_track_table()->Insert(row).id;
313 }
314
CreatePerfCounterTrack(StringId name,uint32_t perf_session_id,uint32_t cpu,bool is_timebase)315 TrackId TrackTracker::CreatePerfCounterTrack(StringId name,
316 uint32_t perf_session_id,
317 uint32_t cpu,
318 bool is_timebase) {
319 tables::PerfCounterTrackTable::Row row(name);
320 row.perf_session_id = perf_session_id;
321 row.cpu = cpu;
322 row.is_timebase = is_timebase;
323 return context_->storage->mutable_perf_counter_track_table()->Insert(row).id;
324 }
325
326 } // namespace trace_processor
327 } // namespace perfetto
328