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