• 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 #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