• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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/data_source_abi.h"
18 
19 #include <bitset>
20 
21 #include "perfetto/base/thread_annotations.h"
22 #include "perfetto/tracing/buffer_exhausted_policy.h"
23 #include "perfetto/tracing/data_source.h"
24 #include "perfetto/tracing/internal/basic_types.h"
25 #include "protos/perfetto/common/data_source_descriptor.gen.h"
26 #include "protos/perfetto/config/data_source_config.gen.h"
27 #include "src/shared_lib/reset_for_testing.h"
28 #include "src/shared_lib/stream_writer.h"
29 
30 namespace {
31 
32 using ::perfetto::internal::DataSourceInstanceThreadLocalState;
33 using ::perfetto::internal::DataSourceThreadLocalState;
34 using ::perfetto::internal::DataSourceType;
35 
36 thread_local DataSourceThreadLocalState*
37     g_tls_cache[perfetto::internal::kMaxDataSources];
38 
39 }  // namespace
40 
41 // Implementation of a shared library data source type (there's one of these per
42 // type, not per instance).
43 //
44 // Returned to the C side when invoking PerfettoDsCreateImpl(). The C side only
45 // has an opaque pointer to this.
46 struct PerfettoDsImpl {
47   // Instance lifecycle callbacks.
48   PerfettoDsOnSetupCb on_setup_cb = nullptr;
49   PerfettoDsOnStartCb on_start_cb = nullptr;
50   PerfettoDsOnStopCb on_stop_cb = nullptr;
51   PerfettoDsOnDestroyCb on_destroy_cb = nullptr;
52   PerfettoDsOnFlushCb on_flush_cb = nullptr;
53 
54   // These are called to create/delete custom thread-local instance state.
55   PerfettoDsOnCreateCustomState on_create_tls_cb = nullptr;
56   PerfettoDsOnDeleteCustomState on_delete_tls_cb = nullptr;
57 
58   // These are called to create/delete custom thread-local instance incremental
59   // state.
60   PerfettoDsOnCreateCustomState on_create_incr_cb = nullptr;
61   PerfettoDsOnDeleteCustomState on_delete_incr_cb = nullptr;
62 
63   // Passed to all the callbacks as the `user_arg` param.
64   void* cb_user_arg;
65 
66   perfetto::BufferExhaustedPolicy buffer_exhausted_policy =
67       perfetto::BufferExhaustedPolicy::kDrop;
68 
69   DataSourceType cpp_type;
70   std::atomic<bool> enabled{false};
71   std::mutex mu;
72   std::bitset<perfetto::internal::kMaxDataSourceInstances> enabled_instances
73       PERFETTO_GUARDED_BY(mu);
74 
IsRegisteredPerfettoDsImpl75   bool IsRegistered() {
76     return cpp_type.static_state()->index !=
77            perfetto::internal::kMaxDataSources;
78   }
79 };
80 
81 struct PerfettoDsOnStopArgs {
82   struct PerfettoDsAsyncStopper* stopper = nullptr;
83 };
84 
85 struct PerfettoDsAsyncStopper {
86   PerfettoDsImpl* ds_impl;
87   uint32_t instance_idx;
88   std::function<void()> async_stop_closure;
89 
FinishStopPerfettoDsAsyncStopper90   void FinishStop() {
91     std::lock_guard<std::mutex> lock(ds_impl->mu);
92     ds_impl->enabled_instances.reset(instance_idx);
93     if (ds_impl->enabled_instances.none()) {
94       ds_impl->enabled.store(false, std::memory_order_release);
95     }
96     async_stop_closure();
97   }
98 };
99 
100 namespace perfetto {
101 namespace shlib {
102 
103 // These are only exposed to tests.
104 
ResetDataSourceTls()105 void ResetDataSourceTls() {
106   memset(g_tls_cache, 0, sizeof(g_tls_cache));
107 }
108 
DsImplDestroy(struct PerfettoDsImpl * ds_impl)109 void DsImplDestroy(struct PerfettoDsImpl* ds_impl) {
110   delete ds_impl;
111 }
112 
113 }  // namespace shlib
114 }  // namespace perfetto
115 
116 namespace {
117 
118 // Represents a global data source instance (there can be more than one of these
119 // for a single data source type).
120 class ShlibDataSource : public perfetto::DataSourceBase {
121  public:
ShlibDataSource(PerfettoDsImpl * type)122   explicit ShlibDataSource(PerfettoDsImpl* type) : type_(*type) {}
123 
OnSetup(const SetupArgs & args)124   void OnSetup(const SetupArgs& args) override {
125     if (type_.on_setup_cb) {
126       std::vector<uint8_t> serialized_config = args.config->SerializeAsArray();
127       inst_ctx_ = type_.on_setup_cb(
128           &type_, args.internal_instance_index, serialized_config.data(),
129           serialized_config.size(), type_.cb_user_arg, nullptr);
130     }
131     std::lock_guard<std::mutex> lock(type_.mu);
132     const bool was_enabled = type_.enabled_instances.any();
133     type_.enabled_instances.set(args.internal_instance_index);
134     if (!was_enabled && type_.enabled_instances.any()) {
135       type_.enabled.store(true, std::memory_order_release);
136     }
137   }
138 
OnStart(const StartArgs & args)139   void OnStart(const StartArgs& args) override {
140     if (type_.on_start_cb) {
141       type_.on_start_cb(&type_, args.internal_instance_index, type_.cb_user_arg,
142                         inst_ctx_, nullptr);
143     }
144   }
145 
OnStop(const StopArgs & args)146   void OnStop(const StopArgs& args) override {
147     PerfettoDsOnStopArgs c_args;
148     c_args.stopper = new PerfettoDsAsyncStopper();
149     // Capturing ds_impl is ok, because data sources cannot be unregistered.
150     c_args.stopper->ds_impl = &type_;
151     c_args.stopper->async_stop_closure = args.HandleStopAsynchronously();
152     c_args.stopper->instance_idx = args.internal_instance_index;
153 
154     if (type_.on_stop_cb) {
155       type_.on_stop_cb(&type_, args.internal_instance_index, type_.cb_user_arg,
156                        inst_ctx_, &c_args);
157     }
158 
159     // If c_args.stopper is nullptr, the user must have called
160     // PerfettoDsOnStopArgsPostpone() in the callback above: the user will
161     // invoke PerfettoDsStopDone later. If c_args.stopper is not nullptr, we
162     // need to invoke it.
163     if (c_args.stopper) {
164       PerfettoDsStopDone(c_args.stopper);
165     }
166   }
167 
~ShlibDataSource()168   ~ShlibDataSource() override {
169     if (type_.on_destroy_cb) {
170       type_.on_destroy_cb(&type_, type_.cb_user_arg, inst_ctx_);
171     }
172   }
173 
OnFlush(const FlushArgs & args)174   void OnFlush(const FlushArgs& args) override {
175     if (type_.on_flush_cb) {
176       type_.on_flush_cb(
177           &type_, args.internal_instance_index, type_.cb_user_arg, inst_ctx_,
178           const_cast<PerfettoDsOnFlushArgs*>(
179               reinterpret_cast<const PerfettoDsOnFlushArgs*>(&args)));
180     }
181   }
182 
type() const183   const PerfettoDsImpl& type() const { return type_; }
184 
inst_ctx() const185   void* inst_ctx() const { return inst_ctx_; }
186 
187  private:
188   PerfettoDsImpl& type_;
189   void* inst_ctx_ = nullptr;
190 };
191 
192 struct DataSourceTraits {
GetDataSourceTLS__anon6595d5f00211::DataSourceTraits193   static DataSourceThreadLocalState* GetDataSourceTLS(
194       perfetto::internal::DataSourceStaticState* static_state,
195       perfetto::internal::TracingTLS* root_tls) {
196     auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
197     // ds_tls->static_state can be:
198     // * nullptr
199     // * equal to static_state
200     // * equal to the static state of a different data source, in tests (when
201     //   ResetForTesting() has been used)
202     // In any case, there's no need to do anything, the caller will reinitialize
203     // static_state.
204     return ds_tls;
205   }
206 };
207 
208 struct TracePointTraits {
209   using TracePointData = DataSourceType*;
GetActiveInstances__anon6595d5f00211::TracePointTraits210   static std::atomic<uint32_t>* GetActiveInstances(TracePointData s) {
211     return s->valid_instances();
212   }
213 };
214 
CreateShlibTls(DataSourceInstanceThreadLocalState * tls_inst,uint32_t inst_idx,void * ctx)215 DataSourceInstanceThreadLocalState::ObjectWithDeleter CreateShlibTls(
216     DataSourceInstanceThreadLocalState* tls_inst,
217     uint32_t inst_idx,
218     void* ctx) {
219   auto* ds_impl = reinterpret_cast<PerfettoDsImpl*>(ctx);
220 
221   void* custom_state = ds_impl->on_create_tls_cb(
222       ds_impl, inst_idx, reinterpret_cast<PerfettoDsTracerImpl*>(tls_inst),
223       ds_impl->cb_user_arg);
224   return DataSourceInstanceThreadLocalState::ObjectWithDeleter(
225       custom_state, ds_impl->on_delete_tls_cb);
226 }
227 
228 DataSourceInstanceThreadLocalState::ObjectWithDeleter
CreateShlibIncrementalState(DataSourceInstanceThreadLocalState * tls_inst,uint32_t inst_idx,void * ctx)229 CreateShlibIncrementalState(DataSourceInstanceThreadLocalState* tls_inst,
230                             uint32_t inst_idx,
231                             void* ctx) {
232   auto* ds_impl = reinterpret_cast<PerfettoDsImpl*>(ctx);
233 
234   void* custom_state = ds_impl->on_create_incr_cb(
235       ds_impl, inst_idx, reinterpret_cast<PerfettoDsTracerImpl*>(tls_inst),
236       ds_impl->cb_user_arg);
237   return DataSourceInstanceThreadLocalState::ObjectWithDeleter(
238       custom_state, ds_impl->on_delete_incr_cb);
239 }
240 
241 }  // namespace
242 
243 // Exposed through data_source_abi.h
244 std::atomic<bool> perfetto_atomic_false{false};
245 
PerfettoDsImplCreate()246 struct PerfettoDsImpl* PerfettoDsImplCreate() {
247   return new PerfettoDsImpl();
248 }
249 
PerfettoDsSetOnSetupCallback(struct PerfettoDsImpl * ds_impl,PerfettoDsOnSetupCb cb)250 void PerfettoDsSetOnSetupCallback(struct PerfettoDsImpl* ds_impl,
251                                   PerfettoDsOnSetupCb cb) {
252   PERFETTO_CHECK(!ds_impl->IsRegistered());
253   ds_impl->on_setup_cb = cb;
254 }
255 
PerfettoDsSetOnStartCallback(struct PerfettoDsImpl * ds_impl,PerfettoDsOnStartCb cb)256 void PerfettoDsSetOnStartCallback(struct PerfettoDsImpl* ds_impl,
257                                   PerfettoDsOnStartCb cb) {
258   PERFETTO_CHECK(!ds_impl->IsRegistered());
259   ds_impl->on_start_cb = cb;
260 }
261 
PerfettoDsSetOnStopCallback(struct PerfettoDsImpl * ds_impl,PerfettoDsOnStopCb cb)262 void PerfettoDsSetOnStopCallback(struct PerfettoDsImpl* ds_impl,
263                                  PerfettoDsOnStopCb cb) {
264   PERFETTO_CHECK(!ds_impl->IsRegistered());
265   ds_impl->on_stop_cb = cb;
266 }
267 
PerfettoDsSetOnDestroyCallback(struct PerfettoDsImpl * ds_impl,PerfettoDsOnDestroyCb cb)268 void PerfettoDsSetOnDestroyCallback(struct PerfettoDsImpl* ds_impl,
269                                     PerfettoDsOnDestroyCb cb) {
270   PERFETTO_CHECK(!ds_impl->IsRegistered());
271   ds_impl->on_destroy_cb = cb;
272 }
273 
PerfettoDsSetOnFlushCallback(struct PerfettoDsImpl * ds_impl,PerfettoDsOnFlushCb cb)274 void PerfettoDsSetOnFlushCallback(struct PerfettoDsImpl* ds_impl,
275                                   PerfettoDsOnFlushCb cb) {
276   PERFETTO_CHECK(!ds_impl->IsRegistered());
277   ds_impl->on_flush_cb = cb;
278 }
279 
PerfettoDsSetOnCreateTls(struct PerfettoDsImpl * ds_impl,PerfettoDsOnCreateCustomState cb)280 void PerfettoDsSetOnCreateTls(struct PerfettoDsImpl* ds_impl,
281                               PerfettoDsOnCreateCustomState cb) {
282   PERFETTO_CHECK(!ds_impl->IsRegistered());
283   ds_impl->on_create_tls_cb = cb;
284 }
285 
PerfettoDsSetOnDeleteTls(struct PerfettoDsImpl * ds_impl,PerfettoDsOnDeleteCustomState cb)286 void PerfettoDsSetOnDeleteTls(struct PerfettoDsImpl* ds_impl,
287                               PerfettoDsOnDeleteCustomState cb) {
288   PERFETTO_CHECK(!ds_impl->IsRegistered());
289   ds_impl->on_delete_tls_cb = cb;
290 }
291 
PerfettoDsSetOnCreateIncr(struct PerfettoDsImpl * ds_impl,PerfettoDsOnCreateCustomState cb)292 void PerfettoDsSetOnCreateIncr(struct PerfettoDsImpl* ds_impl,
293                                PerfettoDsOnCreateCustomState cb) {
294   PERFETTO_CHECK(!ds_impl->IsRegistered());
295   ds_impl->on_create_incr_cb = cb;
296 }
297 
PerfettoDsSetOnDeleteIncr(struct PerfettoDsImpl * ds_impl,PerfettoDsOnDeleteCustomState cb)298 void PerfettoDsSetOnDeleteIncr(struct PerfettoDsImpl* ds_impl,
299                                PerfettoDsOnDeleteCustomState cb) {
300   PERFETTO_CHECK(!ds_impl->IsRegistered());
301   ds_impl->on_delete_incr_cb = cb;
302 }
303 
PerfettoDsSetCbUserArg(struct PerfettoDsImpl * ds_impl,void * user_arg)304 void PerfettoDsSetCbUserArg(struct PerfettoDsImpl* ds_impl, void* user_arg) {
305   PERFETTO_CHECK(!ds_impl->IsRegistered());
306   ds_impl->cb_user_arg = user_arg;
307 }
308 
PerfettoDsSetBufferExhaustedPolicy(struct PerfettoDsImpl * ds_impl,uint32_t policy)309 bool PerfettoDsSetBufferExhaustedPolicy(struct PerfettoDsImpl* ds_impl,
310                                         uint32_t policy) {
311   if (ds_impl->IsRegistered()) {
312     return false;
313   }
314 
315   switch (policy) {
316     case PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_DROP:
317       ds_impl->buffer_exhausted_policy = perfetto::BufferExhaustedPolicy::kDrop;
318       return true;
319     case PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT:
320       ds_impl->buffer_exhausted_policy =
321           perfetto::BufferExhaustedPolicy::kStall;
322       return true;
323   }
324   return false;
325 }
326 
PerfettoDsImplRegister(struct PerfettoDsImpl * ds_impl,PERFETTO_ATOMIC (bool)** enabled_ptr,const void * descriptor,size_t descriptor_size)327 bool PerfettoDsImplRegister(struct PerfettoDsImpl* ds_impl,
328                             PERFETTO_ATOMIC(bool) * *enabled_ptr,
329                             const void* descriptor,
330                             size_t descriptor_size) {
331   std::unique_ptr<PerfettoDsImpl> data_source_type(ds_impl);
332 
333   perfetto::DataSourceDescriptor dsd;
334   dsd.ParseFromArray(descriptor, descriptor_size);
335 
336   auto factory = [ds_impl]() {
337     return std::unique_ptr<perfetto::DataSourceBase>(
338         new ShlibDataSource(ds_impl));
339   };
340 
341   DataSourceType::CreateCustomTlsFn create_custom_tls_fn = nullptr;
342   DataSourceType::CreateIncrementalStateFn create_incremental_state_fn =
343       nullptr;
344   void* cb_ctx = nullptr;
345   if (data_source_type->on_create_incr_cb &&
346       data_source_type->on_delete_incr_cb) {
347     create_incremental_state_fn = CreateShlibIncrementalState;
348     cb_ctx = data_source_type.get();
349   }
350   if (data_source_type->on_create_tls_cb &&
351       data_source_type->on_delete_tls_cb) {
352     create_custom_tls_fn = CreateShlibTls;
353     cb_ctx = data_source_type.get();
354   }
355 
356   perfetto::internal::DataSourceParams params;
357   params.supports_multiple_instances = true;
358   params.requires_callbacks_under_lock = false;
359   bool success = data_source_type->cpp_type.Register(
360       dsd, factory, params, data_source_type->buffer_exhausted_policy,
361       data_source_type->on_flush_cb == nullptr, create_custom_tls_fn,
362       create_incremental_state_fn, cb_ctx);
363   if (!success) {
364     return false;
365   }
366   *enabled_ptr = &data_source_type->enabled;
367   perfetto::base::ignore_result(data_source_type.release());
368   return true;
369 }
370 
PerfettoDsImplUpdateDescriptor(struct PerfettoDsImpl * ds_impl,const void * descriptor,size_t descriptor_size)371 void PerfettoDsImplUpdateDescriptor(struct PerfettoDsImpl* ds_impl,
372                                     const void* descriptor,
373                                     size_t descriptor_size) {
374   perfetto::DataSourceDescriptor dsd;
375   dsd.ParseFromArray(descriptor, descriptor_size);
376 
377   ds_impl->cpp_type.UpdateDescriptor(dsd);
378 }
379 
PerfettoDsOnStopArgsPostpone(PerfettoDsOnStopArgs * args)380 PerfettoDsAsyncStopper* PerfettoDsOnStopArgsPostpone(
381     PerfettoDsOnStopArgs* args) {
382   PerfettoDsAsyncStopper* stopper = args->stopper;
383   args->stopper = nullptr;
384   return stopper;
385 }
386 
PerfettoDsStopDone(PerfettoDsAsyncStopper * stopper)387 void PerfettoDsStopDone(PerfettoDsAsyncStopper* stopper) {
388   stopper->FinishStop();
389   delete stopper;
390 }
391 
PerfettoDsOnFlushArgsPostpone(PerfettoDsOnFlushArgs * args)392 PerfettoDsAsyncFlusher* PerfettoDsOnFlushArgsPostpone(
393     PerfettoDsOnFlushArgs* args) {
394   auto* cb = new std::function<void()>();
395   *cb = reinterpret_cast<const ShlibDataSource::FlushArgs*>(args)
396             ->HandleFlushAsynchronously();
397   return reinterpret_cast<PerfettoDsAsyncFlusher*>(cb);
398 }
399 
PerfettoDsFlushDone(PerfettoDsAsyncFlusher * stopper)400 void PerfettoDsFlushDone(PerfettoDsAsyncFlusher* stopper) {
401   auto* cb = reinterpret_cast<std::function<void()>*>(stopper);
402   (*cb)();
403   delete cb;
404 }
405 
PerfettoDsImplGetInstanceLocked(struct PerfettoDsImpl * ds_impl,PerfettoDsInstanceIndex idx)406 void* PerfettoDsImplGetInstanceLocked(struct PerfettoDsImpl* ds_impl,
407                                       PerfettoDsInstanceIndex idx) {
408   auto* internal_state = ds_impl->cpp_type.static_state()->TryGet(idx);
409   if (!internal_state) {
410     return nullptr;
411   }
412   std::unique_lock<std::recursive_mutex> lock(internal_state->lock);
413   auto* data_source =
414       static_cast<ShlibDataSource*>(internal_state->data_source.get());
415   if (&data_source->type() != ds_impl) {
416     // The data source instance has been destroyed and recreated as a different
417     // type while we where tracing.
418     return nullptr;
419   }
420   void* inst_ctx = data_source->inst_ctx();
421   if (inst_ctx != nullptr) {
422     lock.release();
423   }
424   return inst_ctx;
425 }
426 
PerfettoDsImplReleaseInstanceLocked(struct PerfettoDsImpl * ds_impl,PerfettoDsInstanceIndex idx)427 void PerfettoDsImplReleaseInstanceLocked(struct PerfettoDsImpl* ds_impl,
428                                          PerfettoDsInstanceIndex idx) {
429   // The `valid_instances` bitmap might have changed since the lock has been
430   // taken, but the instance must still be alive (we were holding the lock on
431   // it).
432   auto* internal_state = ds_impl->cpp_type.static_state()->GetUnsafe(idx);
433   internal_state->lock.unlock();
434 }
435 
PerfettoDsImplGetCustomTls(struct PerfettoDsImpl *,struct PerfettoDsTracerImpl * tracer,PerfettoDsInstanceIndex)436 void* PerfettoDsImplGetCustomTls(struct PerfettoDsImpl*,
437                                  struct PerfettoDsTracerImpl* tracer,
438                                  PerfettoDsInstanceIndex) {
439   auto* tls_inst =
440       reinterpret_cast<DataSourceInstanceThreadLocalState*>(tracer);
441 
442   PERFETTO_DCHECK(tls_inst->data_source_custom_tls);
443   return tls_inst->data_source_custom_tls.get();
444 }
445 
PerfettoDsImplGetIncrementalState(struct PerfettoDsImpl * ds_impl,struct PerfettoDsTracerImpl * tracer,PerfettoDsInstanceIndex idx)446 void* PerfettoDsImplGetIncrementalState(struct PerfettoDsImpl* ds_impl,
447                                         struct PerfettoDsTracerImpl* tracer,
448                                         PerfettoDsInstanceIndex idx) {
449   auto* tls_inst =
450       reinterpret_cast<DataSourceInstanceThreadLocalState*>(tracer);
451 
452   return ds_impl->cpp_type.GetIncrementalState(tls_inst, idx);
453 }
454 
PerfettoDsImplTraceIterateBegin(struct PerfettoDsImpl * ds_impl)455 struct PerfettoDsImplTracerIterator PerfettoDsImplTraceIterateBegin(
456     struct PerfettoDsImpl* ds_impl) {
457   DataSourceThreadLocalState** tls =
458       &g_tls_cache[ds_impl->cpp_type.static_state()->index];
459 
460   struct PerfettoDsImplTracerIterator ret = {0, nullptr, nullptr};
461   uint32_t cached_instances =
462       ds_impl->cpp_type.valid_instances()->load(std::memory_order_relaxed);
463   if (!cached_instances) {
464     return ret;
465   }
466   bool res =
467       ds_impl->cpp_type.TracePrologue<DataSourceTraits, TracePointTraits>(
468           tls, &cached_instances, &ds_impl->cpp_type);
469   if (!res) {
470     return ret;
471   }
472   DataSourceType::InstancesIterator it =
473       ds_impl->cpp_type.BeginIteration<TracePointTraits>(cached_instances, *tls,
474                                                          &ds_impl->cpp_type);
475   ret.inst_id = it.i;
476   (*tls)->root_tls->cached_instances = it.cached_instances;
477   ret.tracer = reinterpret_cast<struct PerfettoDsTracerImpl*>(it.instance);
478   if (!ret.tracer) {
479     ds_impl->cpp_type.TraceEpilogue(*tls);
480   }
481 
482   ret.tls = reinterpret_cast<struct PerfettoDsTlsImpl*>(*tls);
483   return ret;
484 }
485 
PerfettoDsImplTraceIterateNext(struct PerfettoDsImpl * ds_impl,struct PerfettoDsImplTracerIterator * iterator)486 void PerfettoDsImplTraceIterateNext(
487     struct PerfettoDsImpl* ds_impl,
488     struct PerfettoDsImplTracerIterator* iterator) {
489   auto* tls = reinterpret_cast<DataSourceThreadLocalState*>(iterator->tls);
490 
491   DataSourceType::InstancesIterator it;
492   it.i = iterator->inst_id;
493   it.cached_instances = tls->root_tls->cached_instances;
494   it.instance =
495       reinterpret_cast<DataSourceInstanceThreadLocalState*>(iterator->tracer);
496 
497   ds_impl->cpp_type.NextIteration<TracePointTraits>(&it, tls,
498                                                     &ds_impl->cpp_type);
499 
500   iterator->inst_id = it.i;
501   tls->root_tls->cached_instances = it.cached_instances;
502   iterator->tracer =
503       reinterpret_cast<struct PerfettoDsTracerImpl*>(it.instance);
504 
505   if (!iterator->tracer) {
506     ds_impl->cpp_type.TraceEpilogue(tls);
507   }
508 }
509 
PerfettoDsImplTraceIterateBreak(struct PerfettoDsImpl * ds_impl,struct PerfettoDsImplTracerIterator * iterator)510 void PerfettoDsImplTraceIterateBreak(
511     struct PerfettoDsImpl* ds_impl,
512     struct PerfettoDsImplTracerIterator* iterator) {
513   auto* tls = reinterpret_cast<DataSourceThreadLocalState*>(iterator->tls);
514 
515   ds_impl->cpp_type.TraceEpilogue(tls);
516 }
517 
PerfettoDsTracerImplPacketBegin(struct PerfettoDsTracerImpl * tracer)518 struct PerfettoStreamWriter PerfettoDsTracerImplPacketBegin(
519     struct PerfettoDsTracerImpl* tracer) {
520   auto* tls_inst =
521       reinterpret_cast<DataSourceInstanceThreadLocalState*>(tracer);
522 
523   auto message_handle = tls_inst->trace_writer->NewTracePacket();
524   struct PerfettoStreamWriter ret;
525   protozero::ScatteredStreamWriter* sw = message_handle.TakeStreamWriter();
526   ret.impl = reinterpret_cast<PerfettoStreamWriterImpl*>(sw);
527   perfetto::UpdateStreamWriter(*sw, &ret);
528   return ret;
529 }
530 
PerfettoDsTracerImplPacketEnd(struct PerfettoDsTracerImpl * tracer,struct PerfettoStreamWriter * w)531 void PerfettoDsTracerImplPacketEnd(struct PerfettoDsTracerImpl* tracer,
532                                    struct PerfettoStreamWriter* w) {
533   auto* tls_inst =
534       reinterpret_cast<DataSourceInstanceThreadLocalState*>(tracer);
535   auto* sw = reinterpret_cast<protozero::ScatteredStreamWriter*>(w->impl);
536 
537   sw->set_write_ptr(w->write_ptr);
538   tls_inst->trace_writer->FinishTracePacket();
539 }
540 
PerfettoDsTracerImplFlush(struct PerfettoDsTracerImpl * tracer,PerfettoDsTracerOnFlushCb cb,void * user_arg)541 void PerfettoDsTracerImplFlush(struct PerfettoDsTracerImpl* tracer,
542                                PerfettoDsTracerOnFlushCb cb,
543                                void* user_arg) {
544   auto* tls_inst =
545       reinterpret_cast<DataSourceInstanceThreadLocalState*>(tracer);
546 
547   std::function<void()> fn;
548   if (cb != nullptr) {
549     fn = [user_arg, cb]() { cb(user_arg); };
550   }
551   tls_inst->trace_writer->Flush(fn);
552 }
553