• 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/protozero/message_handle.h"
35 #include "perfetto/tracing/buffer_exhausted_policy.h"
36 #include "perfetto/tracing/core/flush_flags.h"
37 #include "perfetto/tracing/core/forward_decls.h"
38 #include "perfetto/tracing/internal/basic_types.h"
39 #include "perfetto/tracing/internal/data_source_internal.h"
40 #include "perfetto/tracing/internal/data_source_type.h"
41 #include "perfetto/tracing/internal/tracing_muxer.h"
42 #include "perfetto/tracing/locked_handle.h"
43 #include "perfetto/tracing/trace_writer_base.h"
44 
45 #include "protos/perfetto/trace/trace_packet.pbzero.h"
46 
47 // DEPRECATED: Instead of using this macro, prefer specifying symbol linkage
48 // attributes explicitly using the `_WITH_ATTRS` macro variants (e.g.,
49 // PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS). This avoids
50 // potential macro definition collisions between two libraries using Perfetto.
51 //
52 // PERFETTO_COMPONENT_EXPORT is used to mark symbols in Perfetto's headers
53 // (typically templates) that are defined by the user outside of Perfetto and
54 // should be made visible outside the current module. (e.g., in Chrome's
55 // component build).
56 #if !defined(PERFETTO_COMPONENT_EXPORT)
57 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_MSVC)
58 // Workaround for C4003: not enough arguments for function-like macro invocation
59 // 'PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE'
60 #define PERFETTO_COMPONENT_EXPORT __declspec()
61 #else
62 #define PERFETTO_COMPONENT_EXPORT
63 #endif
64 #endif
65 
66 namespace perfetto {
67 namespace internal {
68 class TracingMuxerImpl;
69 class TrackEventCategoryRegistry;
70 template <typename, const internal::TrackEventCategoryRegistry*>
71 class TrackEventDataSource;
72 }  // namespace internal
73 
74 namespace shlib {
75 class TrackEvent;
76 }  // namespace shlib
77 
78 namespace test {
79 class DataSourceInternalForTest;
80 }  // namespace test
81 
82 // Base class with the virtual methods to get start/stop notifications.
83 // Embedders are supposed to derive the templated version below, not this one.
84 class PERFETTO_EXPORT_COMPONENT DataSourceBase {
85  public:
86   virtual ~DataSourceBase();
87 
88   // TODO(primiano): change the const& args below to be pointers instead. It
89   // makes it more awkward to handle output arguments and require mutable(s).
90   // This requires synchronizing a breaking API change for existing embedders.
91 
92   // OnSetup() is invoked when tracing is configured. In most cases this happens
93   // just before starting the trace. In the case of deferred start (see
94   // deferred_start in trace_config.proto) start might happen later.
95   //
96   // Can be called from any thread.
97   class SetupArgs {
98    public:
99     // This is valid only within the scope of the OnSetup() call and must not
100     // be retained.
101     const DataSourceConfig* config = nullptr;
102 
103     // Backend type.
104     BackendType backend_type = kUnspecifiedBackend;
105 
106     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
107     uint32_t internal_instance_index = 0;
108   };
109   virtual void OnSetup(const SetupArgs&);
110 
111   class StartArgs {
112    public:
113     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
114     uint32_t internal_instance_index = 0;
115   };
116   // Invoked after tracing is actually started.
117   //
118   // Can be called from any thread.
119   virtual void OnStart(const StartArgs&);
120 
121   class PERFETTO_EXPORT_COMPONENT StopArgs {
122    public:
123     virtual ~StopArgs();
124 
125     // HandleAsynchronously() can optionally be called to defer the tracing
126     // session stop and write tracing data just before stopping.
127     // This function returns a closure that must be invoked after the last
128     // trace events have been emitted. The returned closure can be called from
129     // any thread. The caller also needs to explicitly call TraceContext.Flush()
130     // from the last Trace() lambda invocation because no other implicit flushes
131     // will happen after the stop signal.
132     // When this function is called, the tracing service will defer the stop of
133     // the tracing session until the returned closure is invoked.
134     // However, the caller cannot hang onto this closure for too long. The
135     // tracing service will forcefully stop the tracing session without waiting
136     // for pending producers after TraceConfig.data_source_stop_timeout_ms
137     // (default: 5s, can be overridden by Consumers when starting a trace).
138     // If the closure is called after this timeout an error will be logged and
139     // the trace data emitted will not be present in the trace. No other
140     // functional side effects (e.g. crashes or corruptions) will happen. In
141     // other words, it is fine to accidentally hold onto this closure for too
142     // long but, if that happens, some tracing data will be lost.
143     virtual std::function<void()> HandleStopAsynchronously() const = 0;
144 
145     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
146     uint32_t internal_instance_index = 0;
147   };
148   // Invoked before tracing is stopped.
149   //
150   // Can be called from any thread. Blocking this for too long it's not a good
151   // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
152   // disabling the data source instance.
153   virtual void OnStop(const StopArgs&);
154 
155   class ClearIncrementalStateArgs {
156    public:
157     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
158     uint32_t internal_instance_index = 0;
159   };
160   // Invoked before marking the thread local per-instance incremental state
161   // outdated.
162   //
163   // Can be called from any thread.
164   virtual void WillClearIncrementalState(const ClearIncrementalStateArgs&);
165 
166   class FlushArgs {
167    public:
168     virtual ~FlushArgs();
169 
170     // HandleFlushAsynchronously() can be called to postpone acknowledging the
171     // flush request. This function returns a closure that must be invoked after
172     // the flush request has been processed. The returned closure can be called
173     // from any thread.
174     virtual std::function<void()> HandleFlushAsynchronously() const = 0;
175 
176     // The index of this data source instance (0..kMaxDataSourceInstances - 1).
177     uint32_t internal_instance_index = 0;
178 
179     // The reason and initiator of the flush. See flush_flags.h .
180     FlushFlags flush_flags;
181   };
182   // Called when the tracing service requests a Flush. Users can override this
183   // to tell other threads to flush their TraceContext for this data source
184   // (the library cannot execute code on all the threads on its own).
185   //
186   // Can be called from any thread. Blocking this for too long it's not a good
187   // idea and can cause deadlocks. Use HandleAsynchronously() to postpone
188   // sending the flush acknowledgement to the service.
189   virtual void OnFlush(const FlushArgs&);
190 
191   // Determines whether a startup session can be adopted by a service-initiated
192   // tracing session (i.e. whether their configs are compatible).
193   virtual bool CanAdoptStartupSession(const DataSourceConfig& startup_config,
194                                       const DataSourceConfig& service_config);
195 };
196 
197 struct DefaultDataSourceTraits {
198   // |IncrementalStateType| can optionally be used store custom per-sequence
199   // incremental data (e.g., interning tables).
200   using IncrementalStateType = void;
201   // |TlsStateType| can optionally be used to store custom per-sequence
202   // session data, which is not reset when incremental state is cleared
203   // (e.g. configuration options).
204   using TlsStateType = void;
205 
206   // Allows overriding what type of thread-local state configuration the data
207   // source uses. By default every data source gets independent thread-local
208   // state, which means every instance uses separate trace writers and
209   // incremental state even on the same thread. Some data sources (most notably
210   // the track event data source) want to share trace writers and incremental
211   // state on the same thread.
GetDataSourceTLSDefaultDataSourceTraits212   static internal::DataSourceThreadLocalState* GetDataSourceTLS(
213       internal::DataSourceStaticState* static_state,
214       internal::TracingTLS* root_tls) {
215     auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
216     // ds_tls->static_state can be:
217     // * nullptr
218     // * equal to static_state
219     // * equal to the static state of a different data source, in tests (when
220     //   ResetForTesting() has been used)
221     // In any case, there's no need to do anything, the caller will reinitialize
222     // static_state.
223     return ds_tls;
224   }
225 };
226 
227 // Holds the type for a DataSource. Accessed by the static Trace() method
228 // fastpaths. This allows redefinitions under a component where a component
229 // specific export macro is used.
230 // Due to C2086 (redefinition) error on MSVC/clang-cl, internal::DataSourceType
231 // can't be a static data member. To avoid explicit specialization after
232 // instantiation error, type() needs to be in a template helper class that's
233 // instantiated independently from DataSource. See b/280777748.
234 template <typename DerivedDataSource,
235           typename DataSourceTraits = DefaultDataSourceTraits>
236 struct DataSourceHelper {
typeDataSourceHelper237   static internal::DataSourceType& type() {
238     static perfetto::internal::DataSourceType type_;
239     return type_;
240   }
241 };
242 
243 // Templated base class meant to be derived by embedders to create a custom data
244 // source. DerivedDataSource must be the type of the derived class itself, e.g.:
245 // class MyDataSource : public DataSource<MyDataSource> {...}.
246 //
247 // |DataSourceTraits| allows customizing the behavior of the data source. See
248 // |DefaultDataSourceTraits|.
249 template <typename DerivedDataSource,
250           typename DataSourceTraits = DefaultDataSourceTraits>
251 class DataSource : public DataSourceBase {
252   struct DefaultTracePointTraits;
253   using Helper = DataSourceHelper<DerivedDataSource, DataSourceTraits>;
254 
255  public:
256   // The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
257   // Override this in your DataSource class to change the default, which is to
258   // drop data on shared memory overruns.
259   constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
260       BufferExhaustedPolicy::kDrop;
261 
262   // When this flag is false, we cannot have multiple instances of this data
263   // source. When a data source is already active and if we attempt
264   // to start another instance of that data source (via another tracing
265   // session), it will fail to start the second instance of data source.
266   static constexpr bool kSupportsMultipleInstances = true;
267 
268   // When this flag is true, DataSource callbacks (OnSetup, OnStart, etc.) are
269   // called under the lock (the same that is used in GetDataSourceLocked
270   // function). This is not recommended because it can lead to deadlocks, but
271   // it was the default behavior for a long time and some embedders rely on it
272   // to protect concurrent access to the DataSource members. So we keep the
273   // "true" value as the default.
274   static constexpr bool kRequiresCallbacksUnderLock = true;
275 
276   // Argument passed to the lambda function passed to Trace() (below).
277   class TraceContext {
278    public:
279     using TracePacketHandle =
280         ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;
281 
282     TraceContext(TraceContext&&) noexcept = default;
~TraceContext()283     ~TraceContext() {
284       // If the data source is being intercepted, flush the trace writer after
285       // each trace point to make sure the interceptor sees the data right away.
286       if (PERFETTO_UNLIKELY(tls_inst_->is_intercepted))
287         Flush();
288     }
289 
290     // Adds an empty trace packet to the trace to ensure that the service can
291     // safely read the last event from the trace buffer.
292     // See PERFETTO_INTERNAL_ADD_EMPTY_EVENT macros for context.
AddEmptyTracePacket()293     void AddEmptyTracePacket() {
294       // If nothing was written since the last empty packet, there's nothing to
295       // scrape, so adding more empty packets serves no purpose.
296       if (tls_inst_->trace_writer->written() ==
297           tls_inst_->last_empty_packet_position) {
298         return;
299       }
300       tls_inst_->trace_writer->NewTracePacket();
301       tls_inst_->last_empty_packet_position =
302           tls_inst_->trace_writer->written();
303     }
304 
NewTracePacket()305     TracePacketHandle NewTracePacket() {
306       return tls_inst_->trace_writer->NewTracePacket();
307     }
308 
309     // Forces a commit of the thread-local tracing data written so far to the
310     // service. This is almost never required (tracing data is periodically
311     // committed as trace pages are filled up) and has a non-negligible
312     // performance hit (requires an IPC + refresh of the current thread-local
313     // chunk). The only case when this should be used is when handling OnStop()
314     // asynchronously, to ensure sure that the data is committed before the
315     // Stop timeout expires.
316     // The TracePacketHandle obtained by the last NewTracePacket() call must be
317     // finalized before calling Flush() (either implicitly by going out of scope
318     // or by explicitly calling Finalize()).
319     // |cb| is an optional callback. When non-null it will request the
320     // service to ACK the flush and will be invoked on an internal thread after
321     // the service has  acknowledged it. The callback might be NEVER INVOKED if
322     // the service crashes or the IPC connection is dropped.
323     void Flush(std::function<void()> cb = {}) {
324       tls_inst_->trace_writer->Flush(cb);
325     }
326 
327     // Returns the number of bytes written on the current thread by the current
328     // data-source since its creation.
329     // This can be useful for splitting protos that might grow very large.
written()330     uint64_t written() { return tls_inst_->trace_writer->written(); }
331 
332     // Returns a RAII handle to access the data source instance, guaranteeing
333     // that it won't be deleted on another thread (because of trace stopping)
334     // while accessing it from within the Trace() lambda.
335     // The returned handle can be invalid (nullptr) if tracing is stopped
336     // immediately before calling this. The caller is supposed to check for its
337     // validity before using it. After checking, the handle is guaranteed to
338     // remain valid until the handle goes out of scope.
GetDataSourceLocked()339     LockedHandle<DerivedDataSource> GetDataSourceLocked() const {
340       auto* internal_state =
341           Helper::type().static_state()->TryGet(instance_index_);
342       if (!internal_state)
343         return LockedHandle<DerivedDataSource>();
344       std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
345       return LockedHandle<DerivedDataSource>(
346           std::move(lock),
347           static_cast<DerivedDataSource*>(internal_state->data_source.get()));
348     }
349 
350     // Post-condition: returned ptr will be non-null.
GetCustomTlsState()351     typename DataSourceTraits::TlsStateType* GetCustomTlsState() {
352       PERFETTO_DCHECK(tls_inst_->data_source_custom_tls);
353       return reinterpret_cast<typename DataSourceTraits::TlsStateType*>(
354           tls_inst_->data_source_custom_tls.get());
355     }
356 
GetIncrementalState()357     typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
358       return static_cast<typename DataSourceTraits::IncrementalStateType*>(
359           Helper::type().GetIncrementalState(tls_inst_, instance_index_));
360     }
361 
362    private:
363     friend class DataSource;
364     template <typename, const internal::TrackEventCategoryRegistry*>
365     friend class internal::TrackEventDataSource;
TraceContext(internal::DataSourceInstanceThreadLocalState * tls_inst,uint32_t instance_index)366     TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst,
367                  uint32_t instance_index)
368         : tls_inst_(tls_inst), instance_index_(instance_index) {}
369     TraceContext(const TraceContext&) = delete;
370     TraceContext& operator=(const TraceContext&) = delete;
371 
372     internal::DataSourceInstanceThreadLocalState* const tls_inst_;
373     uint32_t const instance_index_;
374   };
375 
376   // The main tracing method. Tracing code should call this passing a lambda as
377   // argument, with the following signature: void(TraceContext).
378   // The lambda will be called synchronously (i.e., always before Trace()
379   // returns) only if tracing is enabled and the data source has been enabled in
380   // the tracing config.
381   // The lambda can be called more than once per Trace() call, in the case of
382   // concurrent tracing sessions (or even if the data source is instantiated
383   // twice within the same trace config).
384   template <typename Lambda>
Trace(Lambda tracing_fn)385   static void Trace(Lambda tracing_fn) {
386     CallIfEnabled<DefaultTracePointTraits>([&tracing_fn](uint32_t instances) {
387       TraceWithInstances<DefaultTracePointTraits>(instances,
388                                                   std::move(tracing_fn));
389     });
390   }
391 
392   // An efficient trace point guard for checking if this data source is active.
393   // |callback| is a function which will only be called if there are active
394   // instances. It is given an instance state parameter, which should be passed
395   // to TraceWithInstances() to actually record trace data.
396   template <typename Traits = DefaultTracePointTraits, typename Callback>
397   static void CallIfEnabled(Callback callback,
398                             typename Traits::TracePointData trace_point_data =
399                                 {}) PERFETTO_ALWAYS_INLINE {
400     // |instances| is a per-class bitmap that tells:
401     // 1. If the data source is enabled at all.
402     // 2. The index of the slot within
403     //    internal::DataSourceStaticState::instances that holds the instance
404     //    state. In turn this allows to map the data source to the tracing
405     //    session and buffers.
406     // memory_order_relaxed is okay because:
407     // - |instances| is re-read with an acquire barrier below if this succeeds.
408     // - The code between this point and the acquire-load is based on static
409     //    storage which has indefinite lifetime.
410     uint32_t instances = Traits::GetActiveInstances(trace_point_data)
411                              ->load(std::memory_order_relaxed);
412 
413     // This is the tracing fast-path. Bail out immediately if tracing is not
414     // enabled (or tracing is enabled but not for this data source).
415     if (PERFETTO_LIKELY(!instances))
416       return;
417     callback(instances);
418   }
419 
420   // The "lower half" of a trace point which actually performs tracing after
421   // this data source has been determined to be active.
422   // |instances| must be the instance state value retrieved through
423   // CallIfEnabled().
424   // |tracing_fn| will be called to record trace data as in Trace().
425   //
426   // |trace_point_data| is an optional parameter given to |Traits::
427   // GetActiveInstances| to make it possible to use custom storage for
428   // the data source enabled state. This is, for example, used by TrackEvent to
429   // implement per-tracing category enabled states.
430   template <typename Traits = DefaultTracePointTraits, typename Lambda>
431   static void TraceWithInstances(
432       uint32_t cached_instances,
433       Lambda tracing_fn,
434       typename Traits::TracePointData trace_point_data = {}) {
435     PERFETTO_DCHECK(cached_instances);
436 
437     if (!Helper::type().template TracePrologue<DataSourceTraits, Traits>(
438             &tls_state_, &cached_instances, trace_point_data)) {
439       return;
440     }
441 
442     for (internal::DataSourceType::InstancesIterator it =
443              Helper::type().template BeginIteration<Traits>(
444                  cached_instances, tls_state_, trace_point_data);
445          it.instance; Helper::type().template NextIteration<Traits>(
446              &it, tls_state_, trace_point_data)) {
447       tracing_fn(TraceContext(it.instance, it.i));
448     }
449 
450     Helper::type().TraceEpilogue(tls_state_);
451   }
452 
453   // Registers the data source on all tracing backends, including ones that
454   // connect after the registration. Doing so enables the data source to receive
455   // Setup/Start/Stop notifications and makes the Trace() method work when
456   // tracing is enabled and the data source is selected.
457   // This must be called after Tracing::Initialize().
458   // Can return false to signal failure if attemping to register more than
459   // kMaxDataSources (32) data sources types or if tracing hasn't been
460   // initialized.
461   // The optional |constructor_args| will be passed to the data source when it
462   // is constructed.
463   template <class... Args>
Register(const DataSourceDescriptor & descriptor,const Args &...constructor_args)464   static bool Register(const DataSourceDescriptor& descriptor,
465                        const Args&... constructor_args) {
466     // Silences -Wunused-variable warning in case the trace method is not used
467     // by the translation unit that declares the data source.
468     (void)tls_state_;
469 
470     auto factory = [constructor_args...]() {
471       return std::unique_ptr<DataSourceBase>(
472           new DerivedDataSource(constructor_args...));
473     };
474     constexpr bool no_flush =
475         std::is_same_v<decltype(&DerivedDataSource::OnFlush),
476                        decltype(&DataSourceBase::OnFlush)>;
477     internal::DataSourceParams params{
478         DerivedDataSource::kSupportsMultipleInstances,
479         DerivedDataSource::kRequiresCallbacksUnderLock};
480     return Helper::type().Register(
481         descriptor, factory, params, DerivedDataSource::kBufferExhaustedPolicy,
482         no_flush,
483         GetCreateTlsFn(
484             static_cast<typename DataSourceTraits::TlsStateType*>(nullptr)),
485         GetCreateIncrementalStateFn(
486             static_cast<typename DataSourceTraits::IncrementalStateType*>(
487                 nullptr)),
488         nullptr);
489   }
490 
491   // Updates the data source descriptor.
UpdateDescriptor(const DataSourceDescriptor & descriptor)492   static void UpdateDescriptor(const DataSourceDescriptor& descriptor) {
493     Helper::type().UpdateDescriptor(descriptor);
494   }
495 
496  private:
497   friend ::perfetto::test::DataSourceInternalForTest;
498   friend ::perfetto::shlib::TrackEvent;
499   // Traits for customizing the behavior of a specific trace point.
500   struct DefaultTracePointTraits {
501     // By default, every call to DataSource::Trace() will record trace events
502     // for every active instance of that data source. A single trace point can,
503     // however, use a custom set of enable flags for more fine grained control
504     // of when that trace point is active.
505     //
506     // DANGER: when doing this, the data source must use the appropriate memory
507     // fences when changing the state of the bitmap.
508     //
509     // |TraceWithInstances| may be optionally given an additional parameter for
510     // looking up the enable flags. That parameter is passed as |TracePointData|
511     // to |GetActiveInstances|. This is, for example, used by TrackEvent to
512     // implement per-category enabled states.
513     struct TracePointData {};
GetActiveInstancesDefaultTracePointTraits514     static constexpr std::atomic<uint32_t>* GetActiveInstances(TracePointData) {
515       return Helper::type().valid_instances();
516     }
517   };
518 
519   template <typename T>
520   static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
CreateIncrementalState(internal::DataSourceInstanceThreadLocalState *,uint32_t,void *)521   CreateIncrementalState(internal::DataSourceInstanceThreadLocalState*,
522                          uint32_t,
523                          void*) {
524     return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
525         reinterpret_cast<void*>(new T()),
526         [](void* p) { delete reinterpret_cast<T*>(p); });
527   }
528 
529   // The second parameter here is used to specialize the case where there is no
530   // incremental state type.
531   template <typename T>
532   static internal::DataSourceType::CreateIncrementalStateFn
GetCreateIncrementalStateFn(const T *)533   GetCreateIncrementalStateFn(const T*) {
534     return &CreateIncrementalState<T>;
535   }
536 
537   static internal::DataSourceType::CreateIncrementalStateFn
GetCreateIncrementalStateFn(const void *)538   GetCreateIncrementalStateFn(const void*) {
539     return nullptr;
540   }
541 
542   template <typename T>
543   static internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter
CreateDataSourceCustomTls(internal::DataSourceInstanceThreadLocalState * tls_inst,uint32_t instance_index,void *)544   CreateDataSourceCustomTls(
545       internal::DataSourceInstanceThreadLocalState* tls_inst,
546       uint32_t instance_index,
547       void*) {
548     return internal::DataSourceInstanceThreadLocalState::ObjectWithDeleter(
549         reinterpret_cast<void*>(new T(TraceContext(tls_inst, instance_index))),
550         [](void* p) { delete reinterpret_cast<T*>(p); });
551   }
552 
553   // The second parameter here is used to specialize the case where there is no
554   // tls state type.
555   template <typename T>
GetCreateTlsFn(const T *)556   static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(const T*) {
557     return &CreateDataSourceCustomTls<T>;
558   }
559 
GetCreateTlsFn(const void *)560   static internal::DataSourceType::CreateCustomTlsFn GetCreateTlsFn(
561       const void*) {
562     return nullptr;
563   }
564 
565   // This TLS object is a cached raw pointer and has deliberately no destructor.
566   // The Platform implementation is supposed to create and manage the lifetime
567   // of the Platform::ThreadLocalObject and take care of destroying it.
568   // This is because non-POD thread_local variables have subtleties (global
569   // destructors) that we need to defer to the embedder. In chromium's platform
570   // implementation, for instance, the tls slot is implemented using
571   // chromium's base::ThreadLocalStorage.
572   static thread_local internal::DataSourceThreadLocalState* tls_state_;
573 };
574 
575 // static
576 template <typename T, typename D>
577 thread_local internal::DataSourceThreadLocalState* DataSource<T, D>::tls_state_;
578 
579 }  // namespace perfetto
580 
581 // If placed at the end of a macro declaration, eats the semicolon at the end of
582 // the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra
583 // semicolons.
584 #define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \
585   extern int perfetto_internal_unused
586 
587 // This macro must be used once for each data source next to the data source's
588 // declaration.
589 #define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...)  \
590   PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
591       PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
592 
593 // Similar to `PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
594 // custom attributes, which are useful when DataSource is defined in a component
595 // where a component specific export macro is used.
596 #define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
597   template <>                                                              \
598   attrs perfetto::internal::DataSourceType&                                \
599   perfetto::DataSourceHelper<__VA_ARGS__>::type()
600 
601 // This macro must be used once for each data source in one source file to
602 // allocate static storage for the data source's static state.
603 #define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...)  \
604   PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS( \
605       PERFETTO_COMPONENT_EXPORT, __VA_ARGS__)
606 
607 // Similar to `PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS` but it also takes
608 // custom attributes, which are useful when DataSource is defined in a component
609 // where a component specific export macro is used.
610 #define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(attrs, ...) \
611   template <>                                                             \
612   perfetto::internal::DataSourceType&                                     \
613   perfetto::DataSourceHelper<__VA_ARGS__>::type() {                       \
614     static perfetto::internal::DataSourceType type_;                      \
615     return type_;                                                         \
616   }                                                                       \
617   PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
618 
619 #endif  // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
620