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