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