1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //
6 // Internal declarations used by the C tracing macros.
7 // This is not part of the public API: use <trace/event.h> instead.
8 //
9
10 #ifndef TRACE_INTERNAL_EVENT_INTERNAL_H_
11 #define TRACE_INTERNAL_EVENT_INTERNAL_H_
12
13 #include <zircon/compiler.h>
14
15 #include <trace-engine/instrumentation.h>
16 #include <trace/internal/event_args.h>
17
18 __BEGIN_CDECLS
19
20 // Variable used to refer to the current trace context.
21 #define TRACE_INTERNAL_CONTEXT __trace_context
22
23 // Variable used to hold call-site cache state.
24 #define TRACE_INTERNAL_SITE_STATE __trace_site_state
25
26 // Variable used to refer to the current trace category's string ref.
27 #define TRACE_INTERNAL_CATEGORY_REF __trace_category_ref
28
29 // Variable used to contain the array of arguments.
30 #define TRACE_INTERNAL_ARGS __trace_args
31
32 // Number of arguments recorded in |TRACE_INTERNAL_ARGS|.
33 // TODO(PT-67): Rename this, conventions says TRACE_NUM_ARGS should call this.
34 #define TRACE_INTERNAL_NUM_ARGS (sizeof(TRACE_INTERNAL_ARGS) / sizeof(TRACE_INTERNAL_ARGS[0]))
35
36 // BEGIN SECTION OF DEPRECATED MACROS, USED BY EXTERNAL CODE
37 // TODO(PT-67): These will be replaced with the NEW_ versions when all existing
38 // code is cleaned up to not use these.
39
40 // Makes a string literal string ref.
41 #define TRACE_INTERNAL_MAKE_LITERAL_STRING_REF(string_literal_value) \
42 (trace_context_make_registered_string_literal( \
43 TRACE_INTERNAL_CONTEXT, (string_literal_value)))
44
45 // Makes a trace argument.
46 #ifdef __cplusplus
47 #define TRACE_INTERNAL_HOLD_ARG(var_name, idx, name_literal, arg_value) \
48 const auto& arg##idx = (arg_value);
49 #define TRACE_INTERNAL_MAKE_ARG(var_name, idx, name_literal, arg_value) \
50 { .name_ref = {.encoded_value = 0, .inline_string = (name_literal)}, \
51 .value = ::trace::internal::MakeArgumentValue(arg##idx) }
52 #else
53 #define TRACE_INTERNAL_MAKE_ARG(var_name, idx, name_literal, arg_value) \
54 { .name_ref = {.encoded_value = 0, .inline_string = (name_literal)}, \
55 .value = (arg_value) }
56 #endif // __cplusplus
57
58 #ifdef __cplusplus
59 #define TRACE_INTERNAL_DECLARE_ARGS(args...) \
60 TRACE_INTERNAL_APPLY_PAIRWISE(TRACE_INTERNAL_HOLD_ARG, ignore, args) \
61 trace_arg_t TRACE_INTERNAL_ARGS[] = { \
62 TRACE_INTERNAL_APPLY_PAIRWISE_CSV(TRACE_INTERNAL_MAKE_ARG, ignore, args)}; \
63 static_assert(TRACE_INTERNAL_NUM_ARGS <= TRACE_MAX_ARGS, "too many args")
64 #else
65 #define TRACE_INTERNAL_DECLARE_ARGS(args...) \
66 trace_arg_t TRACE_INTERNAL_ARGS[] = { \
67 TRACE_INTERNAL_APPLY_PAIRWISE_CSV(TRACE_INTERNAL_MAKE_ARG, ignore, args)}; \
68 static_assert(TRACE_INTERNAL_NUM_ARGS <= TRACE_MAX_ARGS, "too many args")
69 #endif // __cplusplus
70
71 // END SECTION OF DEPRECATED MACROS, USED BY EXTERNAL CODE
72
73 // Obtains a unique identifier name within the containing scope.
74 #define TRACE_INTERNAL_SCOPE_LABEL() TRACE_INTERNAL_SCOPE_LABEL_(__COUNTER__)
75 #define TRACE_INTERNAL_SCOPE_LABEL_(token) TRACE_INTERNAL_SCOPE_LABEL__(token)
76 #define TRACE_INTERNAL_SCOPE_LABEL__(token) __trace_scope_##token
77
78 // Scaffolding for a trace macro that does not have a category.
79 #ifndef NTRACE
80 #define TRACE_INTERNAL_SIMPLE_RECORD(stmt, args...) \
81 do { \
82 trace_context_t* TRACE_INTERNAL_CONTEXT = \
83 trace_acquire_context(); \
84 if (unlikely(TRACE_INTERNAL_CONTEXT)) { \
85 TRACE_INTERNAL_NEW_DECLARE_ARGS(TRACE_INTERNAL_CONTEXT, \
86 TRACE_INTERNAL_ARGS, \
87 args); \
88 stmt; \
89 } \
90 } while (0)
91 #else
92 #define TRACE_INTERNAL_SIMPLE_RECORD(stmt, args...) \
93 do { \
94 if (0) { \
95 trace_context_t* TRACE_INTERNAL_CONTEXT = 0; \
96 TRACE_INTERNAL_NEW_DECLARE_ARGS(TRACE_INTERNAL_CONTEXT, \
97 TRACE_INTERNAL_ARGS, \
98 args); \
99 stmt; \
100 } \
101 } while (0)
102 #endif // NTRACE
103
104 // Scaffolding for a trace macro that has a category (such as a trace event).
105 #ifndef NTRACE
106 #define TRACE_INTERNAL_EVENT_RECORD(category_literal, stmt, args...) \
107 do { \
108 static trace_site_t TRACE_INTERNAL_SITE_STATE; \
109 trace_string_ref_t TRACE_INTERNAL_CATEGORY_REF; \
110 trace_context_t* TRACE_INTERNAL_CONTEXT = \
111 trace_acquire_context_for_category_cached( \
112 (category_literal), &TRACE_INTERNAL_SITE_STATE, \
113 &TRACE_INTERNAL_CATEGORY_REF); \
114 if (unlikely(TRACE_INTERNAL_CONTEXT)) { \
115 TRACE_INTERNAL_NEW_DECLARE_ARGS(TRACE_INTERNAL_CONTEXT, \
116 TRACE_INTERNAL_ARGS, \
117 args); \
118 stmt; \
119 } \
120 } while (0)
121 #else
122 #define TRACE_INTERNAL_EVENT_RECORD(category_literal, stmt, args...) \
123 do { \
124 if (0) { \
125 trace_string_ref_t TRACE_INTERNAL_CATEGORY_REF; \
126 trace_context_t* TRACE_INTERNAL_CONTEXT = 0; \
127 TRACE_INTERNAL_NEW_DECLARE_ARGS(TRACE_INTERNAL_CONTEXT, \
128 TRACE_INTERNAL_ARGS, \
129 args); \
130 stmt; \
131 } \
132 } while (0)
133 #endif // NTRACE
134
135 #define TRACE_INTERNAL_INSTANT(category_literal, name_literal, scope, args...) \
136 do { \
137 TRACE_INTERNAL_EVENT_RECORD( \
138 (category_literal), \
139 trace_internal_write_instant_event_record_and_release_context( \
140 TRACE_INTERNAL_CONTEXT, \
141 &TRACE_INTERNAL_CATEGORY_REF, \
142 (name_literal), (scope), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
143 args); \
144 } while (0)
145
146 #define TRACE_INTERNAL_COUNTER(category_literal, name_literal, counter_id, args...) \
147 do { \
148 TRACE_INTERNAL_EVENT_RECORD( \
149 (category_literal), \
150 trace_internal_write_counter_event_record_and_release_context( \
151 TRACE_INTERNAL_CONTEXT, \
152 &TRACE_INTERNAL_CATEGORY_REF, \
153 (name_literal), (counter_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
154 args); \
155 } while (0)
156
157 #define TRACE_INTERNAL_DURATION_BEGIN(category_literal, name_literal, args...) \
158 do { \
159 TRACE_INTERNAL_EVENT_RECORD( \
160 (category_literal), \
161 trace_internal_write_duration_begin_event_record_and_release_context( \
162 TRACE_INTERNAL_CONTEXT, \
163 &TRACE_INTERNAL_CATEGORY_REF, \
164 (name_literal), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
165 args); \
166 } while (0)
167
168 #define TRACE_INTERNAL_DURATION_END(category_literal, name_literal, args...) \
169 do { \
170 TRACE_INTERNAL_EVENT_RECORD( \
171 (category_literal), \
172 trace_internal_write_duration_end_event_record_and_release_context( \
173 TRACE_INTERNAL_CONTEXT, \
174 &TRACE_INTERNAL_CATEGORY_REF, \
175 (name_literal), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
176 args); \
177 } while (0)
178
179 #ifndef NTRACE
180 #define TRACE_INTERNAL_DECLARE_DURATION_SCOPE(variable, category_literal, name_literal) \
181 __attribute__((cleanup(trace_internal_cleanup_duration_scope))) \
182 trace_internal_duration_scope_t variable; \
183 trace_internal_make_duration_scope(&variable, (category_literal), (name_literal))
184 #define TRACE_INTERNAL_DURATION_(scope_label, scope_category_literal, scope_name_literal, args...) \
185 TRACE_INTERNAL_DECLARE_DURATION_SCOPE(scope_label, scope_category_literal, scope_name_literal); \
186 TRACE_INTERNAL_DURATION_BEGIN(scope_label.category_literal, scope_label.name_literal, args)
187 #define TRACE_INTERNAL_DURATION(category_literal, name_literal, args...) \
188 TRACE_INTERNAL_DURATION_(TRACE_INTERNAL_SCOPE_LABEL(), (category_literal), (name_literal), args)
189 #else
190 #define TRACE_INTERNAL_DURATION(category_literal, name_literal, args...) \
191 TRACE_INTERNAL_DURATION_BEGIN((category_literal), (name_literal), args)
192 #endif // NTRACE
193
194 #define TRACE_INTERNAL_ASYNC_BEGIN(category_literal, name_literal, async_id, args...) \
195 do { \
196 TRACE_INTERNAL_EVENT_RECORD( \
197 (category_literal), \
198 trace_internal_write_async_begin_event_record_and_release_context( \
199 TRACE_INTERNAL_CONTEXT, \
200 &TRACE_INTERNAL_CATEGORY_REF, \
201 (name_literal), (async_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
202 args); \
203 } while (0)
204
205 #define TRACE_INTERNAL_ASYNC_INSTANT(category_literal, name_literal, async_id, args...) \
206 do { \
207 TRACE_INTERNAL_EVENT_RECORD( \
208 (category_literal), \
209 trace_internal_write_async_instant_event_record_and_release_context( \
210 TRACE_INTERNAL_CONTEXT, \
211 &TRACE_INTERNAL_CATEGORY_REF, \
212 (name_literal), (async_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
213 args); \
214 } while (0)
215
216 #define TRACE_INTERNAL_ASYNC_END(category_literal, name_literal, async_id, args...) \
217 do { \
218 TRACE_INTERNAL_EVENT_RECORD( \
219 (category_literal), \
220 trace_internal_write_async_end_event_record_and_release_context( \
221 TRACE_INTERNAL_CONTEXT, \
222 &TRACE_INTERNAL_CATEGORY_REF, \
223 (name_literal), (async_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
224 args); \
225 } while (0)
226
227 #define TRACE_INTERNAL_FLOW_BEGIN(category_literal, name_literal, flow_id, args...) \
228 do { \
229 TRACE_INTERNAL_EVENT_RECORD( \
230 (category_literal), \
231 trace_internal_write_flow_begin_event_record_and_release_context( \
232 TRACE_INTERNAL_CONTEXT, \
233 &TRACE_INTERNAL_CATEGORY_REF, \
234 (name_literal), (flow_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
235 args); \
236 } while (0)
237
238 #define TRACE_INTERNAL_FLOW_STEP(category_literal, name_literal, flow_id, args...) \
239 do { \
240 TRACE_INTERNAL_EVENT_RECORD( \
241 (category_literal), \
242 trace_internal_write_flow_step_event_record_and_release_context( \
243 TRACE_INTERNAL_CONTEXT, \
244 &TRACE_INTERNAL_CATEGORY_REF, \
245 (name_literal), (flow_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
246 args); \
247 } while (0)
248
249 #define TRACE_INTERNAL_FLOW_END(category_literal, name_literal, flow_id, args...) \
250 do { \
251 TRACE_INTERNAL_EVENT_RECORD( \
252 (category_literal), \
253 trace_internal_write_flow_end_event_record_and_release_context( \
254 TRACE_INTERNAL_CONTEXT, \
255 &TRACE_INTERNAL_CATEGORY_REF, \
256 (name_literal), (flow_id), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
257 args); \
258 } while (0)
259
260 #define TRACE_INTERNAL_KERNEL_OBJECT(handle, args...) \
261 do { \
262 TRACE_INTERNAL_SIMPLE_RECORD( \
263 trace_internal_write_kernel_object_record_for_handle_and_release_context( \
264 TRACE_INTERNAL_CONTEXT, \
265 (handle), TRACE_INTERNAL_ARGS, TRACE_INTERNAL_NUM_ARGS), \
266 args); \
267 } while (0)
268
269 #define TRACE_INTERNAL_BLOB(type, name, blob, blob_size) \
270 do { \
271 trace_context_t* TRACE_INTERNAL_CONTEXT = \
272 trace_acquire_context(); \
273 if (unlikely(TRACE_INTERNAL_CONTEXT)) { \
274 trace_internal_write_blob_record_and_release_context( \
275 TRACE_INTERNAL_CONTEXT, \
276 (type), (name), (blob), (blob_size)); \
277 } \
278 } while (0)
279
280 ///////////////////////////////////////////////////////////////////////////////
281
282 void trace_internal_write_instant_event_record_and_release_context(
283 trace_context_t* context,
284 const trace_string_ref_t* category_ref,
285 const char* name_literal,
286 trace_scope_t scope,
287 trace_arg_t* args, size_t num_args);
288
289 void trace_internal_write_counter_event_record_and_release_context(
290 trace_context_t* context,
291 const trace_string_ref_t* category_ref,
292 const char* name_literal,
293 uint64_t counter_id,
294 trace_arg_t* args, size_t num_args);
295
296 void trace_internal_write_duration_begin_event_record_and_release_context(
297 trace_context_t* context,
298 const trace_string_ref_t* category_ref,
299 const char* name_literal,
300 trace_arg_t* args, size_t num_args);
301
302 void trace_internal_write_duration_end_event_record_and_release_context(
303 trace_context_t* context,
304 const trace_string_ref_t* category_ref,
305 const char* name_literal,
306 trace_arg_t* args, size_t num_args);
307
308 void trace_internal_write_async_begin_event_record_and_release_context(
309 trace_context_t* context,
310 const trace_string_ref_t* category_ref,
311 const char* name_literal,
312 trace_async_id_t async_id,
313 trace_arg_t* args, size_t num_args);
314
315 void trace_internal_write_async_instant_event_record_and_release_context(
316 trace_context_t* context,
317 const trace_string_ref_t* category_ref,
318 const char* name_literal,
319 trace_async_id_t async_id,
320 trace_arg_t* args, size_t num_args);
321
322 void trace_internal_write_async_end_event_record_and_release_context(
323 trace_context_t* context,
324 const trace_string_ref_t* category_ref,
325 const char* name_literal,
326 trace_async_id_t async_id,
327 trace_arg_t* args, size_t num_args);
328
329 void trace_internal_write_flow_begin_event_record_and_release_context(
330 trace_context_t* context,
331 const trace_string_ref_t* category_ref,
332 const char* name_literal,
333 trace_flow_id_t flow_id,
334 trace_arg_t* args, size_t num_args);
335
336 void trace_internal_write_flow_step_event_record_and_release_context(
337 trace_context_t* context,
338 const trace_string_ref_t* category_ref,
339 const char* name_literal,
340 trace_flow_id_t flow_id,
341 trace_arg_t* args, size_t num_args);
342
343 void trace_internal_write_flow_end_event_record_and_release_context(
344 trace_context_t* context,
345 const trace_string_ref_t* category_ref,
346 const char* name_literal,
347 trace_flow_id_t flow_id,
348 trace_arg_t* args, size_t num_args);
349
350 void trace_internal_write_kernel_object_record_for_handle_and_release_context(
351 trace_context_t* context,
352 zx_handle_t handle,
353 trace_arg_t* args, size_t num_args);
354
355 void trace_internal_write_blob_record_and_release_context(
356 trace_context_t* context,
357 trace_blob_type_t type,
358 const char* name_literal,
359 const void* blob, size_t blob_size);
360
361 #ifndef NTRACE
362 // When "destroyed" (by the cleanup attribute), writes a duration end event.
363 typedef struct {
364 const char* category_literal;
365 const char* name_literal;
366 } trace_internal_duration_scope_t;
367
trace_internal_make_duration_scope(trace_internal_duration_scope_t * scope,const char * category_literal,const char * name_literal)368 static inline void trace_internal_make_duration_scope(
369 trace_internal_duration_scope_t* scope,
370 const char* category_literal, const char* name_literal) {
371 scope->category_literal = category_literal;
372 scope->name_literal = name_literal;
373 }
374
trace_internal_cleanup_duration_scope(trace_internal_duration_scope_t * scope)375 static inline void trace_internal_cleanup_duration_scope(
376 trace_internal_duration_scope_t* scope) {
377 TRACE_INTERNAL_DURATION_END(scope->category_literal, scope->name_literal);
378 }
379 #endif // NTRACE
380
381 __END_CDECLS
382
383 #endif // TRACE_INTERNAL_EVENT_INTERNAL_H_
384