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