1 /*
2 * Copyright (C) 2023 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 #ifndef INCLUDE_PERFETTO_PUBLIC_TRACK_EVENT_H_
18 #define INCLUDE_PERFETTO_PUBLIC_TRACK_EVENT_H_
19
20 #include <stdint.h>
21 #include <stdlib.h>
22
23 #include "perfetto/public/abi/heap_buffer.h"
24 #include "perfetto/public/abi/track_event_abi.h" // IWYU pragma: export
25 #include "perfetto/public/abi/track_event_hl_abi.h" // IWYU pragma: export
26 #include "perfetto/public/abi/track_event_ll_abi.h" // IWYU pragma: export
27 #include "perfetto/public/compiler.h"
28 #include "perfetto/public/data_source.h"
29 #include "perfetto/public/fnv1a.h"
30 #include "perfetto/public/pb_msg.h"
31 #include "perfetto/public/protos/trace/interned_data/interned_data.pzc.h"
32 #include "perfetto/public/protos/trace/trace_packet.pzc.h"
33 #include "perfetto/public/protos/trace/track_event/counter_descriptor.pzc.h"
34 #include "perfetto/public/protos/trace/track_event/track_descriptor.pzc.h"
35 #include "perfetto/public/protos/trace/track_event/track_event.pzc.h"
36 #include "perfetto/public/thread_utils.h"
37
38 // A registered category.
39 struct PerfettoTeCategory {
40 PERFETTO_ATOMIC(bool) * enabled;
41 struct PerfettoTeCategoryImpl* impl;
42 struct PerfettoTeCategoryDescriptor desc;
43 uint64_t cat_iid;
44 };
45
46 // Registers the category `cat`. `cat->desc` must be filled before calling this.
47 // The rest of the structure is filled by the function.
PerfettoTeCategoryRegister(struct PerfettoTeCategory * cat)48 static inline void PerfettoTeCategoryRegister(struct PerfettoTeCategory* cat) {
49 cat->impl = PerfettoTeCategoryImplCreate(&cat->desc);
50 cat->enabled = PerfettoTeCategoryImplGetEnabled(cat->impl);
51 cat->cat_iid = PerfettoTeCategoryImplGetIid(cat->impl);
52 }
53
54 // Calls PerfettoTeCategoryRegister() on multiple categories.
PerfettoTeRegisterCategories(struct PerfettoTeCategory * cats[],size_t size)55 static inline void PerfettoTeRegisterCategories(
56 struct PerfettoTeCategory* cats[],
57 size_t size) {
58 for (size_t i = 0; i < size; i++) {
59 PerfettoTeCategoryRegister(cats[i]);
60 }
61 }
62
63 // Registers `cb` to be called every time a data source instance with `reg_cat`
64 // enabled is created or destroyed. `user_arg` will be passed unaltered to `cb`.
65 //
66 // `cb` can be NULL to disable the callback.
PerfettoTeCategorySetCallback(struct PerfettoTeCategory * reg_cat,PerfettoTeCategoryImplCallback cb,void * user_arg)67 static inline void PerfettoTeCategorySetCallback(
68 struct PerfettoTeCategory* reg_cat,
69 PerfettoTeCategoryImplCallback cb,
70 void* user_arg) {
71 PerfettoTeCategoryImplSetCallback(reg_cat->impl, cb, user_arg);
72 }
73
74 // Unregisters the category `cat`.
75 //
76 // WARNING: The category cannot be used for tracing anymore after this.
77 // Executing PERFETTO_TE() on an unregistered category will cause a null pointer
78 // dereference.
PerfettoTeCategoryUnregister(struct PerfettoTeCategory * cat)79 static inline void PerfettoTeCategoryUnregister(
80 struct PerfettoTeCategory* cat) {
81 PerfettoTeCategoryImplDestroy(cat->impl);
82 cat->impl = PERFETTO_NULL;
83 cat->enabled = &perfetto_atomic_false;
84 cat->cat_iid = 0;
85 }
86
87 // Calls PerfettoTeCategoryUnregister() on multiple categories.
88 //
89 // WARNING: The categories cannot be used for tracing anymore after this.
90 // Executing PERFETTO_TE() on unregistered categories will cause a null pointer
91 // dereference.
PerfettoTeUnregisterCategories(struct PerfettoTeCategory * cats[],size_t size)92 static inline void PerfettoTeUnregisterCategories(
93 struct PerfettoTeCategory* cats[],
94 size_t size) {
95 for (size_t i = 0; i < size; i++) {
96 PerfettoTeCategoryUnregister(cats[i]);
97 }
98 }
99
100 // A track. Must be registered before it can be used in trace events.
101 struct PerfettoTeRegisteredTrack {
102 struct PerfettoTeRegisteredTrackImpl impl;
103 };
104
105 // Returns the track uuid for the current process.
PerfettoTeProcessTrackUuid(void)106 static inline uint64_t PerfettoTeProcessTrackUuid(void) {
107 return perfetto_te_process_track_uuid;
108 }
109
110 // Returns the track uuid for the current thread.
PerfettoTeThreadTrackUuid(void)111 static inline uint64_t PerfettoTeThreadTrackUuid(void) {
112 return perfetto_te_process_track_uuid ^
113 PERFETTO_STATIC_CAST(uint64_t, PerfettoGetThreadId());
114 }
115
116 // Returns the root track uuid.
PerfettoTeGlobalTrackUuid(void)117 static inline uint64_t PerfettoTeGlobalTrackUuid(void) {
118 return 0;
119 }
120
121 // Computes the track uuid for a counter track named `name` whose parent track
122 // has `parent_uuid`.
PerfettoTeCounterTrackUuid(const char * name,uint64_t parent_uuid)123 static inline uint64_t PerfettoTeCounterTrackUuid(const char* name,
124 uint64_t parent_uuid) {
125 const uint64_t kCounterMagic = 0xb1a4a67d7970839eul;
126 uint64_t uuid = kCounterMagic;
127 uuid ^= parent_uuid;
128 uuid ^= PerfettoFnv1a(name, strlen(name));
129 return uuid;
130 }
131
132 // Computes the track uuid for a track named `name` with unique `id` whose
133 // parent track has `parent_uuid`.
PerfettoTeNamedTrackUuid(const char * name,uint64_t id,uint64_t parent_uuid)134 static inline uint64_t PerfettoTeNamedTrackUuid(const char* name,
135 uint64_t id,
136 uint64_t parent_uuid) {
137 uint64_t uuid = parent_uuid;
138 uuid ^= PerfettoFnv1a(name, strlen(name));
139 uuid ^= id;
140 return uuid;
141 }
142
143 // Serializes the descriptor for a counter track named `name` with
144 // `parent_uuid`. `track_uuid` must be the return value of
145 // PerfettoTeCounterTrackUuid().
PerfettoTeCounterTrackFillDesc(struct perfetto_protos_TrackDescriptor * desc,const char * name,uint64_t parent_track_uuid,uint64_t track_uuid)146 static inline void PerfettoTeCounterTrackFillDesc(
147 struct perfetto_protos_TrackDescriptor* desc,
148 const char* name,
149 uint64_t parent_track_uuid,
150 uint64_t track_uuid) {
151 perfetto_protos_TrackDescriptor_set_uuid(desc, track_uuid);
152 if (parent_track_uuid) {
153 perfetto_protos_TrackDescriptor_set_parent_uuid(desc, parent_track_uuid);
154 }
155 perfetto_protos_TrackDescriptor_set_cstr_name(desc, name);
156 {
157 struct perfetto_protos_CounterDescriptor counter;
158 perfetto_protos_TrackDescriptor_begin_counter(desc, &counter);
159 perfetto_protos_TrackDescriptor_end_counter(desc, &counter);
160 }
161 }
162
163 // Serializes the descriptor for a track named `name` with unique `id` and
164 // `parent_uuid`. `track_uuid` must be the return value of
165 // PerfettoTeNamedTrackUuid().
PerfettoTeNamedTrackFillDesc(struct perfetto_protos_TrackDescriptor * desc,const char * track_name,uint64_t id,uint64_t parent_track_uuid,uint64_t track_uuid)166 static inline void PerfettoTeNamedTrackFillDesc(
167 struct perfetto_protos_TrackDescriptor* desc,
168 const char* track_name,
169 uint64_t id,
170 uint64_t parent_track_uuid,
171 uint64_t track_uuid) {
172 (void)id;
173 perfetto_protos_TrackDescriptor_set_uuid(desc, track_uuid);
174 if (parent_track_uuid) {
175 perfetto_protos_TrackDescriptor_set_parent_uuid(desc, parent_track_uuid);
176 }
177 perfetto_protos_TrackDescriptor_set_cstr_name(desc, track_name);
178 }
179
180 // Registers a track named `name` with unique `id` and `parent_uuid` into
181 // `track`.
PerfettoTeNamedTrackRegister(struct PerfettoTeRegisteredTrack * track,const char * name,uint64_t id,uint64_t parent_track_uuid)182 static inline void PerfettoTeNamedTrackRegister(
183 struct PerfettoTeRegisteredTrack* track,
184 const char* name,
185 uint64_t id,
186 uint64_t parent_track_uuid) {
187 uint64_t uuid;
188 // Build the TrackDescriptor protobuf message.
189 struct PerfettoPbMsgWriter writer;
190 struct PerfettoHeapBuffer* hb = PerfettoHeapBufferCreate(&writer.writer);
191 struct perfetto_protos_TrackDescriptor desc;
192 PerfettoPbMsgInit(&desc.msg, &writer);
193
194 uuid = PerfettoTeNamedTrackUuid(name, id, parent_track_uuid);
195
196 PerfettoTeNamedTrackFillDesc(&desc, name, id, parent_track_uuid, uuid);
197
198 track->impl.descriptor_size =
199 PerfettoStreamWriterGetWrittenSize(&writer.writer);
200 track->impl.descriptor = malloc(track->impl.descriptor_size);
201 track->impl.uuid = uuid;
202 PerfettoHeapBufferCopyInto(hb, &writer.writer, track->impl.descriptor,
203 track->impl.descriptor_size);
204 PerfettoHeapBufferDestroy(hb, &writer.writer);
205 }
206
207 // Registers a counter track named `name` with and `parent_uuid` into `track`.
PerfettoTeCounterTrackRegister(struct PerfettoTeRegisteredTrack * track,const char * name,uint64_t parent_track_uuid)208 static inline void PerfettoTeCounterTrackRegister(
209 struct PerfettoTeRegisteredTrack* track,
210 const char* name,
211 uint64_t parent_track_uuid) {
212 uint64_t uuid;
213 struct PerfettoPbMsgWriter writer;
214 struct PerfettoHeapBuffer* hb = PerfettoHeapBufferCreate(&writer.writer);
215 struct perfetto_protos_TrackDescriptor desc;
216 PerfettoPbMsgInit(&desc.msg, &writer);
217
218 uuid = PerfettoTeCounterTrackUuid(name, parent_track_uuid);
219
220 PerfettoTeCounterTrackFillDesc(&desc, name, parent_track_uuid, uuid);
221
222 track->impl.descriptor_size =
223 PerfettoStreamWriterGetWrittenSize(&writer.writer);
224 track->impl.descriptor = malloc(track->impl.descriptor_size);
225 track->impl.uuid = uuid;
226 PerfettoHeapBufferCopyInto(hb, &writer.writer, track->impl.descriptor,
227 track->impl.descriptor_size);
228 PerfettoHeapBufferDestroy(hb, &writer.writer);
229 }
230
231 // Unregisters the previously registered track `track`.
PerfettoTeRegisteredTrackUnregister(struct PerfettoTeRegisteredTrack * track)232 static inline void PerfettoTeRegisteredTrackUnregister(
233 struct PerfettoTeRegisteredTrack* track) {
234 free(track->impl.descriptor);
235 track->impl.descriptor = PERFETTO_NULL;
236 track->impl.descriptor_size = 0;
237 }
238
239 // Identifies a flow: a link between two events.
240 struct PerfettoTeFlow {
241 uint64_t id;
242 };
243
244 // Returns a flow that's scoped to this process. It can be used to link events
245 // inside this process.
PerfettoTeProcessScopedFlow(uint64_t id)246 static inline struct PerfettoTeFlow PerfettoTeProcessScopedFlow(uint64_t id) {
247 struct PerfettoTeFlow ret;
248 ret.id = id ^ perfetto_te_process_track_uuid;
249 return ret;
250 }
251
252 // Returns a global flow. It can be used to link events between different
253 // processes.
PerfettoTeGlobalFlow(uint64_t id)254 static inline struct PerfettoTeFlow PerfettoTeGlobalFlow(uint64_t id) {
255 struct PerfettoTeFlow ret;
256 ret.id = id;
257 return ret;
258 }
259
260 // Returns a static-category-like object used when dynamic categories are passed
261 // as extra parameters.
PerfettoTeRegisteredDynamicCategory(void)262 static inline struct PerfettoTeCategory PerfettoTeRegisteredDynamicCategory(
263 void) {
264 struct PerfettoTeCategory ret = {
265 perfetto_te_any_categories_enabled,
266 perfetto_te_any_categories,
267 {PERFETTO_NULL, PERFETTO_NULL, PERFETTO_NULL, 0},
268 0};
269 return ret;
270 }
271
272 // Iterator for all the active instances (on this thread) of a data source type.
273 struct PerfettoTeLlIterator {
274 struct PerfettoTeLlImplIterator impl;
275 };
276
PerfettoTeLlBeginSlowPath(struct PerfettoTeCategory * cat,struct PerfettoTeTimestamp ts)277 static inline struct PerfettoTeLlIterator PerfettoTeLlBeginSlowPath(
278 struct PerfettoTeCategory* cat,
279 struct PerfettoTeTimestamp ts) {
280 struct PerfettoTeLlIterator ret;
281 ret.impl = PerfettoTeLlImplBegin(cat->impl, ts);
282 return ret;
283 }
284
PerfettoTeLlNext(struct PerfettoTeCategory * cat,struct PerfettoTeTimestamp ts,struct PerfettoTeLlIterator * iterator)285 static inline void PerfettoTeLlNext(struct PerfettoTeCategory* cat,
286 struct PerfettoTeTimestamp ts,
287 struct PerfettoTeLlIterator* iterator) {
288 PerfettoTeLlImplNext(cat->impl, ts, &iterator->impl);
289 }
290
PerfettoTeLlBreak(struct PerfettoTeCategory * cat,struct PerfettoTeLlIterator * iterator)291 static inline void PerfettoTeLlBreak(struct PerfettoTeCategory* cat,
292 struct PerfettoTeLlIterator* iterator) {
293 if (iterator->impl.ds.tracer) {
294 PerfettoTeLlImplBreak(cat->impl, &iterator->impl);
295 }
296 }
297
298 // Checks if the category descriptor `dyn_cat` is enabled in the current active
299 // instance pointed by `iterator`.
PerfettoTeLlDynCatEnabled(struct PerfettoTeLlIterator * iterator,const struct PerfettoTeCategoryDescriptor * dyn_cat)300 static inline bool PerfettoTeLlDynCatEnabled(
301 struct PerfettoTeLlIterator* iterator,
302 const struct PerfettoTeCategoryDescriptor* dyn_cat) {
303 return PerfettoTeLlImplDynCatEnabled(iterator->impl.ds.tracer,
304 iterator->impl.ds.inst_id, dyn_cat);
305 }
306
307 // Initializes `root` to write a new packet to the data source instance pointed
308 // by `iterator`.
PerfettoTeLlPacketBegin(struct PerfettoTeLlIterator * iterator,struct PerfettoDsRootTracePacket * root)309 static inline void PerfettoTeLlPacketBegin(
310 struct PerfettoTeLlIterator* iterator,
311 struct PerfettoDsRootTracePacket* root) {
312 root->writer.writer =
313 PerfettoDsTracerImplPacketBegin(iterator->impl.ds.tracer);
314 PerfettoPbMsgInit(&root->msg.msg, &root->writer);
315 }
316
317 // Finishes writing the packet pointed by `root` on the data source instance
318 // pointer by `iterator`.
PerfettoTeLlPacketEnd(struct PerfettoTeLlIterator * iterator,struct PerfettoDsRootTracePacket * root)319 static inline void PerfettoTeLlPacketEnd(
320 struct PerfettoTeLlIterator* iterator,
321 struct PerfettoDsRootTracePacket* root) {
322 PerfettoPbMsgFinalize(&root->msg.msg);
323 PerfettoDsTracerImplPacketEnd(iterator->impl.ds.tracer, &root->writer.writer);
324 }
325
PerfettoTeLlFlushPacket(struct PerfettoTeLlIterator * iterator)326 static inline void PerfettoTeLlFlushPacket(
327 struct PerfettoTeLlIterator* iterator) {
328 PerfettoDsTracerImplFlush(iterator->impl.ds.tracer, PERFETTO_NULL,
329 PERFETTO_NULL);
330 }
331
332 // Returns true if the track event incremental state has already seen in the
333 // past a track with `uuid` as track UUID.
PerfettoTeLlTrackSeen(struct PerfettoTeLlImplIncr * incr,uint64_t uuid)334 static inline bool PerfettoTeLlTrackSeen(struct PerfettoTeLlImplIncr* incr,
335 uint64_t uuid) {
336 return PerfettoTeLlImplTrackSeen(incr, uuid);
337 }
338
339 // Interning:
340 //
341 // it's possible to avoid repeating the same data over and over in a trace by
342 // using "interning".
343 //
344 // `type` is a field id in the `perfetto.protos.InternedData` protobuf message.
345 // `data` and `data_size` point to the raw data that is potentially repeated.
346 // The function returns an integer (the iid) that can be used instead of
347 // serializing the data directly in the packet. `*seen` is set to false if this
348 // is the first time the library observed this data for this specific type
349 // (therefore it allocated a new iid).
PerfettoTeLlIntern(struct PerfettoTeLlImplIncr * incr,int32_t type,const void * data,size_t data_size,bool * seen)350 static inline uint64_t PerfettoTeLlIntern(struct PerfettoTeLlImplIncr* incr,
351 int32_t type,
352 const void* data,
353 size_t data_size,
354 bool* seen) {
355 return PerfettoTeLlImplIntern(incr, type, data, data_size, seen);
356 }
357
358 // Used to lazily start, only if required, a nested InternedData submessage for
359 // a TracePacket `tp`. `incr` is the incremental state ABI pointer received from
360 // PerfettoTeLlIterator.
361 struct PerfettoTeLlInternContext {
362 struct PerfettoTeLlImplIncr* incr;
363 struct perfetto_protos_TracePacket* tp;
364 struct perfetto_protos_InternedData interned;
365 // true if the nested `interned` submessage has been started, false otherwise.
366 bool started;
367 };
368
PerfettoTeLlInternContextInit(struct PerfettoTeLlInternContext * ctx,struct PerfettoTeLlImplIncr * incr,struct perfetto_protos_TracePacket * tp)369 static inline void PerfettoTeLlInternContextInit(
370 struct PerfettoTeLlInternContext* ctx,
371 struct PerfettoTeLlImplIncr* incr,
372 struct perfetto_protos_TracePacket* tp) {
373 ctx->incr = incr;
374 ctx->tp = tp;
375 ctx->started = false;
376 }
377
PerfettoTeLlInternContextStartIfNeeded(struct PerfettoTeLlInternContext * ctx)378 static inline void PerfettoTeLlInternContextStartIfNeeded(
379 struct PerfettoTeLlInternContext* ctx) {
380 if (!ctx->started) {
381 ctx->started = true;
382 perfetto_protos_TracePacket_begin_interned_data(ctx->tp, &ctx->interned);
383 }
384 }
385
PerfettoTeLlInternContextDestroy(struct PerfettoTeLlInternContext * ctx)386 static inline void PerfettoTeLlInternContextDestroy(
387 struct PerfettoTeLlInternContext* ctx) {
388 if (ctx->started) {
389 perfetto_protos_TracePacket_end_interned_data(ctx->tp, &ctx->interned);
390 }
391 }
392
PerfettoTeLlInternRegisteredCat(struct PerfettoTeLlInternContext * ctx,struct PerfettoTeCategory * reg_cat)393 static inline void PerfettoTeLlInternRegisteredCat(
394 struct PerfettoTeLlInternContext* ctx,
395 struct PerfettoTeCategory* reg_cat) {
396 uint64_t iid = reg_cat->cat_iid;
397 bool seen;
398
399 if (!iid) {
400 return;
401 }
402 PerfettoTeLlIntern(ctx->incr,
403 perfetto_protos_InternedData_event_categories_field_number,
404 &iid, sizeof(iid), &seen);
405 if (!seen) {
406 struct perfetto_protos_EventCategory event_category;
407 PerfettoTeLlInternContextStartIfNeeded(ctx);
408
409 perfetto_protos_InternedData_begin_event_categories(&ctx->interned,
410 &event_category);
411 perfetto_protos_EventCategory_set_iid(&event_category, iid);
412 perfetto_protos_EventCategory_set_cstr_name(&event_category,
413 reg_cat->desc.name);
414 perfetto_protos_InternedData_end_event_categories(&ctx->interned,
415 &event_category);
416 }
417 }
418
PerfettoTeLlWriteRegisteredCat(struct perfetto_protos_TrackEvent * te,struct PerfettoTeCategory * reg_cat)419 static inline void PerfettoTeLlWriteRegisteredCat(
420 struct perfetto_protos_TrackEvent* te,
421 struct PerfettoTeCategory* reg_cat) {
422 if (reg_cat->cat_iid) {
423 perfetto_protos_TrackEvent_set_category_iids(te, reg_cat->cat_iid);
424 } else if (reg_cat->desc.name) {
425 perfetto_protos_TrackEvent_set_cstr_categories(te, reg_cat->desc.name);
426 }
427 }
428
PerfettoTeLlWriteDynamicCat(struct perfetto_protos_TrackEvent * te,struct PerfettoTeCategoryDescriptor * dyn_cat,int32_t type)429 static inline void PerfettoTeLlWriteDynamicCat(
430 struct perfetto_protos_TrackEvent* te,
431 struct PerfettoTeCategoryDescriptor* dyn_cat,
432 int32_t type) {
433 if (dyn_cat && type != PERFETTO_TE_TYPE_SLICE_END &&
434 type != PERFETTO_TE_TYPE_COUNTER) {
435 perfetto_protos_TrackEvent_set_cstr_categories(te, dyn_cat->name);
436 }
437 }
438
PerfettoTeLlInternEventName(struct PerfettoTeLlInternContext * ctx,const char * name)439 static inline uint64_t PerfettoTeLlInternEventName(
440 struct PerfettoTeLlInternContext* ctx,
441 const char* name) {
442 uint64_t iid = 0;
443 if (name) {
444 bool seen;
445 iid = PerfettoTeLlIntern(
446 ctx->incr, perfetto_protos_InternedData_event_names_field_number, name,
447 strlen(name), &seen);
448 if (!seen) {
449 struct perfetto_protos_EventName event_name;
450 PerfettoTeLlInternContextStartIfNeeded(ctx);
451 perfetto_protos_InternedData_begin_event_names(&ctx->interned,
452 &event_name);
453 perfetto_protos_EventName_set_iid(&event_name, iid);
454 perfetto_protos_EventName_set_cstr_name(&event_name, name);
455 perfetto_protos_InternedData_end_event_names(&ctx->interned, &event_name);
456 }
457 }
458 return iid;
459 }
460
PerfettoTeLlWriteEventName(struct perfetto_protos_TrackEvent * te,const char * name)461 static inline void PerfettoTeLlWriteEventName(
462 struct perfetto_protos_TrackEvent* te,
463 const char* name) {
464 if (name) {
465 perfetto_protos_TrackEvent_set_cstr_name(te, name);
466 }
467 }
468
PerfettoTeLlWriteInternedEventName(struct perfetto_protos_TrackEvent * te,uint64_t iid)469 static inline void PerfettoTeLlWriteInternedEventName(
470 struct perfetto_protos_TrackEvent* te,
471 uint64_t iid) {
472 if (iid != 0) {
473 perfetto_protos_TrackEvent_set_name_iid(te, iid);
474 }
475 }
476
PerfettoTeLlWriteTimestamp(struct perfetto_protos_TracePacket * tp,const struct PerfettoTeTimestamp * ts)477 static inline void PerfettoTeLlWriteTimestamp(
478 struct perfetto_protos_TracePacket* tp,
479 const struct PerfettoTeTimestamp* ts) {
480 uint32_t clock_id = ts->clock_id;
481 perfetto_protos_TracePacket_set_timestamp(tp, ts->value);
482 perfetto_protos_TracePacket_set_timestamp_clock_id(tp, clock_id);
483 }
484
PerfettoTeLlInternDbgArgName(struct PerfettoTeLlInternContext * ctx,const char * name)485 static inline uint64_t PerfettoTeLlInternDbgArgName(
486 struct PerfettoTeLlInternContext* ctx,
487 const char* name) {
488 uint64_t iid = 0;
489 if (name) {
490 bool seen;
491 iid = PerfettoTeLlIntern(
492 ctx->incr,
493 perfetto_protos_InternedData_debug_annotation_names_field_number, name,
494 strlen(name), &seen);
495 if (!seen) {
496 struct perfetto_protos_EventName event_name;
497 PerfettoTeLlInternContextStartIfNeeded(ctx);
498 perfetto_protos_InternedData_begin_event_names(&ctx->interned,
499 &event_name);
500 perfetto_protos_EventName_set_iid(&event_name, iid);
501 perfetto_protos_EventName_set_cstr_name(&event_name, name);
502 perfetto_protos_InternedData_end_event_names(&ctx->interned, &event_name);
503 }
504 }
505 return iid;
506 }
507
508 #endif // INCLUDE_PERFETTO_PUBLIC_TRACK_EVENT_H_
509