• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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