• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
18 #define INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
19 
20 // This header contains the key class (DataSource) that a producer app should
21 // override in order to create a custom data source that gets tracing Start/Stop
22 // notifications and emits tracing data.
23 
24 #include <assert.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 
28 #include <array>
29 #include <atomic>
30 #include <functional>
31 #include <memory>
32 #include <mutex>
33 
34 #include "perfetto/base/build_config.h"
35 #include "perfetto/base/compiler.h"
36 #include "perfetto/base/export.h"
37 #include "perfetto/protozero/message.h"
38 #include "perfetto/protozero/message_handle.h"
39 #include "perfetto/tracing/buffer_exhausted_policy.h"
40 #include "perfetto/tracing/core/forward_decls.h"
41 #include "perfetto/tracing/internal/basic_types.h"
42 #include "perfetto/tracing/internal/data_source_internal.h"
43 #include "perfetto/tracing/internal/tracing_muxer.h"
44 #include "perfetto/tracing/locked_handle.h"
45 #include "perfetto/tracing/trace_writer_base.h"
46 
47 #include "protos/perfetto/trace/trace_packet.pbzero.h"
48 
49 // PERFETTO_COMPONENT_EXPORT is used to mark symbols in Perfetto's headers
50 // (typically templates) that are defined by the user outside of Perfetto and
51 // should be made visible outside the current module. (e.g., in Chrome's
52 // component build).
53 #if !defined(PERFETTO_COMPONENT_EXPORT)
54 #define PERFETTO_COMPONENT_EXPORT
55 #endif
56 
57 namespace perfetto {
58 namespace internal {
59 class TracingMuxerImpl;
60 class TrackEventCategoryRegistry;
61 template <typename, const internal::TrackEventCategoryRegistry*>
62 class TrackEventDataSource;
63 }  // namespace internal
64 
65 // Base class with the virtual methods to get start/stop notifications.
66 // Embedders are supposed to derive the templated version below, not this one.
67 class PERFETTO_EXPORT DataSourceBase {
68  public:
69   virtual ~DataSourceBase();
70 
71   // TODO(primiano): change the const& args below to be pointers instead. It
72   // makes it more awkward to handle output arguments and require mutable(s).
73   // This requires synchronizing a breaking API change for existing embedders.
74 
75   // OnSetup() is invoked when tracing is configured. In most cases this happens
76   // just before starting the trace. In the case of deferred start (see
77   // deferred_start in trace_config.proto) start might happen later.
78   class SetupArgs {
79    public:
80     // This is valid only within the scope of the OnSetup() call and must not
81     // be retained.
82     const DataSourceConfig* config = nullptr;
83 
84     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
85     uint32_t internal_instance_index = 0;
86   };
87   virtual void OnSetup(const SetupArgs&);
88 
89   class StartArgs {
90    public:
91     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
92     uint32_t internal_instance_index = 0;
93   };
94   virtual void OnStart(const StartArgs&);
95 
96   class StopArgs {
97    public:
98     virtual ~StopArgs();
99 
100     // HandleAsynchronously() can optionally be called to defer the tracing
101     // session stop and write tracing data just before stopping.
102     // This function returns a closure that must be invoked after the last
103     // trace events have been emitted. The returned closure can be called from
104     // any thread. The caller also needs to explicitly call TraceContext.Flush()
105     // from the last Trace() lambda invocation because no other implicit flushes
106     // will happen after the stop signal.
107     // When this function is called, the tracing service will defer the stop of
108     // the tracing session until the returned closure is invoked.
109     // However, the caller cannot hang onto this closure for too long. The
110     // tracing service will forcefully stop the tracing session without waiting
111     // for pending producers after TraceConfig.data_source_stop_timeout_ms
112     // (default: 5s, can be overridden by Consumers when starting a trace).
113     // If the closure is called after this timeout an error will be logged and
114     // the trace data emitted will not be present in the trace. No other
115     // functional side effects (e.g. crashes or corruptions) will happen. In
116     // other words, it is fine to accidentally hold onto this closure for too
117     // long but, if that happens, some tracing data will be lost.
118     virtual std::function<void()> HandleStopAsynchronously() const = 0;
119 
120     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
121     uint32_t internal_instance_index = 0;
122   };
123   virtual void OnStop(const StopArgs&);
124 };
125 
126 struct DefaultDataSourceTraits {
127   // |IncrementalStateType| can optionally be used store custom per-sequence
128   // incremental data (e.g., interning tables). It should have a Clear() method
129   // for when incremental state needs to be cleared. See
130   // TraceContext::GetIncrementalState().
131   using IncrementalStateType = void;
132   // |TlsStateType| can optionally be used to store custom per-sequence
133   // session data, which is not reset when incremental state is cleared
134   // (e.g. configuration options).
135   using TlsStateType = void;
136 
137   // Allows overriding what type of thread-local state configuration the data
138   // source uses. By default every data source gets independent thread-local
139   // state, which means every instance uses separate trace writers and
140   // incremental state even on the same thread. Some data sources (most notably
141   // the track event data source) want to share trace writers and incremental
142   // state on the same thread.
GetDataSourceTLSDefaultDataSourceTraits143   static internal::DataSourceThreadLocalState* GetDataSourceTLS(
144       internal::DataSourceStaticState* static_state,
145       internal::TracingTLS* root_tls) {
146     auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
147     // The per-type TLS is either zero-initialized or must have been initialized
148     // for this specific data source type.
149     assert(!ds_tls->static_state ||
150            ds_tls->static_state->index == static_state->index);
151     return ds_tls;
152   }
153 };
154 
155 // Templated base class meant to be derived by embedders to create a custom data
156 // source. DataSourceType must be the type of the derived class itself, e.g.:
157 // class MyDataSource : public DataSourceBase<MyDataSource> {...}.
158 //
159 // |DataSourceTraits| allows customizing the behavior of the data source. See
160 // |DefaultDataSourceTraits|.
161 template <typename DataSourceType,
162           typename DataSourceTraits = DefaultDataSourceTraits>
163 class DataSource : public DataSourceBase {
164   struct DefaultTracePointTraits;
165 
166  public:
167   // The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
168   // Override this in your DataSource class to change the default, which is to
169   // drop data on shared memory overruns.
170   constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
171       BufferExhaustedPolicy::kDrop;
172 
173   // Argument passed to the lambda function passed to Trace() (below).
174   class TraceContext {
175    public:
176     using TracePacketHandle =
177         ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;
178 
179     TraceContext(TraceContext&&) noexcept = default;
~TraceContext()180     ~TraceContext() {
181       // If the data source is being intercepted, flush the trace writer after
182       // each trace point to make sure the interceptor sees the data right away.
183       if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted))
184         Flush();
185     }
186 
NewTracePacket()187     TracePacketHandle NewTracePacket() {
188       return tls_inst_->trace_writer->NewTracePacket();
189     }
190 
191     // Forces a commit of the thread-local tracing data written so far to the
192     // service. This is almost never required (tracing data is periodically
193     // committed as trace pages are filled up) and has a non-negligible
194     // performance hit (requires an IPC + refresh of the current thread-local
195     // chunk). The only case when this should be used is when handling OnStop()
196     // asynchronously, to ensure sure that the data is committed before the
197     // Stop timeout expires.
198     // The TracePacketHandle obtained by the last NewTracePacket() call must be
199     // finalized before calling Flush() (either implicitly by going out of scope
200     // or by explicitly calling Finalize()).
201     // |cb| is an optional callback. When non-null it will request the
202     // service to ACK the flush and will be invoked on an internal thread after
203     // the service has  acknowledged it. The callback might be NEVER INVOKED if
204     // the service crashes or the IPC connection is dropped.
205     void Flush(std::function<void()> cb = {}) {
206       tls_inst_->trace_writer->Flush(cb);
207     }
208 
209     // Returns the number of bytes written on the current thread by the current
210     // data-source since its creation.
211     // This can be useful for splitting protos that might grow very large.
written()212     uint64_t written() { return tls_inst_->trace_writer->written(); }
213 
214     // Returns a RAII handle to access the data source instance, guaranteeing
215     // that it won't be deleted on another thread (because of trace stopping)
216     // while accessing it from within the Trace() lambda.
217     // The returned handle can be invalid (nullptr) if tracing is stopped
218     // immediately before calling this. The caller is supposed to check for its
219     // validity before using it. After checking, the handle is guaranteed to
220     // remain valid until the handle goes out of scope.
GetDataSourceLocked()221     LockedHandle<DataSourceType> GetDataSourceLocked() const {
222       auto* internal_state = static_state_.TryGet(instance_index_);
223       if (!internal_state)
224         return LockedHandle<DataSourceType>();
225       return LockedHandle<DataSourceType>(
226           &internal_state->lock,
227           static_cast<DataSourceType*>(internal_state->data_source.get()));
228     }
229 
230     // Post-condition: returned ptr will be non-null.
GetCustomTlsState()231     typename DataSourceTraits::TlsStateType* GetCustomTlsState() {
232       PERFETTO_DCHECK(tls_inst_->data_source_custom_tls);
233       return reinterpret_cast<typename DataSourceTraits::TlsStateType*>(
234           tls_inst_->data_source_custom_tls.get());
235     }
236 
GetIncrementalState()237     typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
238       // Recreate incremental state data if it has been reset by the service.
239       if (tls_inst_->incremental_state_generation !=
240           static_state_.incremental_state_generation.load(
241               std::memory_order_relaxed)) {
242         tls_inst_->incremental_state.reset();
243         CreateIncrementalState(tls_inst_);
244       }
245       return reinterpret_cast<typename DataSourceTraits::IncrementalStateType*>(
246           tls_inst_->incremental_state.get());
247     }
248 
249    private:
250     friend class DataSource;
251     template <typename, const internal::TrackEventCategoryRegistry*>
252     friend class internal::TrackEventDataSource;
TraceContext(internal::DataSourceInstanceThreadLocalState * tls_inst,uint32_t instance_index)253     TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst,
254                  uint32_t instance_index)
255         : tls_inst_(tls_inst), instance_index_(instance_index) {}
256     TraceContext(const TraceContext&) = delete;
257     TraceContext& operator=(const TraceContext&) = delete;
258 
259     internal::DataSourceInstanceThreadLocalState* const tls_inst_;
260     uint32_t const instance_index_;
261   };
262 
263   // The main tracing method. Tracing code should call this passing a lambda as
264   // argument, with the following signature: void(TraceContext).
265   // The lambda will be called synchronously (i.e., always before Trace()
266   // returns) only if tracing is enabled and the data source has been enabled in
267   // the tracing config.
268   // The lambda can be called more than once per Trace() call, in the case of
269   // concurrent tracing sessions (or even if the data source is instantiated
270   // twice within the same trace config).
271   template <typename Lambda>
Trace(Lambda tracing_fn)272   static void Trace(Lambda tracing_fn) {
273     CallIfEnabled<DefaultTracePointTraits>([&tracing_fn](uint32_t instances) {
274       TraceWithInstances<DefaultTracePointTraits>(instances,
275                                                   std::move(tracing_fn));
276     });
277   }
278 
279   // An efficient trace point guard for checking if this data source is active.
280   // |callback| is a function which will only be called if there are active
281   // instances. It is given an instance state parameter, which should be passed
282   // to TraceWithInstances() to actually record trace data.
283   template <typename Traits = DefaultTracePointTraits, typename Callback>
284   static void CallIfEnabled(Callback callback,
285                             typename Traits::TracePointData trace_point_data =
286                                 {}) PERFETTO_ALWAYS_INLINE {
287     // |instances| is a per-class bitmap that tells:
288     // 1. If the data source is enabled at all.
289     // 2. The index of the slot within |static_state_| that holds the instance
290     //    state. In turn this allows to map the data source to the tracing
291     //    session and buffers.
292     // memory_order_relaxed is okay because:
293     // - |instances| is re-read with an acquire barrier below if this succeeds.
294     // - The code between this point and the acquire-load is based on static
295     //    storage which has indefinite lifetime.
296     uint32_t instances = Traits::GetActiveInstances(trace_point_data)
297                              ->load(std::memory_order_relaxed);
298 
299     // This is the tracing fast-path. Bail out immediately if tracing is not
300     // enabled (or tracing is enabled but not for this data source).
301     if (PERFETTO_LIKELY(!instances))
302       return;
303     callback(instances);
304   }
305 
306   // The "lower half" of a trace point which actually performs tracing after
307   // this data source has been determined to be active.
308   // |instances| must be the instance state value retrieved through
309   // CallIfEnabled().
310   // |tracing_fn| will be called to record trace data as in Trace().
311   //
312   // |trace_point_data| is an optional parameter given to |Traits::
313   // GetActiveInstances| to make it possible to use custom storage for
314   // the data source enabled state. This is, for example, used by TrackEvent to
315   // implement per-tracing category enabled states.
316   //
317   // TODO(primiano): all the stuff below should be outlined from the trace
318   // point. Or at least we should have some compile-time traits like
319   // kOptimizeBinarySize / kOptimizeTracingLatency.
320   template <typename Traits = DefaultTracePointTraits, typename Lambda>
321   static void TraceWithInstances(
322       uint32_t instances,
323       Lambda tracing_fn,
324       typename Traits::TracePointData trace_point_data = {}) {
325     PERFETTO_DCHECK(instances);
326     constexpr auto kMaxDataSourceInstances = internal::kMaxDataSourceInstances;
327 
328     // See tracing_muxer.h for the structure of the TLS.
329     auto* tracing_impl = internal::TracingMuxer::Get();
330     if (PERFETTO_UNLIKELY(!tls_state_))
331       tls_state_ = GetOrCreateDataSourceTLS(&static_state_);
332 
333     // Avoid re-entering the trace point recursively.
334     if (PERFETTO_UNLIKELY(tls_state_->root_tls->is_in_trace_point))
335       return;
336     internal::ScopedReentrancyAnnotator scoped_annotator(*tls_state_->root_tls);
337 
338     // TracingTLS::generation is a global monotonic counter that is incremented
339     // every time a tracing session is stopped. We use that as a signal to force
340     // a slow-path garbage collection of all the trace writers for the current
341     // thread and to destroy the ones that belong to tracing sessions that have
342     // ended. This is to avoid having too many TraceWriter instances alive, each
343     // holding onto one chunk of the shared memory buffer.
344     // Rationale why memory_order_relaxed should be fine:
345     // - The TraceWriter object that we use is always constructed and destructed
346     //   on the current thread. There is no risk of accessing a half-initialized
347     //   TraceWriter (which would be really bad).
348     // - In the worst case, in the case of a race on the generation check, we
349     //   might end up using a TraceWriter for the same data source that belongs
350     //   to a stopped session. This is not really wrong, as we don't give any
351     //   guarantee on the global atomicity of the stop. In the worst case the
352     //   service will reject the data commit if this arrives too late.
353 
354     if (PERFETTO_UNLIKELY(
355             tls_state_->root_tls->generation !=
356             tracing_impl->generation(std::memory_order_relaxed))) {
357       // Will update root_tls->generation.
358       tracing_impl->DestroyStoppedTraceWritersForCurrentThread();
359     }
360 
361     for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
362       internal::DataSourceState* instance_state =
363           static_state_.TryGetCached(instances, i);
364       if (!instance_state)
365         continue;
366 
367       // Even if we passed the check above, the DataSourceInstance might be
368       // still destroyed concurrently while this code runs. The code below is
369       // designed to deal with such race, as follows:
370       // - We don't access the user-defined data source instance state. The only
371       //   bits of state we use are |backend_id| and |buffer_id|.
372       // - Beyond those two integers, we access only the TraceWriter here. The
373       //   TraceWriter is always safe because it lives on the TLS.
374       // - |instance_state| is backed by static storage, so the pointer is
375       //   always valid, even after the data source instance is destroyed.
376       // - In the case of a race-on-destruction, we'll still see the latest
377       //   backend_id and buffer_id and in the worst case keep trying writing
378       //   into the tracing shared memory buffer after stopped. But this isn't
379       //   really any worse than the case of the stop IPC being delayed by the
380       //   kernel scheduler. The tracing service is robust against data commit
381       //   attemps made after tracing is stopped.
382       // There is a theoretical race that would case the wrong behavior w.r.t
383       // writing data in the wrong buffer, but it's so rare that we ignore it:
384       // if the data source is stopped and started kMaxDataSourceInstances
385       // times (so that the same id is recycled) while we are in this function,
386       // we might end up reusing the old data source's backend_id and buffer_id
387       // for the new one, because we don't see the generation change past this
388       // point. But stopping and starting tracing (even once) takes so much
389       // handshaking to make this extremely unrealistic.
390 
391       auto& tls_inst = tls_state_->per_instance[i];
392       if (PERFETTO_UNLIKELY(!tls_inst.trace_writer)) {
393         // Here we need an acquire barrier, which matches the release-store made
394         // by TracingMuxerImpl::SetupDataSource(), to ensure that the backend_id
395         // and buffer_id are consistent.
396         instances = Traits::GetActiveInstances(trace_point_data)
397                         ->load(std::memory_order_acquire);
398         instance_state = static_state_.TryGetCached(instances, i);
399         if (!instance_state || !instance_state->trace_lambda_enabled)
400           continue;
401         tls_inst.muxer_id_for_testing = instance_state->muxer_id_for_testing;
402         tls_inst.backend_id = instance_state->backend_id;
403         tls_inst.backend_connection_id = instance_state->backend_connection_id;
404         tls_inst.buffer_id = instance_state->buffer_id;
405         tls_inst.data_source_instance_id =
406             instance_state->data_source_instance_id;
407         tls_inst.is_intercepted = instance_state->interceptor_id != 0;
408         tls_inst.trace_writer = tracing_impl->CreateTraceWriter(
409             &static_state_, i, instance_state,
410             DataSourceType::kBufferExhaustedPolicy);
411         CreateIncrementalState(&tls_inst);
412         CreateDataSourceCustomTLS(TraceContext(&tls_inst, i));
413         // Even in the case of out-of-IDs, SharedMemoryArbiterImpl returns a
414         // NullTraceWriter. The returned pointer should never be null.
415         assert(tls_inst.trace_writer);
416       }
417 
418       tracing_fn(TraceContext(&tls_inst, i));
419     }
420   }
421 
422   // Registers the data source on all tracing backends, including ones that
423   // connect after the registration. Doing so enables the data source to receive
424   // Setup/Start/Stop notifications and makes the Trace() method work when
425   // tracing is enabled and the data source is selected.
426   // This must be called after Tracing::Initialize().
427   // Can return false to signal failure if attemping to register more than
428   // kMaxDataSources (32) data sources types or if tracing hasn't been
429   // initialized.
430   // The optional |constructor_args| will be passed to the data source when it
431   // is constructed.
432   template <class... Args>
Register(const DataSourceDescriptor & descriptor,const Args &...constructor_args)433   static bool Register(const DataSourceDescriptor& descriptor,
434                        const Args&... constructor_args) {
435     // Silences -Wunused-variable warning in case the trace method is not used
436     // by the translation unit that declares the data source.
437     (void)static_state_;
438     (void)tls_state_;
439 
440     auto factory = [constructor_args...]() {
441       return std::unique_ptr<DataSourceBase>(
442           new DataSourceType(constructor_args...));
443     };
444     auto* tracing_impl = internal::TracingMuxer::Get();
445     return tracing_impl->RegisterDataSource(descriptor, factory,
446                                             &static_state_);
447   }
448 
449   // Updates the data source descriptor.
UpdateDescriptor(const DataSourceDescriptor & descriptor)450   static void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
451     auto* tracing_impl = internal::TracingMuxer::Get();
452     tracing_impl->UpdateDataSourceDescriptor(descriptor, &static_state_);
453   }
454 
455  private:
456   // Traits for customizing the behavior of a specific trace point.
457   struct DefaultTracePointTraits {
458     // By default, every call to DataSource::Trace() will record trace events
459     // for every active instance of that data source. A single trace point can,
460     // however, use a custom set of enable flags for more fine grained control
461     // of when that trace point is active.
462     //
463     // DANGER: when doing this, the data source must use the appropriate memory
464     // fences when changing the state of the bitmap.
465     //
466     // |TraceWithInstances| may be optionally given an additional parameter for
467     // looking up the enable flags. That parameter is passed as |TracePointData|
468     // to |GetActiveInstances|. This is, for example, used by TrackEvent to
469     // implement per-category enabled states.
470     struct TracePointData {};
GetActiveInstancesDefaultTracePointTraits471     static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
472       return &static_state_.valid_instances;
473     }
474   };
475 
476   // Create the user provided incremental state in the given thread-local
477   // storage. Note: The second parameter here is used to specialize the case
478   // where there is no incremental state type.
479   template <typename T>
CreateIncrementalStateImpl(internal::DataSourceInstanceThreadLocalState * tls_inst,const T *)480   static void CreateIncrementalStateImpl(
481       internal::DataSourceInstanceThreadLocalState* tls_inst,
482       const T*) {
483     PERFETTO_DCHECK(!tls_inst->incremental_state);
484     tls_inst->incremental_state_generation =
485         static_state_.incremental_state_generation.load(
486             std::memory_order_relaxed);
487     tls_inst->incremental_state =
488         internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
489             reinterpret_cast<void*>(new T()),
490             [](void* p) { delete reinterpret_cast<T*>(p); });
491   }
492 
CreateIncrementalStateImpl(internal::DataSourceInstanceThreadLocalState *,const void *)493   static void CreateIncrementalStateImpl(
494       internal::DataSourceInstanceThreadLocalState*,
495       const void*) {}
496 
CreateIncrementalState(internal::DataSourceInstanceThreadLocalState * tls_inst)497   static void CreateIncrementalState(
498       internal::DataSourceInstanceThreadLocalState* tls_inst) {
499     CreateIncrementalStateImpl(
500         tls_inst,
501         static_cast<typename DataSourceTraits::IncrementalStateType*>(nullptr));
502   }
503 
504   // Create the user provided custom tls state in the given TraceContext's
505   // thread-local storage.  Note: The second parameter here is used to
506   // specialize the case where there is no incremental state type.
507   template <typename T>
CreateDataSourceCustomTLSImpl(const TraceContext & trace_context,const T *)508   static void CreateDataSourceCustomTLSImpl(const TraceContext& trace_context,
509                                             const T*) {
510     PERFETTO_DCHECK(!trace_context.tls_inst_->data_source_custom_tls);
511     trace_context.tls_inst_->data_source_custom_tls =
512         internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
513             reinterpret_cast<void*>(new T(trace_context)),
514             [](void* p) { delete reinterpret_cast<T*>(p); });
515   }
516 
CreateDataSourceCustomTLSImpl(const TraceContext &,const void *)517   static void CreateDataSourceCustomTLSImpl(const TraceContext&, const void*) {}
518 
CreateDataSourceCustomTLS(const TraceContext & trace_context)519   static void CreateDataSourceCustomTLS(const TraceContext& trace_context) {
520     CreateDataSourceCustomTLSImpl(
521         trace_context,
522         static_cast<typename DataSourceTraits::TlsStateType*>(nullptr));
523   }
524 
525   // Note that the returned object is one per-thread per-data-source-type, NOT
526   // per data-source *instance*.
GetOrCreateDataSourceTLS(internal::DataSourceStaticState * static_state)527   static internal::DataSourceThreadLocalState* GetOrCreateDataSourceTLS(
528       internal::DataSourceStaticState* static_state) {
529 #if PERFETTO_BUILDFLAG(PERFETTO_OS_IOS)
530     PERFETTO_FATAL("Data source TLS not supported on iOS, see b/158814068");
531 #endif
532     auto* tracing_impl = internal::TracingMuxer::Get();
533     internal::TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS();
534     internal::DataSourceThreadLocalState* ds_tls =
535         DataSourceTraits::GetDataSourceTLS(static_state, root_tls);
536     // We keep re-initializing as the initialization is idempotent and not worth
537     // the code for extra checks.
538     ds_tls->static_state = static_state;
539     assert(!ds_tls->root_tls || ds_tls->root_tls == root_tls);
540     ds_tls->root_tls = root_tls;
541     return ds_tls;
542   }
543 
544   // Static state. Accessed by the static Trace() method fastpaths.
545   static internal::DataSourceStaticState static_state_;
546 
547   // This TLS object is a cached raw pointer and has deliberately no destructor.
548   // The Platform implementation is supposed to create and manage the lifetime
549   // of the Platform::ThreadLocalObject and take care of destroying it.
550   // This is because non-POD thread_local variables have subtleties (global
551   // destructors) that we need to defer to the embedder. In chromium's platform
552   // implementation, for instance, the tls slot is implemented using
553   // chromium's base::ThreadLocalStorage.
554   static PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState* tls_state_;
555 };
556 
557 // static
558 template <typename T, typename D>
559 internal::DataSourceStaticState DataSource<T, D>::static_state_;
560 // static
561 template <typename T, typename D>
562 PERFETTO_THREAD_LOCAL internal::DataSourceThreadLocalState*
563     DataSource<T, D>::tls_state_;
564 
565 }  // namespace perfetto
566 
567 // If placed at the end of a macro declaration, eats the semicolon at the end of
568 // the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra
569 // semicolons.
570 #define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \
571   extern int perfetto_internal_unused
572 
573 // This macro must be used once for each data source next to the data source's
574 // declaration.
575 #define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...)              \
576   template <>                                                         \
577   PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \
578       perfetto::DataSource<__VA_ARGS__>::static_state_
579 
580 // This macro must be used once for each data source in one source file to
581 // allocate static storage for the data source's static state.
582 //
583 // Note: if MSVC fails with a C2086 (redefinition) error here, use the
584 // permissive- flag to enable standards-compliant mode. See
585 // https://developercommunity.visualstudio.com/content/problem/319447/
586 // explicit-specialization-of-static-data-member-inco.html.
587 #define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...)               \
588   template <>                                                         \
589   PERFETTO_COMPONENT_EXPORT perfetto::internal::DataSourceStaticState \
590       perfetto::DataSource<__VA_ARGS__>::static_state_ {}
591 
592 #endif  // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
593