• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TE_MACROS_H_
18 #define INCLUDE_PERFETTO_PUBLIC_TE_MACROS_H_
19 
20 #include <assert.h>
21 
22 #ifdef __cplusplus
23 #include <initializer_list>
24 #endif
25 
26 #include "perfetto/public/abi/track_event_hl_abi.h"
27 #include "perfetto/public/pb_utils.h"
28 #include "perfetto/public/track_event.h"
29 
30 // This header defines the PERFETTO_TE macros and its possible params (at the
31 // end of the file). The rest of the file contains internal implementation
32 // details of the macros, which are subject to change at any time.
33 //
34 // The macro uses the High level ABI to emit track events.
35 
36 #define PERFETTO_I_TE_HL_MACRO_PARAMS__(NAME_AND_TYPE, ...)           \
37   NAME_AND_TYPE.type, NAME_AND_TYPE.name,                             \
38       PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(struct PerfettoTeHlExtra*, \
39                                            {__VA_ARGS__})
40 
41 // Level of indirection for MSVC traditional preprocessor.
42 #define PERFETTO_I_TE_HL_MACRO_PARAMS_(MACRO, ARGS) MACRO ARGS
43 
44 // Provides an initializer for `struct PerfettoTeHlMacroParams` and sets all the
45 // unused extra fields to PERFETTO_NULL.
46 #define PERFETTO_I_TE_HL_MACRO_PARAMS(...)                        \
47   PERFETTO_I_TE_HL_MACRO_PARAMS_(PERFETTO_I_TE_HL_MACRO_PARAMS__, \
48                                  (__VA_ARGS__, PERFETTO_NULL))
49 
50 // Implementation of the PERFETTO_TE macro. If `CAT` is enabled, emits the
51 // tracing event specified by the params.
52 //
53 // Uses `?:` instead of `if` because this might be used as an expression, where
54 // statements are not allowed.
55 #define PERFETTO_I_TE_IMPL(CAT, ...)                                        \
56   ((PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(                        \
57        (CAT).enabled, PERFETTO_MEMORY_ORDER_RELAXED)))                      \
58        ? (PerfettoTeHlEmitImpl((CAT).impl,                                  \
59                                PERFETTO_I_TE_HL_MACRO_PARAMS(__VA_ARGS__)), \
60           0)                                                                \
61        : 0)
62 
63 #ifndef __cplusplus
64 #define PERFETTO_I_TE_COMPOUND_LITERAL(STRUCT, ...) (struct STRUCT) __VA_ARGS__
65 #define PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, ...) \
66   &(struct STRUCT)__VA_ARGS__
67 #define PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(TYPE, ...) (TYPE[]) __VA_ARGS__
68 #define PERFETTO_I_TE_EXTRA(STRUCT, ...)                           \
69   ((struct PerfettoTeHlExtra*)PERFETTO_I_TE_COMPOUND_LITERAL_ADDR( \
70       STRUCT, __VA_ARGS__))
71 #else
72 #define PERFETTO_I_TE_COMPOUND_LITERAL(STRUCT, ...) STRUCT __VA_ARGS__
73 #define PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, ...) \
74   &(STRUCT{} = STRUCT __VA_ARGS__)
75 #define PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(TYPE, ...) \
76   static_cast<TYPE const*>((std::initializer_list<TYPE> __VA_ARGS__).begin())
77 #define PERFETTO_I_TE_EXTRA(STRUCT, ...)       \
78   reinterpret_cast<struct PerfettoTeHlExtra*>( \
79       PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, __VA_ARGS__))
80 #endif
81 
82 #define PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(NAME, TYPE) \
83   (PERFETTO_I_TE_COMPOUND_LITERAL(PerfettoTeHlMacroNameAndType, {NAME, TYPE}))
84 
85 #define PERFETTO_I_TE_CONCAT2(a, b) a##b
86 #define PERFETTO_I_TE_CONCAT(a, b) PERFETTO_I_TE_CONCAT2(a, b)
87 // Generate a unique name with a given prefix.
88 #define PERFETTO_I_TE_UID(prefix) PERFETTO_I_TE_CONCAT(prefix, __LINE__)
89 
90 struct PerfettoTeHlMacroNameAndType {
91   const char* name;
92   int32_t type;
93 };
94 
95 // Instead of a previously registered category, this macro can be used to
96 // specify that the category will be provided dynamically as a param.
97 #define PERFETTO_TE_DYNAMIC_CATEGORY PerfettoTeRegisteredDynamicCategory()
98 
99 // ---------------------------------------------------------------
100 // Possible types of fields for the PERFETTO_TE_PROTO_FIELDS macro
101 // ---------------------------------------------------------------
102 
103 // A string or bytes protobuf field (with field id `ID`) and value `VAL` (a null
104 // terminated string).
105 #define PERFETTO_TE_PROTO_FIELD_CSTR(ID, VAL)                    \
106   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,      \
107                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR( \
108                                 PerfettoTeHlProtoFieldCstr,      \
109                                 {{PERFETTO_TE_HL_PROTO_TYPE_CSTR, ID}, VAL}))
110 
111 // A string or bytes protobuf field (with field id `ID`) with a `SIZE` long
112 // value starting from `VAL`.
113 #define PERFETTO_TE_PROTO_FIELD_BYTES(ID, VAL, SIZE) \
114   PERFETTO_REINTERPRET_CAST(                         \
115       struct PerfettoTeHlProtoField*,                \
116       PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(           \
117           PerfettoTeHlProtoFieldBytes,               \
118           {{PERFETTO_TE_HL_PROTO_TYPE_BYTES, ID}, VAL, SIZE}))
119 
120 // An varint protobuf field (with field id `ID`) and value `VAL`.
121 #define PERFETTO_TE_PROTO_FIELD_VARINT(ID, VAL)                          \
122   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,              \
123                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(         \
124                                 PerfettoTeHlProtoFieldVarInt,            \
125                                 {{PERFETTO_TE_HL_PROTO_TYPE_VARINT, ID}, \
126                                  PERFETTO_STATIC_CAST(uint64_t, VAL)}))
127 
128 // An zigzag (sint*) protobuf field (with field id `ID`) and value `VAL`.
129 #define PERFETTO_TE_PROTO_FIELD_ZIGZAG(ID, VAL)    \
130   PERFETTO_REINTERPRET_CAST(                       \
131       struct PerfettoTeHlProtoField*,              \
132       PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(         \
133           PerfettoTeHlProtoFieldVarInt,            \
134           {{PERFETTO_TE_HL_PROTO_TYPE_VARINT, ID}, \
135            PerfettoPbZigZagEncode64(PERFETTO_STATIC_CAST(int64_t, VAL))}))
136 
137 // A fixed64 protobuf field (with field id `ID`) and value `VAL`.
138 #define PERFETTO_TE_PROTO_FIELD_FIXED64(ID, VAL)                          \
139   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,               \
140                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(          \
141                                 PerfettoTeHlProtoFieldFixed64,            \
142                                 {{PERFETTO_TE_HL_PROTO_TYPE_FIXED64, ID}, \
143                                  PERFETTO_STATIC_CAST(uint64_t, VAL)}))
144 
145 // A fixed32 protobuf field (with field id `ID`) and value `VAL`.
146 #define PERFETTO_TE_PROTO_FIELD_FIXED32(ID, VAL)                          \
147   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,               \
148                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(          \
149                                 PerfettoTeHlProtoFieldFixed32,            \
150                                 {{PERFETTO_TE_HL_PROTO_TYPE_FIXED32, ID}, \
151                                  PERFETTO_STATIC_CAST(uint32_t, VAL)}))
152 
153 // A double protobuf field (with field id `ID`) and value `VAL`.
154 #define PERFETTO_TE_PROTO_FIELD_DOUBLE(ID, VAL)                          \
155   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,              \
156                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(         \
157                                 PerfettoTeHlProtoFieldDouble,            \
158                                 {{PERFETTO_TE_HL_PROTO_TYPE_DOUBLE, ID}, \
159                                  PERFETTO_STATIC_CAST(double, VAL)}))
160 
161 // A float protobuf field (with field id `ID`) and value `VAL`.
162 #define PERFETTO_TE_PROTO_FIELD_FLOAT(ID, VAL)                                 \
163   PERFETTO_REINTERPRET_CAST(                                                   \
164       struct PerfettoTeHlProtoField*,                                          \
165       PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(                                     \
166           PerfettoTeHlProtoFieldFloat, {{PERFETTO_TE_HL_PROTO_TYPE_FLOAT, ID}, \
167                                         PERFETTO_STATIC_CAST(float, VAL)}))
168 
169 // A nested message protobuf field (with field id `ID`). The rest of the
170 // argument can be PERFETTO_TE_PROTO_FIELD_*.
171 #define PERFETTO_TE_PROTO_FIELD_NESTED(ID, ...)                          \
172   PERFETTO_REINTERPRET_CAST(struct PerfettoTeHlProtoField*,              \
173                             PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(         \
174                                 PerfettoTeHlProtoFieldNested,            \
175                                 {{PERFETTO_TE_HL_PROTO_TYPE_NESTED, ID}, \
176                                  PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(   \
177                                      struct PerfettoTeHlProtoField*,     \
178                                      {__VA_ARGS__, PERFETTO_NULL})}))
179 
180 // -------------------------------------------------
181 // Possible types of event for the PERFETTO_TE macro
182 // -------------------------------------------------
183 
184 // Begins a slice named `const char* NAME` on a track.
185 #define PERFETTO_TE_SLICE_BEGIN(NAME) \
186   PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(NAME, PERFETTO_TE_TYPE_SLICE_BEGIN)
187 
188 // Ends the last slice opened on a track.
189 #define PERFETTO_TE_SLICE_END()                       \
190   PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(PERFETTO_NULL, \
191                                        PERFETTO_TE_TYPE_SLICE_END)
192 
193 // Reports an instant event named `const char* NAME`.
194 #define PERFETTO_TE_INSTANT(NAME) \
195   PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(NAME, PERFETTO_TE_TYPE_INSTANT)
196 
197 // Reports the value of a counter. The counter value must be specified
198 // separately on another param with PERFETTO_TE_INT_COUNTER() or
199 // PERFETTO_TE_DOUBLE_COUNTER().
200 #define PERFETTO_TE_COUNTER() \
201   PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(PERFETTO_NULL, PERFETTO_TE_TYPE_COUNTER)
202 
203 // -----------------------------------------------------------
204 // Possible types of extra arguments for the PERFETTO_TE macro
205 // -----------------------------------------------------------
206 
207 // The value (`C`) of an integer counter. A separate parameter must describe the
208 // counter track this refers to. This should only be used for events with
209 // type PERFETTO_TE_COUNTER().
210 #define PERFETTO_TE_INT_COUNTER(C)                   \
211   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraCounterInt64, \
212                       {{PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64}, C})
213 
214 // The value (`C`) of a floating point. A separate parameter must describe the
215 // counter track this refers to. This should only be used for events with type
216 // PERFETTO_TE_COUNTER().
217 #define PERFETTO_TE_DOUBLE_COUNTER(C)                 \
218   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraCounterDouble, \
219                       {{PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE}, C})
220 
221 // Uses the timestamp `struct PerfettoTeTimestamp T` to report this event. If
222 // this is not specified, PERFETTO_TE() reads the current timestamp with
223 // PerfettoTeGetTimestamp().
224 #define PERFETTO_TE_TIMESTAMP(T)                  \
225   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraTimestamp, \
226                       {{PERFETTO_TE_HL_EXTRA_TYPE_TIMESTAMP}, T})
227 
228 // Specifies that the current track for this event is
229 // `struct PerfettoTeRegisteredTrack* T`, which must have been previously
230 // registered.
231 #define PERFETTO_TE_REGISTERED_TRACK(T) \
232   PERFETTO_I_TE_EXTRA(                  \
233       PerfettoTeHlExtraRegisteredTrack, \
234       {{PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK}, &(T)->impl})
235 
236 // Specifies that the current track for this event is a track named `const char
237 // *NAME`, child of a track whose uuid is `PARENT_UUID`. `NAME`, `uint64_t ID`
238 // and `PARENT_UUID` uniquely identify a track. Common values for `PARENT_UUID`
239 // include PerfettoTeProcessTrackUuid(), PerfettoTeThreadTrackUuid() or
240 // PerfettoTeGlobalTrackUuid().
241 #define PERFETTO_TE_NAMED_TRACK(NAME, ID, PARENT_UUID) \
242   PERFETTO_I_TE_EXTRA(                                 \
243       PerfettoTeHlExtraNamedTrack,                     \
244       {{PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK}, NAME, ID, PARENT_UUID})
245 
246 // When PERFETTO_TE_DYNAMIC_CATEGORY is used, this is used to specify `const
247 // char* S` as a category name.
248 #define PERFETTO_TE_DYNAMIC_CATEGORY_STRING(S)                       \
249   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraDynamicCategory,              \
250                       {{PERFETTO_TE_HL_EXTRA_TYPE_DYNAMIC_CATEGORY}, \
251                        PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(          \
252                            PerfettoTeCategoryDescriptor,             \
253                            {S, PERFETTO_NULL, PERFETTO_NULL, 0})})
254 
255 // Adds the debug annotation named `const char * NAME` with value `bool VALUE`.
256 #define PERFETTO_TE_ARG_BOOL(NAME, VALUE) \
257   PERFETTO_I_TE_EXTRA(                    \
258       PerfettoTeHlExtraDebugArgBool,      \
259       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL}, NAME, VALUE})
260 
261 // Adds the debug annotation named `const char * NAME` with value `uint64_t
262 // VALUE`.
263 #define PERFETTO_TE_ARG_UINT64(NAME, VALUE) \
264   PERFETTO_I_TE_EXTRA(                      \
265       PerfettoTeHlExtraDebugArgUint64,      \
266       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_UINT64}, NAME, VALUE})
267 
268 // Adds the debug annotation named `const char * NAME` with value `int64_t
269 // VALUE`.
270 #define PERFETTO_TE_ARG_INT64(NAME, VALUE) \
271   PERFETTO_I_TE_EXTRA(                     \
272       PerfettoTeHlExtraDebugArgInt64,      \
273       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64}, NAME, VALUE})
274 
275 // Adds the debug annotation named `const char * NAME` with value `double
276 // VALUE`.
277 #define PERFETTO_TE_ARG_DOUBLE(NAME, VALUE) \
278   PERFETTO_I_TE_EXTRA(                      \
279       PerfettoTeHlExtraDebugArgDouble,      \
280       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE}, NAME, VALUE})
281 
282 // Adds the debug annotation named `const char * NAME` with value `const char*
283 // VALUE`.
284 #define PERFETTO_TE_ARG_STRING(NAME, VALUE) \
285   PERFETTO_I_TE_EXTRA(                      \
286       PerfettoTeHlExtraDebugArgString,      \
287       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING}, NAME, VALUE})
288 
289 // Adds the debug annotation named `const char * NAME` with value `void* VALUE`.
290 #define PERFETTO_TE_ARG_POINTER(NAME, VALUE) \
291   PERFETTO_I_TE_EXTRA(                       \
292       PerfettoTeHlExtraDebugArgPointer,      \
293       {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_POINTER}, NAME, VALUE})
294 
295 // Specifies that this event is part (or starts) a "flow" (i.e. a link among
296 // different events). The flow is identified by `struct PerfettoTeFlow VALUE`.
297 #define PERFETTO_TE_FLOW(VALUE)              \
298   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraFlow, \
299                       {{PERFETTO_TE_HL_EXTRA_TYPE_FLOW}, (VALUE).id})
300 
301 // Specifies that this event terminates a "flow" (i.e. a link among different
302 // events). The flow is identified by `struct PerfettoTeFlow VALUE`.
303 #define PERFETTO_TE_TERMINATING_FLOW(VALUE) \
304   PERFETTO_I_TE_EXTRA(                      \
305       PerfettoTeHlExtraFlow,                \
306       {{PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW}, (VALUE).id})
307 
308 // Flushes the shared memory buffer and makes sure that all the previous events
309 // emitted by this thread are visibile in the central tracing buffer.
310 #define PERFETTO_TE_FLUSH() \
311   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtra, {PERFETTO_TE_HL_EXTRA_TYPE_FLUSH})
312 
313 // Turns off interning for event names.
314 #define PERFETTO_TE_NO_INTERN() \
315   PERFETTO_I_TE_EXTRA(PerfettoTeHlExtra, {PERFETTO_TE_HL_EXTRA_TYPE_NO_INTERN})
316 
317 // Adds some proto fields to the event. The arguments should use the
318 // PERFETTO_TE_PROTO_FIELD_* macros and should be fields of the
319 // perfetto.protos.TrackEvent protobuf message.
320 #define PERFETTO_TE_PROTO_FIELDS(...)                                       \
321   PERFETTO_I_TE_EXTRA(                                                      \
322       PerfettoTeHlExtraProtoFields,                                         \
323       {{PERFETTO_TE_HL_EXTRA_TYPE_PROTO_FIELDS},                            \
324        PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(struct PerfettoTeHlProtoField*, \
325                                             {__VA_ARGS__, PERFETTO_NULL})})
326 
327 // Specifies (manually) the track for this event
328 // * `UUID` can be computed with e.g.:
329 //   * PerfettoTeCounterTrackUuid()
330 //   * PerfettoTeNamedTrackUuid()
331 // * `...` the rest of the params should be PERFETTO_TE_PROTO_FIELD_* macros
332 //   and should be fields of the perfetto.protos.TrackDescriptor protobuf
333 //   message.
334 #define PERFETTO_TE_PROTO_TRACK(UUID, ...)                                  \
335   PERFETTO_I_TE_EXTRA(                                                      \
336       PerfettoTeHlExtraProtoTrack,                                          \
337       {{PERFETTO_TE_HL_EXTRA_TYPE_PROTO_TRACK},                             \
338        UUID,                                                                \
339        PERFETTO_I_TE_COMPOUND_LITERAL_ARRAY(struct PerfettoTeHlProtoField*, \
340                                             {__VA_ARGS__, PERFETTO_NULL})})
341 
342 // Specifies that the current track for this event is a counter track named
343 // `const char *NAME`, child of a track whose uuid is `PARENT_UUID`. `NAME`
344 // and `PARENT_UUID` uniquely identify a track. Common values for `PARENT_UUID`
345 // include PerfettoTeProcessTrackUuid(), PerfettoTeThreadTrackUuid() or
346 // PerfettoTeGlobalTrackUuid().
347 #define PERFETTO_TE_COUNTER_TRACK(NAME, PARENT_UUID)                           \
348   PERFETTO_TE_PROTO_TRACK(                                                     \
349       PerfettoTeCounterTrackUuid(NAME, PARENT_UUID),                           \
350       PERFETTO_TE_PROTO_FIELD_VARINT(                                          \
351           perfetto_protos_TrackDescriptor_parent_uuid_field_number,            \
352           PARENT_UUID),                                                        \
353       PERFETTO_TE_PROTO_FIELD_CSTR(                                            \
354           perfetto_protos_TrackDescriptor_name_field_number, NAME),            \
355       PERFETTO_TE_PROTO_FIELD_BYTES(                                           \
356           perfetto_protos_TrackDescriptor_counter_field_number, PERFETTO_NULL, \
357           0))
358 
359 // ----------------------------------
360 // The main PERFETTO_TE tracing macro
361 // ----------------------------------
362 //
363 // If tracing is active and the passed tracing category is enabled, adds an
364 // entry in the tracing stream of the perfetto track event data source.
365 // Parameters:
366 // * `CAT`: The tracing category (it should be a struct
367 //   PerfettoTeCategory object). It can be
368 //   PERFETTO_TE_DYNAMIC_CATEGORY for dynamic categories (the dynamic category
369 //   name should be passed later with)
370 // * The type of the event. It can be one of:
371 //   * PERFETTO_TE_SLICE_BEGIN(name)
372 //   * PERFETTO_TE_SLICE_END()
373 //   * PERFETTO_TE_INSTANT()
374 //   * PERFETTO_TE_COUNTER()
375 // * `...`: One or more macro parameters from the above list that specify the
376 //   data to be traced.
377 //
378 // Examples:
379 //
380 // PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN("name"),
381 //             PERFETTO_TE_ARG_UINT64("extra_arg", 42));
382 // PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
383 // PERFETTO_TE(category, PERFETTO_TE_COUNTER(),
384 //             PERFETTO_TE_REGISTERED_TRACK(&mycounter),
385 //             PERFETTO_TE_INT_COUNTER(79));
386 // PERFETTO_TE(PERFETTO_TE_DYNAMIC_CATEGORY, PERFETTO_TE_INSTANT("instant"),
387 //             PERFETTO_TE_DYNAMIC_CATEGORY_STRING("category"));
388 //
389 #define PERFETTO_TE(CAT, ...) PERFETTO_I_TE_IMPL(CAT, __VA_ARGS__)
390 
391 #ifdef __cplusplus
392 
393 // Begins a slice named `const char* NAME` on the current thread track.
394 //
395 // This is supposed to be used with PERFETTO_TE_SCOPED(). The implementation is
396 // identical to PERFETTO_TE_SLICE_BEGIN(): this has a different name to
397 // highlight the fact that PERFETTO_TE_SCOPED() also adds a
398 // PERFETTO_TE_SLICE_END().
399 #define PERFETTO_TE_SLICE(NAME) \
400   PERFETTO_I_TE_HL_MACRO_NAME_AND_TYPE(NAME, PERFETTO_TE_TYPE_SLICE_BEGIN)
401 
402 namespace perfetto::internal {
403 template <typename F>
404 class TeCleanup {
405  public:
TeCleanup(F && f)406   explicit TeCleanup(F&& f) PERFETTO_ALWAYS_INLINE : f_(std::forward<F>(f)) {}
407 
~TeCleanup()408   ~TeCleanup() PERFETTO_ALWAYS_INLINE { f_(); }
409 
410  private:
411   TeCleanup(const TeCleanup&) = delete;
412   TeCleanup(TeCleanup&&) = delete;
413   TeCleanup& operator=(const TeCleanup&) = delete;
414   TeCleanup& operator=(TeCleanup&&) = delete;
415   F f_;
416 };
417 
418 template <typename F>
MakeTeCleanup(F && f)419 TeCleanup<F> MakeTeCleanup(F&& f) {
420   return TeCleanup<F>(std::forward<F>(f));
421 }
422 
423 }  // namespace perfetto::internal
424 
425 // ------------------------
426 // PERFETTO_TE_SCOPED macro
427 // ------------------------
428 //
429 // Emits an event immediately and a PERFETTO_TE_SLICE_END event when the current
430 // scope terminates.
431 //
432 // All the extra params are added only to the event emitted immediately, not to
433 // the END event.
434 //
435 // TRACK params are not supported.
436 //
437 // This
438 // {
439 //   PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"), ...);
440 //   ...
441 // }
442 // is equivalent to
443 // {
444 //   PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN("name"), ...);
445 //   ...
446 //   PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
447 // }
448 //
449 // Examples:
450 //
451 // PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"));
452 // PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"),
453 //                    PERFETTO_TE_ARG_UINT64("count", 42));
454 //
455 #define PERFETTO_TE_SCOPED(CAT, ...)              \
456   auto PERFETTO_I_TE_UID(perfetto_i_te_cleanup) = \
457       (PERFETTO_I_TE_IMPL(CAT, __VA_ARGS__),      \
458        perfetto::internal::MakeTeCleanup(         \
459            [&] { PERFETTO_TE(CAT, PERFETTO_TE_SLICE_END()); }))
460 
461 #endif  // __cplusplus
462 
463 #endif  // INCLUDE_PERFETTO_PUBLIC_TE_MACROS_H_
464