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