1 /*
2 * Copyright (C) 2023 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 "perfetto/public/abi/track_event_abi.h"
18 #include "perfetto/public/abi/track_event_hl_abi.h"
19 #include "perfetto/public/abi/track_event_ll_abi.h"
20
21 #include <algorithm>
22 #include <atomic>
23 #include <limits>
24 #include <mutex>
25 #include <optional>
26
27 #include "perfetto/base/compiler.h"
28 #include "perfetto/base/flat_set.h"
29 #include "perfetto/ext/base/file_utils.h"
30 #include "perfetto/ext/base/no_destructor.h"
31 #include "perfetto/ext/base/string_splitter.h"
32 #include "perfetto/ext/base/string_view.h"
33 #include "perfetto/ext/base/thread_utils.h"
34 #include "perfetto/protozero/contiguous_memory_range.h"
35 #include "perfetto/public/compiler.h"
36 #include "perfetto/tracing/data_source.h"
37 #include "perfetto/tracing/internal/basic_types.h"
38 #include "perfetto/tracing/internal/data_source_internal.h"
39 #include "perfetto/tracing/internal/track_event_internal.h"
40 #include "perfetto/tracing/track.h"
41 #include "protos/perfetto/common/data_source_descriptor.gen.h"
42 #include "protos/perfetto/common/track_event_descriptor.pbzero.h"
43 #include "protos/perfetto/config/data_source_config.gen.h"
44 #include "protos/perfetto/config/track_event/track_event_config.gen.h"
45 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
46 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
47 #include "protos/perfetto/trace/trace_packet.pbzero.h"
48 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
49 #include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
50 #include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
51 #include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
52 #include "protos/perfetto/trace/track_event/track_event.pbzero.h"
53 #include "src/shared_lib/intern_map.h"
54 #include "src/shared_lib/reset_for_testing.h"
55
56 struct PerfettoTeCategoryImpl* perfetto_te_any_categories;
57
58 PERFETTO_ATOMIC(bool) * perfetto_te_any_categories_enabled;
59
60 uint64_t perfetto_te_process_track_uuid;
61
62 struct PerfettoTeCategoryImpl {
63 std::atomic<bool> flag{false};
64 std::atomic<uint8_t> instances{0};
65 PerfettoTeCategoryDescriptor* desc = nullptr;
66 uint64_t cat_iid = 0;
67 PerfettoTeCategoryImplCallback cb = nullptr;
68 void* cb_user_arg = nullptr;
69 };
70
71 enum class MatchType { kExact, kPattern };
72
NameMatchesPattern(const std::string & pattern,const perfetto::base::StringView & name,MatchType match_type)73 static bool NameMatchesPattern(const std::string& pattern,
74 const perfetto::base::StringView& name,
75 MatchType match_type) {
76 // To avoid pulling in all of std::regex, for now we only support a single "*"
77 // wildcard at the end of the pattern.
78 size_t i = pattern.find('*');
79 if (i != std::string::npos) {
80 if (match_type != MatchType::kPattern)
81 return false;
82 return name.substr(0, i) ==
83 perfetto::base::StringView(pattern).substr(0, i);
84 }
85 return name == perfetto::base::StringView(pattern);
86 }
87
NameMatchesPatternList(const std::vector<std::string> & patterns,const perfetto::base::StringView & name,MatchType match_type)88 static bool NameMatchesPatternList(const std::vector<std::string>& patterns,
89 const perfetto::base::StringView& name,
90 MatchType match_type) {
91 for (const auto& pattern : patterns) {
92 if (NameMatchesPattern(pattern, name, match_type))
93 return true;
94 }
95 return false;
96 }
97
IsSingleCategoryEnabled(const PerfettoTeCategoryDescriptor & c,const perfetto::protos::gen::TrackEventConfig & config)98 static bool IsSingleCategoryEnabled(
99 const PerfettoTeCategoryDescriptor& c,
100 const perfetto::protos::gen::TrackEventConfig& config) {
101 auto has_matching_tag = [&](std::function<bool(const char*)> matcher) {
102 for (size_t i = 0; i < c.num_tags; ++i) {
103 if (matcher(c.tags[i]))
104 return true;
105 }
106 return false;
107 };
108 // First try exact matches, then pattern matches.
109 const std::array<MatchType, 2> match_types = {
110 {MatchType::kExact, MatchType::kPattern}};
111 for (auto match_type : match_types) {
112 // 1. Enabled categories.
113 if (NameMatchesPatternList(config.enabled_categories(), c.name,
114 match_type)) {
115 return true;
116 }
117
118 // 2. Enabled tags.
119 if (has_matching_tag([&](const char* tag) {
120 return NameMatchesPatternList(config.enabled_tags(), tag, match_type);
121 })) {
122 return true;
123 }
124
125 // 3. Disabled categories.
126 if (NameMatchesPatternList(config.disabled_categories(), c.name,
127 match_type)) {
128 return false;
129 }
130
131 // 4. Disabled tags.
132 if (has_matching_tag([&](const char* tag) {
133 return NameMatchesPatternList(config.disabled_tags(), tag,
134 match_type);
135 })) {
136 return false;
137 }
138 }
139
140 // If nothing matched, the category is disabled by default. N.B. this behavior
141 // is different than the C++ TrackEvent API.
142 return false;
143 }
144
IsRegisteredCategoryEnabled(const PerfettoTeCategoryImpl & cat,const perfetto::protos::gen::TrackEventConfig & config)145 static bool IsRegisteredCategoryEnabled(
146 const PerfettoTeCategoryImpl& cat,
147 const perfetto::protos::gen::TrackEventConfig& config) {
148 if (!cat.desc) {
149 return false;
150 }
151 return IsSingleCategoryEnabled(*cat.desc, config);
152 }
153
EnableRegisteredCategory(PerfettoTeCategoryImpl * cat,uint32_t instance_index)154 static void EnableRegisteredCategory(PerfettoTeCategoryImpl* cat,
155 uint32_t instance_index) {
156 PERFETTO_DCHECK(instance_index < perfetto::internal::kMaxDataSourceInstances);
157 // Matches the acquire_load in DataSource::Trace().
158 uint8_t old = cat->instances.fetch_or(
159 static_cast<uint8_t>(1u << instance_index), std::memory_order_release);
160 bool global_state_changed = old == 0;
161 if (global_state_changed) {
162 cat->flag.store(true, std::memory_order_relaxed);
163 }
164 if (cat->cb) {
165 cat->cb(cat, instance_index, /*created=*/true, global_state_changed,
166 cat->cb_user_arg);
167 }
168 }
169
DisableRegisteredCategory(PerfettoTeCategoryImpl * cat,uint32_t instance_index)170 static void DisableRegisteredCategory(PerfettoTeCategoryImpl* cat,
171 uint32_t instance_index) {
172 PERFETTO_DCHECK(instance_index < perfetto::internal::kMaxDataSourceInstances);
173 // Matches the acquire_load in DataSource::Trace().
174 cat->instances.fetch_and(static_cast<uint8_t>(~(1u << instance_index)),
175 std::memory_order_release);
176 bool global_state_changed = false;
177 if (!cat->instances.load(std::memory_order_relaxed)) {
178 cat->flag.store(false, std::memory_order_relaxed);
179 global_state_changed = true;
180 }
181 if (cat->cb) {
182 cat->cb(cat, instance_index, /*created=*/false, global_state_changed,
183 cat->cb_user_arg);
184 }
185 }
186
SerializeCategory(const PerfettoTeCategoryDescriptor & desc,perfetto::protos::pbzero::TrackEventDescriptor * ted)187 static void SerializeCategory(
188 const PerfettoTeCategoryDescriptor& desc,
189 perfetto::protos::pbzero::TrackEventDescriptor* ted) {
190 auto* c = ted->add_available_categories();
191 c->set_name(desc.name);
192 if (desc.desc)
193 c->set_description(desc.desc);
194 for (size_t j = 0; j < desc.num_tags; ++j) {
195 c->add_tags(desc.tags[j]);
196 }
197 }
198
199 namespace perfetto {
200 namespace shlib {
201
202 struct TrackEventIncrementalState {
203 // A heap-allocated message for storing newly seen interned data while we are
204 // in the middle of writing a track event. When a track event wants to write
205 // new interned data into the trace, it is first serialized into this message
206 // and then flushed to the real trace in EventContext when the packet ends.
207 // The message is cached here as a part of incremental state so that we can
208 // reuse the underlying buffer allocation for subsequently written interned
209 // data.
210 uint64_t last_timestamp_ns = 0;
211 protozero::HeapBuffered<protos::pbzero::InternedData>
212 serialized_interned_data;
213 bool was_cleared = true;
214 base::FlatSet<uint64_t> seen_track_uuids;
215 // Map from serialized representation of a dynamic category to its enabled
216 // state.
217 base::FlatHashMap<std::string, bool> dynamic_categories;
218 InternMap iids;
219 };
220
221 struct TrackEventTlsState {
222 template <typename TraceContext>
TrackEventTlsStateperfetto::shlib::TrackEventTlsState223 explicit TrackEventTlsState(const TraceContext& trace_context) {
224 auto locked_ds = trace_context.GetDataSourceLocked();
225 bool disable_incremental_timestamps = false;
226 timestamp_unit_multiplier = 1;
227 if (locked_ds.valid()) {
228 const auto& config = locked_ds->GetConfig();
229 disable_incremental_timestamps = config.disable_incremental_timestamps();
230 if (config.has_timestamp_unit_multiplier() &&
231 config.timestamp_unit_multiplier() != 0) {
232 timestamp_unit_multiplier = config.timestamp_unit_multiplier();
233 }
234 }
235 if (disable_incremental_timestamps) {
236 if (timestamp_unit_multiplier == 1) {
237 default_clock_id = PERFETTO_I_CLOCK_INCREMENTAL_UNDERNEATH;
238 } else {
239 default_clock_id = PERFETTO_TE_TIMESTAMP_TYPE_ABSOLUTE;
240 }
241 } else {
242 default_clock_id = PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL;
243 }
244 }
245 uint32_t default_clock_id;
246 uint64_t timestamp_unit_multiplier;
247 };
248
249 struct TrackEventDataSourceTraits : public perfetto::DefaultDataSourceTraits {
250 using IncrementalStateType = TrackEventIncrementalState;
251 using TlsStateType = TrackEventTlsState;
252 };
253
254 class TrackEvent
255 : public perfetto::DataSource<TrackEvent, TrackEventDataSourceTraits> {
256 public:
257 ~TrackEvent() override;
OnSetup(const DataSourceBase::SetupArgs & args)258 void OnSetup(const DataSourceBase::SetupArgs& args) override {
259 const std::string& config_raw = args.config->track_event_config_raw();
260 bool ok = config_.ParseFromArray(config_raw.data(), config_raw.size());
261 if (!ok) {
262 PERFETTO_LOG("Failed to parse config");
263 }
264 inst_id_ = args.internal_instance_index;
265 }
266
OnStart(const DataSourceBase::StartArgs &)267 void OnStart(const DataSourceBase::StartArgs&) override {
268 GlobalState::Instance().OnStart(config_, inst_id_);
269 }
270
OnStop(const DataSourceBase::StopArgs &)271 void OnStop(const DataSourceBase::StopArgs&) override {
272 GlobalState::Instance().OnStop(inst_id_);
273 }
274
GetConfig() const275 const perfetto::protos::gen::TrackEventConfig& GetConfig() const {
276 return config_;
277 }
278
Init()279 static void Init() {
280 DataSourceDescriptor dsd =
281 GlobalState::Instance().GenerateDescriptorFromCategories();
282 Register(dsd);
283 }
284
RegisterCategory(PerfettoTeCategoryImpl * cat)285 static void RegisterCategory(PerfettoTeCategoryImpl* cat) {
286 GlobalState::Instance().RegisterCategory(cat);
287 }
288
UpdateDescriptorFromCategories()289 static void UpdateDescriptorFromCategories() {
290 DataSourceDescriptor dsd =
291 GlobalState::Instance().GenerateDescriptorFromCategories();
292 UpdateDescriptor(dsd);
293 }
294
UnregisterCategory(PerfettoTeCategoryImpl * cat)295 static void UnregisterCategory(PerfettoTeCategoryImpl* cat) {
296 GlobalState::Instance().UnregisterCategory(cat);
297 }
298
CategorySetCallback(struct PerfettoTeCategoryImpl * cat,PerfettoTeCategoryImplCallback cb,void * user_arg)299 static void CategorySetCallback(struct PerfettoTeCategoryImpl* cat,
300 PerfettoTeCategoryImplCallback cb,
301 void* user_arg) {
302 GlobalState::Instance().CategorySetCallback(cat, cb, user_arg);
303 }
304
305 static internal::DataSourceType* GetType();
306
307 static internal::DataSourceThreadLocalState** GetTlsState();
308
309 private:
310 struct GlobalState {
Instanceperfetto::shlib::TrackEvent::GlobalState311 static GlobalState& Instance() {
312 static GlobalState* instance = new GlobalState();
313 return *instance;
314 }
315
OnStartperfetto::shlib::TrackEvent::GlobalState316 void OnStart(const perfetto::protos::gen::TrackEventConfig& config,
317 uint32_t instance_id) {
318 std::lock_guard<std::mutex> lock(mu_);
319 EnableRegisteredCategory(perfetto_te_any_categories, instance_id);
320 for (PerfettoTeCategoryImpl* cat : categories_) {
321 if (IsRegisteredCategoryEnabled(*cat, config)) {
322 EnableRegisteredCategory(cat, instance_id);
323 }
324 }
325 }
326
OnStopperfetto::shlib::TrackEvent::GlobalState327 void OnStop(uint32_t instance_id) {
328 std::lock_guard<std::mutex> lock(GlobalState::Instance().mu_);
329 for (PerfettoTeCategoryImpl* cat : GlobalState::Instance().categories_) {
330 DisableRegisteredCategory(cat, instance_id);
331 }
332 DisableRegisteredCategory(perfetto_te_any_categories, instance_id);
333 }
334
RegisterCategoryperfetto::shlib::TrackEvent::GlobalState335 void RegisterCategory(PerfettoTeCategoryImpl* cat) {
336 {
337 std::lock_guard<std::mutex> lock(mu_);
338 Trace([cat](TraceContext ctx) {
339 auto ds = ctx.GetDataSourceLocked();
340
341 if (IsRegisteredCategoryEnabled(*cat, ds->GetConfig())) {
342 EnableRegisteredCategory(cat, ds->inst_id_);
343 }
344 });
345 categories_.push_back(cat);
346 cat->cat_iid = ++GlobalState::Instance().interned_categories_;
347 }
348 }
349
UnregisterCategoryperfetto::shlib::TrackEvent::GlobalState350 void UnregisterCategory(PerfettoTeCategoryImpl* cat) {
351 std::lock_guard<std::mutex> lock(mu_);
352 categories_.erase(
353 std::remove(categories_.begin(), categories_.end(), cat),
354 categories_.end());
355 }
356
CategorySetCallbackperfetto::shlib::TrackEvent::GlobalState357 void CategorySetCallback(struct PerfettoTeCategoryImpl* cat,
358 PerfettoTeCategoryImplCallback cb,
359 void* user_arg) {
360 std::lock_guard<std::mutex> lock(mu_);
361 cat->cb = cb;
362 cat->cb_user_arg = user_arg;
363 if (!cat->cb) {
364 return;
365 }
366
367 bool first = true;
368 uint8_t active_instances = cat->instances.load(std::memory_order_relaxed);
369 for (PerfettoDsInstanceIndex i = 0; i < internal::kMaxDataSourceInstances;
370 i++) {
371 if ((active_instances & (1 << i)) == 0) {
372 continue;
373 }
374 cb(cat, i, true, first, user_arg);
375 first = false;
376 }
377 }
378
GenerateDescriptorFromCategoriesperfetto::shlib::TrackEvent::GlobalState379 DataSourceDescriptor GenerateDescriptorFromCategories() const {
380 DataSourceDescriptor dsd;
381 dsd.set_name("track_event");
382
383 protozero::HeapBuffered<perfetto::protos::pbzero::TrackEventDescriptor>
384 ted;
385 for (PerfettoTeCategoryImpl* cat : categories_) {
386 SerializeCategory(*cat->desc, ted.get());
387 }
388 dsd.set_track_event_descriptor_raw(ted.SerializeAsString());
389 return dsd;
390 }
391
392 private:
GlobalStateperfetto::shlib::TrackEvent::GlobalState393 GlobalState() : interned_categories_(0) {
394 perfetto_te_any_categories = new PerfettoTeCategoryImpl;
395 perfetto_te_any_categories_enabled = &perfetto_te_any_categories->flag;
396 }
397
398 // Guards categories and interned_categories;
399 std::mutex mu_;
400 std::vector<PerfettoTeCategoryImpl*> categories_;
401 uint64_t interned_categories_;
402 };
403
404 uint32_t inst_id_;
405 perfetto::protos::gen::TrackEventConfig config_;
406 };
407
408 TrackEvent::~TrackEvent() = default;
409
ResetTrackEventTls()410 void ResetTrackEventTls() {
411 *TrackEvent::GetTlsState() = nullptr;
412 }
413
414 struct TracePointTraits {
415 struct TracePointData {
416 struct PerfettoTeCategoryImpl* enabled;
417 };
GetActiveInstancesperfetto::shlib::TracePointTraits418 static constexpr std::atomic<uint8_t>* GetActiveInstances(
419 TracePointData data) {
420 return &data.enabled->instances;
421 }
422 };
423
424 } // namespace shlib
425 } // namespace perfetto
426
427 PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(
428 perfetto::shlib::TrackEvent,
429 perfetto::shlib::TrackEventDataSourceTraits);
430
431 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(
432 perfetto::shlib::TrackEvent,
433 perfetto::shlib::TrackEventDataSourceTraits);
434
GetType()435 perfetto::internal::DataSourceType* perfetto::shlib::TrackEvent::GetType() {
436 return &perfetto::shlib::TrackEvent::Helper::type();
437 }
438
439 perfetto::internal::DataSourceThreadLocalState**
GetTlsState()440 perfetto::shlib::TrackEvent::GetTlsState() {
441 return &tls_state_;
442 }
443
444 namespace {
445
446 using perfetto::internal::TrackEventInternal;
447
EventType(int32_t type)448 perfetto::protos::pbzero::TrackEvent::Type EventType(int32_t type) {
449 using Type = perfetto::protos::pbzero::TrackEvent::Type;
450 auto enum_type = static_cast<PerfettoTeType>(type);
451 switch (enum_type) {
452 case PERFETTO_TE_TYPE_SLICE_BEGIN:
453 return Type::TYPE_SLICE_BEGIN;
454 case PERFETTO_TE_TYPE_SLICE_END:
455 return Type::TYPE_SLICE_END;
456 case PERFETTO_TE_TYPE_INSTANT:
457 return Type::TYPE_INSTANT;
458 case PERFETTO_TE_TYPE_COUNTER:
459 return Type::TYPE_COUNTER;
460 }
461 return Type::TYPE_UNSPECIFIED;
462 }
463
464 protozero::MessageHandle<perfetto::protos::pbzero::TracePacket>
NewTracePacketInternal(perfetto::TraceWriterBase * trace_writer,perfetto::shlib::TrackEventIncrementalState * incr_state,const perfetto::shlib::TrackEventTlsState & tls_state,perfetto::TraceTimestamp timestamp,uint32_t seq_flags)465 NewTracePacketInternal(perfetto::TraceWriterBase* trace_writer,
466 perfetto::shlib::TrackEventIncrementalState* incr_state,
467 const perfetto::shlib::TrackEventTlsState& tls_state,
468 perfetto::TraceTimestamp timestamp,
469 uint32_t seq_flags) {
470 // PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL is the default timestamp returned
471 // by TrackEventInternal::GetTraceTime(). If the configuration in `tls_state`
472 // uses a different clock, we have to use that instead.
473 if (PERFETTO_UNLIKELY(tls_state.default_clock_id !=
474 PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL &&
475 timestamp.clock_id ==
476 PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL)) {
477 timestamp.clock_id = tls_state.default_clock_id;
478 }
479 auto packet = trace_writer->NewTracePacket();
480 auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
481 if (PERFETTO_LIKELY(timestamp.clock_id ==
482 PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL)) {
483 if (PERFETTO_LIKELY(incr_state->last_timestamp_ns <= timestamp.value)) {
484 // No need to set the clock id here, since
485 // PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL is the clock id assumed by
486 // default.
487 auto time_diff_ns = timestamp.value - incr_state->last_timestamp_ns;
488 auto time_diff_units = time_diff_ns / ts_unit_multiplier;
489 packet->set_timestamp(time_diff_units);
490 incr_state->last_timestamp_ns += time_diff_units * ts_unit_multiplier;
491 } else {
492 packet->set_timestamp(timestamp.value / ts_unit_multiplier);
493 packet->set_timestamp_clock_id(
494 ts_unit_multiplier == 1
495 ? static_cast<uint32_t>(PERFETTO_I_CLOCK_INCREMENTAL_UNDERNEATH)
496 : static_cast<uint32_t>(PERFETTO_TE_TIMESTAMP_TYPE_ABSOLUTE));
497 }
498 } else if (PERFETTO_LIKELY(timestamp.clock_id ==
499 tls_state.default_clock_id)) {
500 packet->set_timestamp(timestamp.value / ts_unit_multiplier);
501 } else {
502 packet->set_timestamp(timestamp.value);
503 packet->set_timestamp_clock_id(timestamp.clock_id);
504 }
505 packet->set_sequence_flags(seq_flags);
506 return packet;
507 }
508
509 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
510 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
GetCmdLine()511 std::vector<std::string> GetCmdLine() {
512 std::vector<std::string> cmdline_str;
513 std::string cmdline;
514 if (perfetto::base::ReadFile("/proc/self/cmdline", &cmdline)) {
515 perfetto::base::StringSplitter splitter(std::move(cmdline), '\0');
516 while (splitter.Next()) {
517 cmdline_str.emplace_back(splitter.cur_token(), splitter.cur_token_size());
518 }
519 }
520 return cmdline_str;
521 }
522 #endif
523
ResetIncrementalStateIfRequired(perfetto::TraceWriterBase * trace_writer,perfetto::shlib::TrackEventIncrementalState * incr_state,const perfetto::shlib::TrackEventTlsState & tls_state,const perfetto::TraceTimestamp & timestamp)524 void ResetIncrementalStateIfRequired(
525 perfetto::TraceWriterBase* trace_writer,
526 perfetto::shlib::TrackEventIncrementalState* incr_state,
527 const perfetto::shlib::TrackEventTlsState& tls_state,
528 const perfetto::TraceTimestamp& timestamp) {
529 if (!incr_state->was_cleared) {
530 return;
531 }
532 incr_state->was_cleared = false;
533
534 auto sequence_timestamp = timestamp;
535 if (timestamp.clock_id != PERFETTO_I_CLOCK_INCREMENTAL_UNDERNEATH &&
536 timestamp.clock_id != PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL) {
537 sequence_timestamp = TrackEventInternal::GetTraceTime();
538 }
539
540 incr_state->last_timestamp_ns = sequence_timestamp.value;
541 auto tid = perfetto::base::GetThreadId();
542 auto pid = perfetto::Platform::GetCurrentProcessId();
543 uint64_t thread_track_uuid =
544 perfetto_te_process_track_uuid ^ static_cast<uint64_t>(tid);
545 auto ts_unit_multiplier = tls_state.timestamp_unit_multiplier;
546 {
547 // Mark any incremental state before this point invalid. Also set up
548 // defaults so that we don't need to repeat constant data for each packet.
549 auto packet = NewTracePacketInternal(
550 trace_writer, incr_state, tls_state, timestamp,
551 perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
552 auto defaults = packet->set_trace_packet_defaults();
553 defaults->set_timestamp_clock_id(tls_state.default_clock_id);
554 // Establish the default track for this event sequence.
555 auto track_defaults = defaults->set_track_event_defaults();
556 track_defaults->set_track_uuid(thread_track_uuid);
557
558 if (tls_state.default_clock_id != PERFETTO_I_CLOCK_INCREMENTAL_UNDERNEATH) {
559 perfetto::protos::pbzero::ClockSnapshot* clocks =
560 packet->set_clock_snapshot();
561 // Trace clock.
562 perfetto::protos::pbzero::ClockSnapshot::Clock* trace_clock =
563 clocks->add_clocks();
564 trace_clock->set_clock_id(PERFETTO_I_CLOCK_INCREMENTAL_UNDERNEATH);
565 trace_clock->set_timestamp(sequence_timestamp.value);
566
567 if (PERFETTO_LIKELY(tls_state.default_clock_id ==
568 PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL)) {
569 // Delta-encoded incremental clock in nanoseconds by default but
570 // configurable by |tls_state.timestamp_unit_multiplier|.
571 perfetto::protos::pbzero::ClockSnapshot::Clock* clock_incremental =
572 clocks->add_clocks();
573 clock_incremental->set_clock_id(PERFETTO_TE_TIMESTAMP_TYPE_INCREMENTAL);
574 clock_incremental->set_timestamp(sequence_timestamp.value /
575 ts_unit_multiplier);
576 clock_incremental->set_is_incremental(true);
577 clock_incremental->set_unit_multiplier_ns(ts_unit_multiplier);
578 }
579 if (ts_unit_multiplier > 1) {
580 // absolute clock with custom timestamp_unit_multiplier.
581 perfetto::protos::pbzero::ClockSnapshot::Clock* absolute_clock =
582 clocks->add_clocks();
583 absolute_clock->set_clock_id(PERFETTO_TE_TIMESTAMP_TYPE_ABSOLUTE);
584 absolute_clock->set_timestamp(sequence_timestamp.value /
585 ts_unit_multiplier);
586 absolute_clock->set_is_incremental(false);
587 absolute_clock->set_unit_multiplier_ns(ts_unit_multiplier);
588 }
589 }
590 }
591
592 // Every thread should write a descriptor for its default track, because most
593 // trace points won't explicitly reference it. We also write the process
594 // descriptor from every thread that writes trace events to ensure it gets
595 // emitted at least once.
596 {
597 auto packet = NewTracePacketInternal(
598 trace_writer, incr_state, tls_state, timestamp,
599 perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
600 auto* track = packet->set_track_descriptor();
601 track->set_uuid(thread_track_uuid);
602 track->set_parent_uuid(perfetto_te_process_track_uuid);
603 auto* td = track->set_thread();
604
605 td->set_pid(static_cast<int32_t>(pid));
606 td->set_tid(static_cast<int32_t>(tid));
607 std::string thread_name;
608 if (perfetto::base::GetThreadName(thread_name))
609 td->set_thread_name(thread_name);
610 }
611 {
612 auto packet = NewTracePacketInternal(
613 trace_writer, incr_state, tls_state, timestamp,
614 perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
615 auto* track = packet->set_track_descriptor();
616 track->set_uuid(perfetto_te_process_track_uuid);
617 auto* pd = track->set_process();
618
619 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
620 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
621 static perfetto::base::NoDestructor<std::vector<std::string>> cmdline(
622 GetCmdLine());
623 if (!cmdline.ref().empty()) {
624 // Since cmdline is a zero-terminated list of arguments, this ends up
625 // writing just the first element, i.e., the process name, into the
626 // process name field.
627 pd->set_process_name(cmdline.ref()[0]);
628 for (const std::string& arg : cmdline.ref()) {
629 pd->add_cmdline(arg);
630 }
631 }
632 #endif
633 pd->set_pid(static_cast<int32_t>(pid));
634 }
635 }
636
WriteTrackEvent(perfetto::shlib::TrackEventIncrementalState * incr,perfetto::protos::pbzero::TrackEvent * event,PerfettoTeCategoryImpl * cat,perfetto::protos::pbzero::TrackEvent::Type type,const char * name,const PerfettoTeHlExtra * extra_data,std::optional<uint64_t> track_uuid,const PerfettoTeCategoryDescriptor * dynamic_cat,bool use_interning)637 void WriteTrackEvent(perfetto::shlib::TrackEventIncrementalState* incr,
638 perfetto::protos::pbzero::TrackEvent* event,
639 PerfettoTeCategoryImpl* cat,
640 perfetto::protos::pbzero::TrackEvent::Type type,
641 const char* name,
642 const PerfettoTeHlExtra* extra_data,
643 std::optional<uint64_t> track_uuid,
644 const PerfettoTeCategoryDescriptor* dynamic_cat,
645 bool use_interning) {
646 if (type != perfetto::protos::pbzero::TrackEvent::TYPE_UNSPECIFIED) {
647 event->set_type(type);
648 }
649
650 if (!dynamic_cat &&
651 type != perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END &&
652 type != perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER) {
653 uint64_t iid = cat->cat_iid;
654 auto res = incr->iids.FindOrAssign(
655 perfetto::protos::pbzero::InternedData::kEventCategoriesFieldNumber,
656 &iid, sizeof(iid));
657 if (res.newly_assigned) {
658 auto* ser = incr->serialized_interned_data->add_event_categories();
659 ser->set_iid(iid);
660 ser->set_name(cat->desc->name);
661 }
662 event->add_category_iids(iid);
663 }
664
665 if (type != perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) {
666 if (name) {
667 if (use_interning) {
668 const void* str = name;
669 size_t len = strlen(name);
670 auto res = incr->iids.FindOrAssign(
671 perfetto::protos::pbzero::InternedData::kEventNamesFieldNumber, str,
672 len);
673 if (res.newly_assigned) {
674 auto* ser = incr->serialized_interned_data->add_event_names();
675 ser->set_iid(res.iid);
676 ser->set_name(name);
677 }
678 event->set_name_iid(res.iid);
679 } else {
680 event->set_name(name);
681 }
682 }
683 }
684
685 if (dynamic_cat &&
686 type != perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END &&
687 type != perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER) {
688 event->add_categories(dynamic_cat->name);
689 }
690
691 if (track_uuid) {
692 event->set_track_uuid(*track_uuid);
693 }
694
695 for (const auto* it = extra_data; it; it = it->next) {
696 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64 &&
697 type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER) {
698 event->set_counter_value(
699 reinterpret_cast<const struct PerfettoTeHlExtraCounterInt64*>(it)
700 ->value);
701 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE) {
702 event->set_double_counter_value(
703 reinterpret_cast<const struct PerfettoTeHlExtraCounterDouble*>(it)
704 ->value);
705 }
706 }
707
708 for (const auto* it = extra_data; it; it = it->next) {
709 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL ||
710 it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_UINT64 ||
711 it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64 ||
712 it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE ||
713 it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING ||
714 it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_POINTER) {
715 auto* dbg = event->add_debug_annotations();
716 const char* arg_name = nullptr;
717 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL) {
718 auto* arg =
719 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgBool*>(it);
720 dbg->set_bool_value(arg->value);
721 arg_name = arg->name;
722 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_UINT64) {
723 auto* arg =
724 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgUint64*>(it);
725 dbg->set_uint_value(arg->value);
726 arg_name = arg->name;
727 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64) {
728 auto* arg =
729 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgInt64*>(it);
730 dbg->set_int_value(arg->value);
731 arg_name = arg->name;
732 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE) {
733 auto* arg =
734 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgDouble*>(it);
735 dbg->set_double_value(arg->value);
736 arg_name = arg->name;
737 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING) {
738 auto* arg =
739 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgString*>(it);
740 dbg->set_string_value(arg->value);
741 arg_name = arg->name;
742 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_POINTER) {
743 auto* arg =
744 reinterpret_cast<const struct PerfettoTeHlExtraDebugArgPointer*>(
745 it);
746 dbg->set_pointer_value(arg->value);
747 arg_name = arg->name;
748 }
749
750 if (arg_name != nullptr) {
751 const void* str = arg_name;
752 size_t len = strlen(arg_name);
753 auto res =
754 incr->iids.FindOrAssign(perfetto::protos::pbzero::InternedData::
755 kDebugAnnotationNamesFieldNumber,
756 str, len);
757 if (res.newly_assigned) {
758 auto* ser =
759 incr->serialized_interned_data->add_debug_annotation_names();
760 ser->set_iid(res.iid);
761 ser->set_name(arg_name);
762 }
763 dbg->set_name_iid(res.iid);
764 }
765 }
766 }
767
768 for (const auto* it = extra_data; it; it = it->next) {
769 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_FLOW) {
770 event->add_flow_ids(
771 reinterpret_cast<const struct PerfettoTeHlExtraFlow*>(it)->id);
772 }
773 }
774
775 for (const auto* it = extra_data; it; it = it->next) {
776 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW) {
777 event->add_terminating_flow_ids(
778 reinterpret_cast<const struct PerfettoTeHlExtraFlow*>(it)->id);
779 }
780 }
781 }
782
783 } // namespace
784
PerfettoTeCategoryImplCreate(struct PerfettoTeCategoryDescriptor * desc)785 struct PerfettoTeCategoryImpl* PerfettoTeCategoryImplCreate(
786 struct PerfettoTeCategoryDescriptor* desc) {
787 auto* cat = new PerfettoTeCategoryImpl;
788 cat->desc = desc;
789 perfetto::shlib::TrackEvent::RegisterCategory(cat);
790 return cat;
791 }
792
PerfettoTePublishCategories()793 void PerfettoTePublishCategories() {
794 perfetto::shlib::TrackEvent::UpdateDescriptorFromCategories();
795 }
796
PerfettoTeCategoryImplSetCallback(struct PerfettoTeCategoryImpl * cat,PerfettoTeCategoryImplCallback cb,void * user_arg)797 void PerfettoTeCategoryImplSetCallback(struct PerfettoTeCategoryImpl* cat,
798 PerfettoTeCategoryImplCallback cb,
799 void* user_arg) {
800 perfetto::shlib::TrackEvent::CategorySetCallback(cat, cb, user_arg);
801 }
802
PERFETTO_ATOMIC(bool)803 PERFETTO_ATOMIC(bool) *
804 PerfettoTeCategoryImplGetEnabled(struct PerfettoTeCategoryImpl* cat) {
805 return &cat->flag;
806 }
807
PerfettoTeCategoryImplGetIid(struct PerfettoTeCategoryImpl * cat)808 uint64_t PerfettoTeCategoryImplGetIid(struct PerfettoTeCategoryImpl* cat) {
809 return cat->cat_iid;
810 }
811
PerfettoTeCategoryImplDestroy(struct PerfettoTeCategoryImpl * cat)812 void PerfettoTeCategoryImplDestroy(struct PerfettoTeCategoryImpl* cat) {
813 perfetto::shlib::TrackEvent::UnregisterCategory(cat);
814 delete cat;
815 }
816
PerfettoTeInit(void)817 void PerfettoTeInit(void) {
818 perfetto::shlib::TrackEvent::Init();
819 perfetto_te_process_track_uuid =
820 perfetto::internal::TrackRegistry::ComputeProcessUuid();
821 }
822
PerfettoTeGetTimestamp(void)823 struct PerfettoTeTimestamp PerfettoTeGetTimestamp(void) {
824 struct PerfettoTeTimestamp ret;
825 ret.clock_id = PERFETTO_TE_TIMESTAMP_TYPE_BOOT;
826 ret.value = TrackEventInternal::GetTimeNs();
827 return ret;
828 }
829
IsDynamicCategoryEnabled(uint32_t inst_idx,perfetto::shlib::TrackEventIncrementalState * incr_state,const struct PerfettoTeCategoryDescriptor & desc)830 static bool IsDynamicCategoryEnabled(
831 uint32_t inst_idx,
832 perfetto::shlib::TrackEventIncrementalState* incr_state,
833 const struct PerfettoTeCategoryDescriptor& desc) {
834 constexpr size_t kMaxCacheSize = 20;
835 perfetto::internal::DataSourceType* ds =
836 perfetto::shlib::TrackEvent::GetType();
837 auto& cache = incr_state->dynamic_categories;
838 protozero::HeapBuffered<perfetto::protos::pbzero::TrackEventDescriptor> ted;
839 SerializeCategory(desc, ted.get());
840 std::string serialized = ted.SerializeAsString();
841 auto* cached = cache.Find(serialized);
842 if (cached) {
843 return *cached;
844 }
845
846 auto* internal_state = ds->static_state()->TryGet(inst_idx);
847 if (!internal_state)
848 return false;
849 std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
850 auto* sds = static_cast<perfetto::shlib::TrackEvent*>(
851 internal_state->data_source.get());
852
853 bool res = IsSingleCategoryEnabled(desc, sds->GetConfig());
854 if (cache.size() < kMaxCacheSize) {
855 cache[serialized] = res;
856 }
857 return res;
858 }
859
860 // If the category `dyn_cat` is enabled on the data source instance pointed by
861 // `ii`, returns immediately. Otherwise, advances `ii` to a data source instance
862 // where `dyn_cat` is enabled. If there's no data source instance where
863 // `dyn_cat` is enabled, `ii->instance` will be nullptr.
AdvanceToFirstEnabledDynamicCategory(perfetto::internal::DataSourceType::InstancesIterator * ii,perfetto::internal::DataSourceThreadLocalState * tls_state,struct PerfettoTeCategoryImpl * cat,const PerfettoTeCategoryDescriptor & dyn_cat)864 static void AdvanceToFirstEnabledDynamicCategory(
865 perfetto::internal::DataSourceType::InstancesIterator* ii,
866 perfetto::internal::DataSourceThreadLocalState* tls_state,
867 struct PerfettoTeCategoryImpl* cat,
868 const PerfettoTeCategoryDescriptor& dyn_cat) {
869 perfetto::internal::DataSourceType* ds =
870 perfetto::shlib::TrackEvent::GetType();
871 for (; ii->instance;
872 ds->NextIteration</*Traits=*/perfetto::shlib::TracePointTraits>(
873 ii, tls_state, {cat})) {
874 auto* incr_state =
875 static_cast<perfetto::shlib::TrackEventIncrementalState*>(
876 ds->GetIncrementalState(ii->instance, ii->i));
877 if (IsDynamicCategoryEnabled(ii->i, incr_state, dyn_cat)) {
878 break;
879 }
880 }
881 }
882
InstanceOp(perfetto::internal::DataSourceType * ds,perfetto::internal::DataSourceType::InstancesIterator * ii,perfetto::internal::DataSourceThreadLocalState * tls_state,struct PerfettoTeCategoryImpl * cat,perfetto::protos::pbzero::TrackEvent::Type type,const char * name,const struct PerfettoTeHlExtra * extra_data)883 static void InstanceOp(
884 perfetto::internal::DataSourceType* ds,
885 perfetto::internal::DataSourceType::InstancesIterator* ii,
886 perfetto::internal::DataSourceThreadLocalState* tls_state,
887 struct PerfettoTeCategoryImpl* cat,
888 perfetto::protos::pbzero::TrackEvent::Type type,
889 const char* name,
890 const struct PerfettoTeHlExtra* extra_data) {
891 if (!ii->instance) {
892 return;
893 }
894
895 const PerfettoTeRegisteredTrackImpl* registered_track = nullptr;
896 const PerfettoTeHlExtraNamedTrack* named_track = nullptr;
897 std::optional<uint64_t> track_uuid;
898
899 const struct PerfettoTeHlExtraTimestamp* custom_timestamp = nullptr;
900 const struct PerfettoTeCategoryDescriptor* dynamic_cat = nullptr;
901 std::optional<int64_t> int_counter;
902 std::optional<double> double_counter;
903 bool use_interning = true;
904
905 for (const auto* it = extra_data; it; it = it->next) {
906 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK) {
907 auto* cast =
908 reinterpret_cast<const struct PerfettoTeHlExtraRegisteredTrack*>(it);
909 registered_track = cast->track;
910 named_track = nullptr;
911 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK) {
912 registered_track = nullptr;
913 named_track =
914 reinterpret_cast<const struct PerfettoTeHlExtraNamedTrack*>(it);
915 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_TIMESTAMP) {
916 custom_timestamp =
917 reinterpret_cast<const struct PerfettoTeHlExtraTimestamp*>(it);
918 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_DYNAMIC_CATEGORY) {
919 dynamic_cat =
920 reinterpret_cast<const struct PerfettoTeHlExtraDynamicCategory*>(it)
921 ->desc;
922 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64) {
923 int_counter =
924 reinterpret_cast<const struct PerfettoTeHlExtraCounterInt64*>(it)
925 ->value;
926 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE) {
927 double_counter =
928 reinterpret_cast<const struct PerfettoTeHlExtraCounterInt64*>(it)
929 ->value;
930 } else if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_NO_INTERN) {
931 use_interning = false;
932 }
933 }
934
935 perfetto::TraceTimestamp ts;
936 if (custom_timestamp) {
937 ts.clock_id = custom_timestamp->timestamp.clock_id;
938 ts.value = custom_timestamp->timestamp.value;
939 } else {
940 ts = TrackEventInternal::GetTraceTime();
941 }
942
943 if (PERFETTO_UNLIKELY(dynamic_cat)) {
944 AdvanceToFirstEnabledDynamicCategory(ii, tls_state, cat, *dynamic_cat);
945 if (!ii->instance) {
946 return;
947 }
948 }
949
950 const auto& track_event_tls =
951 *static_cast<perfetto::shlib::TrackEventTlsState*>(
952 ii->instance->data_source_custom_tls.get());
953
954 auto* incr_state = static_cast<perfetto::shlib::TrackEventIncrementalState*>(
955 ds->GetIncrementalState(ii->instance, ii->i));
956 ResetIncrementalStateIfRequired(ii->instance->trace_writer.get(), incr_state,
957 track_event_tls, ts);
958
959 if (registered_track) {
960 if (incr_state->seen_track_uuids.insert(registered_track->uuid).second) {
961 auto packet = ii->instance->trace_writer->NewTracePacket();
962 auto* track_descriptor = packet->set_track_descriptor();
963 track_descriptor->AppendRawProtoBytes(registered_track->descriptor,
964 registered_track->descriptor_size);
965 }
966 track_uuid = registered_track->uuid;
967 } else if (named_track) {
968 uint64_t uuid = named_track->parent_uuid;
969 uuid ^= PerfettoFnv1a(named_track->name, strlen(named_track->name));
970 uuid ^= named_track->id;
971 if (incr_state->seen_track_uuids.insert(uuid).second) {
972 auto packet = ii->instance->trace_writer->NewTracePacket();
973 auto* track_descriptor = packet->set_track_descriptor();
974 track_descriptor->set_uuid(uuid);
975 if (named_track->parent_uuid) {
976 track_descriptor->set_parent_uuid(named_track->parent_uuid);
977 }
978 track_descriptor->set_name(named_track->name);
979 }
980 track_uuid = uuid;
981 }
982
983 perfetto::TraceWriterBase* trace_writer = ii->instance->trace_writer.get();
984 {
985 auto packet = NewTracePacketInternal(
986 trace_writer, incr_state, track_event_tls, ts,
987 perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
988 auto* track_event = packet->set_track_event();
989 WriteTrackEvent(incr_state, track_event, cat, type, name, extra_data,
990 track_uuid, dynamic_cat, use_interning);
991 track_event->Finalize();
992
993 if (!incr_state->serialized_interned_data.empty()) {
994 auto ranges = incr_state->serialized_interned_data.GetRanges();
995 packet->AppendScatteredBytes(
996 perfetto::protos::pbzero::TracePacket::kInternedDataFieldNumber,
997 ranges.data(), ranges.size());
998 incr_state->serialized_interned_data.Reset();
999 }
1000 }
1001
1002 bool flush = false;
1003 for (const auto* it = extra_data; it; it = it->next) {
1004 if (it->type == PERFETTO_TE_HL_EXTRA_TYPE_FLUSH) {
1005 flush = true;
1006 }
1007 }
1008 if (PERFETTO_UNLIKELY(flush)) {
1009 trace_writer->Flush();
1010 }
1011 }
1012
PerfettoTeHlEmitImpl(struct PerfettoTeCategoryImpl * cat,int32_t type,const char * name,const struct PerfettoTeHlExtra * extra_data)1013 void PerfettoTeHlEmitImpl(struct PerfettoTeCategoryImpl* cat,
1014 int32_t type,
1015 const char* name,
1016 const struct PerfettoTeHlExtra* extra_data) {
1017 uint32_t cached_instances =
1018 perfetto::shlib::TracePointTraits::GetActiveInstances({cat})->load(
1019 std::memory_order_relaxed);
1020 if (!cached_instances) {
1021 return;
1022 }
1023
1024 perfetto::internal::DataSourceType* ds =
1025 perfetto::shlib::TrackEvent::GetType();
1026
1027 perfetto::internal::DataSourceThreadLocalState*& tls_state =
1028 *perfetto::shlib::TrackEvent::GetTlsState();
1029
1030 if (!ds->TracePrologue<perfetto::shlib::TrackEventDataSourceTraits,
1031 perfetto::shlib::TracePointTraits>(
1032 &tls_state, &cached_instances, {cat})) {
1033 return;
1034 }
1035
1036 for (perfetto::internal::DataSourceType::InstancesIterator ii =
1037 ds->BeginIteration<perfetto::shlib::TracePointTraits>(
1038 cached_instances, tls_state, {cat});
1039 ii.instance;
1040 ds->NextIteration</*Traits=*/perfetto::shlib::TracePointTraits>(
1041 &ii, tls_state, {cat})) {
1042 InstanceOp(ds, &ii, tls_state, cat, EventType(type), name, extra_data);
1043 }
1044 ds->TraceEpilogue(tls_state);
1045 }
1046
FillIterator(const perfetto::internal::DataSourceType::InstancesIterator * ii,struct PerfettoTeTimestamp ts,struct PerfettoTeLlImplIterator * iterator)1047 static void FillIterator(
1048 const perfetto::internal::DataSourceType::InstancesIterator* ii,
1049 struct PerfettoTeTimestamp ts,
1050 struct PerfettoTeLlImplIterator* iterator) {
1051 perfetto::internal::DataSourceType* ds =
1052 perfetto::shlib::TrackEvent::GetType();
1053
1054 auto& track_event_tls = *static_cast<perfetto::shlib::TrackEventTlsState*>(
1055 ii->instance->data_source_custom_tls.get());
1056
1057 auto* incr_state = static_cast<perfetto::shlib::TrackEventIncrementalState*>(
1058 ds->GetIncrementalState(ii->instance, ii->i));
1059 perfetto::TraceTimestamp tts;
1060 tts.clock_id = ts.clock_id;
1061 tts.value = ts.value;
1062 ResetIncrementalStateIfRequired(ii->instance->trace_writer.get(), incr_state,
1063 track_event_tls, tts);
1064
1065 iterator->incr = reinterpret_cast<struct PerfettoTeLlImplIncr*>(incr_state);
1066 iterator->tls =
1067 reinterpret_cast<struct PerfettoTeLlImplTls*>(&track_event_tls);
1068 }
1069
PerfettoTeLlImplBegin(struct PerfettoTeCategoryImpl * cat,struct PerfettoTeTimestamp ts)1070 struct PerfettoTeLlImplIterator PerfettoTeLlImplBegin(
1071 struct PerfettoTeCategoryImpl* cat,
1072 struct PerfettoTeTimestamp ts) {
1073 struct PerfettoTeLlImplIterator ret = {};
1074 uint32_t cached_instances =
1075 perfetto::shlib::TracePointTraits::GetActiveInstances({cat})->load(
1076 std::memory_order_relaxed);
1077 if (!cached_instances) {
1078 return ret;
1079 }
1080
1081 perfetto::internal::DataSourceType* ds =
1082 perfetto::shlib::TrackEvent::GetType();
1083
1084 perfetto::internal::DataSourceThreadLocalState*& tls_state =
1085 *perfetto::shlib::TrackEvent::GetTlsState();
1086
1087 if (!ds->TracePrologue<perfetto::shlib::TrackEventDataSourceTraits,
1088 perfetto::shlib::TracePointTraits>(
1089 &tls_state, &cached_instances, {cat})) {
1090 return ret;
1091 }
1092
1093 perfetto::internal::DataSourceType::InstancesIterator ii =
1094 ds->BeginIteration<perfetto::shlib::TracePointTraits>(cached_instances,
1095 tls_state, {cat});
1096
1097 ret.ds.inst_id = ii.i;
1098 tls_state->root_tls->cached_instances = ii.cached_instances;
1099 ret.ds.tracer = reinterpret_cast<struct PerfettoDsTracerImpl*>(ii.instance);
1100 if (!ret.ds.tracer) {
1101 ds->TraceEpilogue(tls_state);
1102 return ret;
1103 }
1104
1105 FillIterator(&ii, ts, &ret);
1106
1107 ret.ds.tls = reinterpret_cast<struct PerfettoDsTlsImpl*>(tls_state);
1108 return ret;
1109 }
1110
PerfettoTeLlImplNext(struct PerfettoTeCategoryImpl * cat,struct PerfettoTeTimestamp ts,struct PerfettoTeLlImplIterator * iterator)1111 void PerfettoTeLlImplNext(struct PerfettoTeCategoryImpl* cat,
1112 struct PerfettoTeTimestamp ts,
1113 struct PerfettoTeLlImplIterator* iterator) {
1114 auto* tls = reinterpret_cast<perfetto::internal::DataSourceThreadLocalState*>(
1115 iterator->ds.tls);
1116
1117 perfetto::internal::DataSourceType::InstancesIterator ii;
1118 ii.i = iterator->ds.inst_id;
1119 ii.cached_instances = tls->root_tls->cached_instances;
1120 ii.instance =
1121 reinterpret_cast<perfetto::internal::DataSourceInstanceThreadLocalState*>(
1122 iterator->ds.tracer);
1123
1124 perfetto::internal::DataSourceType* ds =
1125 perfetto::shlib::TrackEvent::GetType();
1126
1127 ds->NextIteration</*Traits=*/perfetto::shlib::TracePointTraits>(&ii, tls,
1128 {cat});
1129
1130 iterator->ds.inst_id = ii.i;
1131 tls->root_tls->cached_instances = ii.cached_instances;
1132 iterator->ds.tracer =
1133 reinterpret_cast<struct PerfettoDsTracerImpl*>(ii.instance);
1134
1135 if (!iterator->ds.tracer) {
1136 ds->TraceEpilogue(tls);
1137 return;
1138 }
1139
1140 FillIterator(&ii, ts, iterator);
1141 }
1142
PerfettoTeLlImplBreak(struct PerfettoTeCategoryImpl *,struct PerfettoTeLlImplIterator * iterator)1143 void PerfettoTeLlImplBreak(struct PerfettoTeCategoryImpl*,
1144 struct PerfettoTeLlImplIterator* iterator) {
1145 auto* tls = reinterpret_cast<perfetto::internal::DataSourceThreadLocalState*>(
1146 iterator->ds.tls);
1147
1148 perfetto::internal::DataSourceType* ds =
1149 perfetto::shlib::TrackEvent::GetType();
1150
1151 ds->TraceEpilogue(tls);
1152 }
1153
PerfettoTeLlImplDynCatEnabled(struct PerfettoDsTracerImpl * tracer,PerfettoDsInstanceIndex inst_id,const struct PerfettoTeCategoryDescriptor * dyn_cat)1154 bool PerfettoTeLlImplDynCatEnabled(
1155 struct PerfettoDsTracerImpl* tracer,
1156 PerfettoDsInstanceIndex inst_id,
1157 const struct PerfettoTeCategoryDescriptor* dyn_cat) {
1158 perfetto::internal::DataSourceType* ds =
1159 perfetto::shlib::TrackEvent::GetType();
1160
1161 auto* tls_inst =
1162 reinterpret_cast<perfetto::internal::DataSourceInstanceThreadLocalState*>(
1163 tracer);
1164
1165 auto* incr_state = static_cast<perfetto::shlib::TrackEventIncrementalState*>(
1166 ds->GetIncrementalState(tls_inst, inst_id));
1167
1168 return IsDynamicCategoryEnabled(inst_id, incr_state, *dyn_cat);
1169 }
1170
PerfettoTeLlImplTrackSeen(struct PerfettoTeLlImplIncr * incr,uint64_t uuid)1171 bool PerfettoTeLlImplTrackSeen(struct PerfettoTeLlImplIncr* incr,
1172 uint64_t uuid) {
1173 auto* incr_state =
1174 reinterpret_cast<perfetto::shlib::TrackEventIncrementalState*>(incr);
1175
1176 return !incr_state->seen_track_uuids.insert(uuid).second;
1177 }
1178
PerfettoTeLlImplIntern(struct PerfettoTeLlImplIncr * incr,int32_t type,const void * data,size_t data_size,bool * seen)1179 uint64_t PerfettoTeLlImplIntern(struct PerfettoTeLlImplIncr* incr,
1180 int32_t type,
1181 const void* data,
1182 size_t data_size,
1183 bool* seen) {
1184 auto* incr_state =
1185 reinterpret_cast<perfetto::shlib::TrackEventIncrementalState*>(incr);
1186
1187 auto res = incr_state->iids.FindOrAssign(type, data, data_size);
1188 *seen = !res.newly_assigned;
1189 return res.iid;
1190 }
1191