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