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 #include "perfetto/public/abi/track_event_hl_abi.h"
23 #include "perfetto/public/track_event.h"
24
25 // This header defines the PERFETTO_TE macros and its possible params (at the
26 // end of the file). The rest of the file contains internal implementation
27 // details of the macros, which are subject to change at any time.
28 //
29 // The macro uses the High level ABI to emit track events.
30
31 #define PERFETTO_I_TE_STATIC_ASSERT_NUM_PARAMS_( \
32 NAME_AND_TYPE1, NAME_AND_TYPE2, EXTRA1, EXTRA2, EXTRA3, EXTRA4, SENTINEL, \
33 ...) \
34 static_assert((SENTINEL) == 0, \
35 "Too many arguments for PERFETTO_TE " \
36 "macro")
37
38 // Fails to compile if there are too many params and they don't fit into
39 // PerfettoTeHlMacroParams.
40 #define PERFETTO_I_TE_STATIC_ASSERT_NUM_PARAMS(...) \
41 PERFETTO_I_TE_STATIC_ASSERT_NUM_PARAMS_(__VA_ARGS__, 0, 0, 0, 0, 0, 0)
42
43 #define PERFETTO_I_TE_LIMIT_4__(NAME_AND_TYPE1, NAME_AND_TYPE2, EXTRA1, \
44 EXTRA2, EXTRA3, EXTRA4, ...) \
45 NAME_AND_TYPE1, NAME_AND_TYPE2, EXTRA1, EXTRA2, EXTRA3, EXTRA4
46 #define PERFETTO_I_TE_LIMIT_4_(MACRO, ARGS) MACRO ARGS
47 #define PERFETTO_I_TE_LIMIT_4(...) \
48 PERFETTO_I_TE_LIMIT_4_(PERFETTO_I_TE_LIMIT_4__, (__VA_ARGS__))
49
50 // In C we have to use a compound literal. In C++ we can use a regular
51 // initializer.
52 #ifndef __cplusplus
53 #define PERFETTO_I_TE_HL_MACRO_PARAMS_PREAMBLE (struct PerfettoTeHlMacroParams)
54 #else
55 #define PERFETTO_I_TE_HL_MACRO_PARAMS_PREAMBLE
56 #endif
57
58 // Provides an initializer for `struct PerfettoTeHlMacroParams` and sets all the
59 // unused extra fields to PERFETTO_NULL.
60 #define PERFETTO_I_TE_HL_MACRO_PARAMS(...) \
61 PERFETTO_I_TE_HL_MACRO_PARAMS_PREAMBLE { \
62 PERFETTO_I_TE_LIMIT_4(__VA_ARGS__, PERFETTO_NULL, PERFETTO_NULL, \
63 PERFETTO_NULL, PERFETTO_NULL, PERFETTO_NULL, \
64 PERFETTO_NULL) \
65 }
66
67 // Implementation of the PERFETTO_TE macro. If `CAT` is enabled, emits the
68 // tracing event specified by the params.
69 //
70 // Uses `?:` instead of `if` because this might be used as an expression, where
71 // statements are not allowed.
72 #define PERFETTO_I_TE_IMPL(CAT, ...) \
73 ((PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT( \
74 (CAT).enabled, PERFETTO_MEMORY_ORDER_RELAXED))) \
75 ? (PerfettoTeHlCall((CAT).impl, \
76 PERFETTO_I_TE_HL_MACRO_PARAMS(__VA_ARGS__)), \
77 0) \
78 : 0)
79
80 #ifndef __cplusplus
81 #define PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, ...) \
82 &(struct STRUCT)__VA_ARGS__
83 #define PERFETTO_I_TE_EXTRA(STRUCT, ...) \
84 ((struct PerfettoTeHlExtra*)PERFETTO_I_TE_COMPOUND_LITERAL_ADDR( \
85 STRUCT, __VA_ARGS__))
86 #else
87 #define PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, ...) \
88 &(STRUCT{} = STRUCT __VA_ARGS__)
89 #define PERFETTO_I_TE_EXTRA(STRUCT, ...) \
90 reinterpret_cast<struct PerfettoTeHlExtra*>( \
91 PERFETTO_I_TE_COMPOUND_LITERAL_ADDR(STRUCT, __VA_ARGS__))
92 #endif
93
94 #define PERFETTO_I_TE_CONCAT2(a, b) a##b
95 #define PERFETTO_I_TE_CONCAT(a, b) PERFETTO_I_TE_CONCAT2(a, b)
96 // Generate a unique name with a given prefix.
97 #define PERFETTO_I_TE_UID(prefix) PERFETTO_I_TE_CONCAT(prefix, __LINE__)
98
99 struct PerfettoTeHlMacroNameAndType {
100 const char* name;
101 int32_t type;
102 };
103
104 struct PerfettoTeHlMacroParams {
105 struct PerfettoTeHlMacroNameAndType name_and_type;
106 struct PerfettoTeHlExtra* extra1;
107 struct PerfettoTeHlExtra* extra2;
108 struct PerfettoTeHlExtra* extra3;
109 struct PerfettoTeHlExtra* extra4;
110 };
111
PerfettoTeHlCall(struct PerfettoTeCategoryImpl * cat,struct PerfettoTeHlMacroParams params)112 static inline void PerfettoTeHlCall(struct PerfettoTeCategoryImpl* cat,
113 struct PerfettoTeHlMacroParams params) {
114 struct PerfettoTeHlExtra* perfetto_i_extra_data = PERFETTO_NULL;
115 if (params.extra1) {
116 params.extra1->next = perfetto_i_extra_data;
117 perfetto_i_extra_data = params.extra1;
118 }
119 if (params.extra2) {
120 params.extra2->next = perfetto_i_extra_data;
121 perfetto_i_extra_data = params.extra2;
122 }
123 if (params.extra3) {
124 params.extra3->next = perfetto_i_extra_data;
125 perfetto_i_extra_data = params.extra3;
126 }
127 if (params.extra4) {
128 params.extra4->next = perfetto_i_extra_data;
129 perfetto_i_extra_data = params.extra4;
130 }
131 PerfettoTeHlEmitImpl(cat, params.name_and_type.type,
132 params.name_and_type.name, perfetto_i_extra_data);
133 }
134
135 // Instead of a previously registered category, this macro can be used to
136 // specify that the category will be provided dynamically as a param.
137 #define PERFETTO_TE_DYNAMIC_CATEGORY PerfettoTeRegisteredDynamicCategory()
138
139 // -------------------------------------------------
140 // Possible types of event for the PERFETTO_TE macro
141 // -------------------------------------------------
142
143 // Begins a slice named `const char* NAME` on a track.
144 #define PERFETTO_TE_SLICE_BEGIN(NAME) \
145 { NAME, PERFETTO_TE_TYPE_SLICE_BEGIN }
146
147 // Ends the last slice opened on a track.
148 #define PERFETTO_TE_SLICE_END() \
149 { PERFETTO_NULL, PERFETTO_TE_TYPE_SLICE_END }
150
151 // Reports an instant event named `const char* NAME`.
152 #define PERFETTO_TE_INSTANT(NAME) \
153 { NAME, PERFETTO_TE_TYPE_INSTANT }
154
155 // Reports the value of a counter. The counter value must be specified
156 // separately on another param with PERFETTO_TE_INT_COUNTER() or
157 // PERFETTO_TE_DOUBLE_COUNTER().
158 #define PERFETTO_TE_COUNTER() \
159 { PERFETTO_NULL, PERFETTO_TE_TYPE_COUNTER }
160
161 // -------------------------------------------------
162 // Possible types of event for the PERFETTO_TE macro
163 // -------------------------------------------------
164
165 // The value (`C`) of an integer counter. A separate parameter must describe the
166 // counter track this refers to. This should only be used for events with
167 // type PERFETTO_TE_COUNTER().
168 #define PERFETTO_TE_INT_COUNTER(C) \
169 PERFETTO_I_TE_EXTRA( \
170 PerfettoTeHlExtraCounterInt64, \
171 {{PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64, PERFETTO_NULL}, C})
172
173 // The value (`C`) of a floating point. A separate parameter must describe the
174 // counter track this refers to. This should only be used for events with type
175 // PERFETTO_TE_COUNTER().
176 #define PERFETTO_TE_DOUBLE_COUNTER(C) \
177 PERFETTO_I_TE_EXTRA( \
178 PerfettoTeHlExtraCounterDouble, \
179 {{PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE, PERFETTO_NULL}, C})
180
181 // Uses the timestamp `struct PerfettoTeTimestamp T` to report this event. If
182 // this is not specified, PERFETTO_TE() reads the current timestamp with
183 // PerfettoTeGetTimestamp().
184 #define PERFETTO_TE_TIMESTAMP(T) \
185 PERFETTO_I_TE_EXTRA( \
186 PerfettoTeHlExtraTimestamp, \
187 {{PERFETTO_TE_HL_EXTRA_TYPE_TIMESTAMP, PERFETTO_NULL}, T})
188
189 // Specifies that the current track for this event is
190 // `struct PerfettoTeRegisteredTrack* T`, which must have been previously
191 // registered.
192 #define PERFETTO_TE_REGISTERED_TRACK(T) \
193 PERFETTO_I_TE_EXTRA( \
194 PerfettoTeHlExtraRegisteredTrack, \
195 {{PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK, PERFETTO_NULL}, \
196 &(T)->impl})
197
198 // Specifies that the current track for this event is a track named `const char
199 // *NAME`, child of a track whose uuid is `PARENT_UUID`. `NAME`, `uint64_t ID`
200 // and `PARENT_UUID` uniquely identify a track. Common values for `PARENT_UUID`
201 // include PerfettoTeProcessTrackUuid(), PerfettoTeThreadTrackUuid() or
202 // PerfettoTeGlobalTrackUuid().
203 #define PERFETTO_TE_NAMED_TRACK(NAME, ID, PARENT_UUID) \
204 PERFETTO_I_TE_EXTRA(PerfettoTeHlExtraNamedTrack, \
205 {{PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK, PERFETTO_NULL}, \
206 NAME, \
207 ID, \
208 PARENT_UUID})
209
210 // When PERFETTO_TE_DYNAMIC_CATEGORY is used, this is used to specify `const
211 // char* S` as a category name.
212 #define PERFETTO_TE_DYNAMIC_CATEGORY_STRING(S) \
213 PERFETTO_I_TE_EXTRA( \
214 PerfettoTeHlExtraDynamicCategory, \
215 {{PERFETTO_TE_HL_EXTRA_TYPE_DYNAMIC_CATEGORY, PERFETTO_NULL}, \
216 PERFETTO_I_TE_COMPOUND_LITERAL_ADDR( \
217 PerfettoTeCategoryDescriptor, \
218 {S, PERFETTO_NULL, PERFETTO_NULL, 0})})
219
220 // Adds the debug annotation named `const char * NAME` with value `bool VALUE`.
221 #define PERFETTO_TE_ARG_BOOL(NAME, VALUE) \
222 PERFETTO_I_TE_EXTRA( \
223 PerfettoTeHlExtraDebugArgBool, \
224 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL, PERFETTO_NULL}, \
225 NAME, \
226 VALUE})
227
228 // Adds the debug annotation named `const char * NAME` with value `uint64_t
229 // VALUE`.
230 #define PERFETTO_TE_ARG_UINT64(NAME, VALUE) \
231 PERFETTO_I_TE_EXTRA( \
232 PerfettoTeHlExtraDebugArgUint64, \
233 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_UINT64, PERFETTO_NULL}, \
234 NAME, \
235 VALUE})
236
237 // Adds the debug annotation named `const char * NAME` with value `int64_t
238 // VALUE`.
239 #define PERFETTO_TE_ARG_INT64(NAME, VALUE) \
240 PERFETTO_I_TE_EXTRA( \
241 PerfettoTeHlExtraDebugArgInt64, \
242 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64, PERFETTO_NULL}, \
243 NAME, \
244 VALUE})
245
246 // Adds the debug annotation named `const char * NAME` with value `double
247 // VALUE`.
248 #define PERFETTO_TE_ARG_DOUBLE(NAME, VALUE) \
249 PERFETTO_I_TE_EXTRA( \
250 PerfettoTeHlExtraDebugArgDouble, \
251 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE, PERFETTO_NULL}, \
252 NAME, \
253 VALUE})
254
255 // Adds the debug annotation named `const char * NAME` with value `const char*
256 // VALUE`.
257 #define PERFETTO_TE_ARG_STRING(NAME, VALUE) \
258 PERFETTO_I_TE_EXTRA( \
259 PerfettoTeHlExtraDebugArgString, \
260 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING, PERFETTO_NULL}, \
261 NAME, \
262 VALUE})
263
264 // Adds the debug annotation named `const char * NAME` with value `void* VALUE`.
265 #define PERFETTO_TE_ARG_POINTER(NAME, VALUE) \
266 PERFETTO_I_TE_EXTRA( \
267 PerfettoTeHlExtraDebugArgPointer, \
268 {{PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_POINTER, PERFETTO_NULL}, \
269 NAME, \
270 VALUE})
271
272 // Specifies that this event is part (or starts) a "flow" (i.e. a link among
273 // different events). The flow is identified by `struct PerfettoTeFlow VALUE`.
274 #define PERFETTO_TE_FLOW(VALUE) \
275 PERFETTO_I_TE_EXTRA( \
276 PerfettoTeHlExtraFlow, \
277 {{PERFETTO_TE_HL_EXTRA_TYPE_FLOW, PERFETTO_NULL}, (VALUE).id})
278
279 // Specifies that this event terminates a "flow" (i.e. a link among different
280 // events). The flow is identified by `struct PerfettoTeFlow VALUE`.
281 #define PERFETTO_TE_TERMINATING_FLOW(VALUE) \
282 PERFETTO_I_TE_EXTRA( \
283 PerfettoTeHlExtraFlow, \
284 {{PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW, PERFETTO_NULL}, \
285 (VALUE).id})
286
287 // Flushes the shared memory buffer and makes sure that all the previous events
288 // emitted by this thread are visibile in the central tracing buffer.
289 #define PERFETTO_TE_FLUSH() \
290 PERFETTO_I_TE_EXTRA(PerfettoTeHlExtra, \
291 {PERFETTO_TE_HL_EXTRA_TYPE_FLUSH, PERFETTO_NULL})
292
293 // Turns off interning for event names.
294 #define PERFETTO_TE_NO_INTERN() \
295 PERFETTO_I_TE_EXTRA(PerfettoTeHlExtra, \
296 {PERFETTO_TE_HL_EXTRA_TYPE_NO_INTERN, PERFETTO_NULL})
297
298 // ----------------------------------
299 // The main PERFETTO_TE tracing macro
300 // ----------------------------------
301 //
302 // If tracing is active and the passed tracing category is enabled, adds an
303 // entry in the tracing stream of the perfetto track event data source.
304 // Parameters:
305 // * `CAT`: The tracing category (it should be a struct
306 // PerfettoTeCategory object). It can be
307 // PERFETTO_TE_DYNAMIC_CATEGORY for dynamic categories (the dynamic category
308 // name should be passed later with)
309 // * The type of the event. It can be one of:
310 // * PERFETTO_TE_SLICE_BEGIN(name)
311 // * PERFETTO_TE_SLICE_END()
312 // * PERFETTO_TE_INSTANT()
313 // * PERFETTO_TE_COUNTER()
314 // * `...`: One or more (up to 4) macro parameters from the above list that
315 // specify the data to be traced.
316 //
317 // Examples:
318 //
319 // PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN("name"),
320 // PERFETTO_TE_ARG_UINT64("extra_arg", 42));
321 // PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
322 // PERFETTO_TE(category, PERFETTO_TE_COUNTER(),
323 // PERFETTO_TE_REGISTERED_TRACK(&mycounter),
324 // PERFETTO_TE_INT_COUNTER(79));
325 // PERFETTO_TE(PERFETTO_TE_DYNAMIC_CATEGORY, PERFETTO_TE_INSTANT("instant"),
326 // PERFETTO_TE_DYNAMIC_CATEGORY_STRING("category"));
327 //
328 #define PERFETTO_TE(CAT, ...) \
329 do { \
330 PERFETTO_I_TE_STATIC_ASSERT_NUM_PARAMS(__VA_ARGS__); \
331 (void)PERFETTO_I_TE_IMPL(CAT, __VA_ARGS__); \
332 } while (0)
333
334 #ifdef __cplusplus
335
336 // Begins a slice named `const char* NAME` on the current thread track.
337 //
338 // This is supposed to be used with PERFETTO_TE_SCOPED(). The implementation is
339 // identical to PERFETTO_TE_SLICE_BEGIN(): this has a different name to
340 // highlight the fact that PERFETTO_TE_SCOPED() also adds a
341 // PERFETTO_TE_SLICE_END().
342 #define PERFETTO_TE_SLICE(NAME) \
343 { NAME, PERFETTO_TE_TYPE_SLICE_BEGIN }
344
345 namespace perfetto::internal {
346 template <typename F>
347 class TeCleanup {
348 public:
TeCleanup(F && f)349 explicit TeCleanup(F&& f) PERFETTO_ALWAYS_INLINE : f_(std::forward<F>(f)) {}
350
~TeCleanup()351 ~TeCleanup() PERFETTO_ALWAYS_INLINE { f_(); }
352
353 private:
354 TeCleanup(const TeCleanup&) = delete;
355 TeCleanup(TeCleanup&&) = delete;
356 TeCleanup& operator=(const TeCleanup&) = delete;
357 TeCleanup& operator=(TeCleanup&&) = delete;
358 F f_;
359 };
360
361 template <typename F>
MakeTeCleanup(F && f)362 TeCleanup<F> MakeTeCleanup(F&& f) {
363 return TeCleanup<F>(std::forward<F>(f));
364 }
365
366 } // namespace perfetto::internal
367
368 // ------------------------
369 // PERFETTO_TE_SCOPED macro
370 // ------------------------
371 //
372 // Emits an event immediately and a PERFETTO_TE_SLICE_END event when the current
373 // scope terminates.
374 //
375 // All the extra params are added only to the event emitted immediately, not to
376 // the END event.
377 //
378 // TRACK params are not supported.
379 //
380 // This
381 // {
382 // PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"), ...);
383 // ...
384 // }
385 // is equivalent to
386 // {
387 // PERFETTO_TE(category, PERFETTO_TE_SLICE_BEGIN("name"), ...);
388 // ...
389 // PERFETTO_TE(category, PERFETTO_TE_SLICE_END());
390 // }
391 //
392 // Examples:
393 //
394 // PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"));
395 // PERFETTO_TE_SCOPED(category, PERFETTO_TE_SLICE("name"),
396 // PERFETTO_TE_ARG_UINT64("count", 42));
397 //
398 #define PERFETTO_TE_SCOPED(CAT, ...) \
399 auto PERFETTO_I_TE_UID(perfetto_i_te_cleanup) = \
400 (PERFETTO_I_TE_IMPL(CAT, __VA_ARGS__), \
401 perfetto::internal::MakeTeCleanup([&] { \
402 PERFETTO_I_TE_STATIC_ASSERT_NUM_PARAMS(__VA_ARGS__); \
403 PERFETTO_TE(CAT, PERFETTO_TE_SLICE_END()); \
404 }))
405
406 #endif // __cplusplus
407
408 #endif // INCLUDE_PERFETTO_PUBLIC_TE_MACROS_H_
409