1 // Copyright (c) 2012 The Chromium 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 #ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_
6 #define BASE_TRACE_EVENT_TRACE_EVENT_H_
7
8 // This header file defines implementation details of how the trace macros in
9 // trace_event_common.h collect and store trace events. Anything not
10 // implementation-specific should go in trace_event_common.h instead of here.
11
12 #include <stddef.h>
13 #include <stdint.h>
14
15 #include <string>
16
17 #include "base/atomicops.h"
18 #include "base/debug/debugging_buildflags.h"
19 #include "base/macros.h"
20 #include "base/time/time.h"
21 #include "base/time/time_override.h"
22 #include "base/trace_event/builtin_categories.h"
23 #include "base/trace_event/common/trace_event_common.h"
24 #include "base/trace_event/heap_profiler.h"
25 #include "base/trace_event/log_message.h"
26 #include "base/trace_event/thread_instruction_count.h"
27 #include "base/trace_event/trace_arguments.h"
28 #include "base/trace_event/trace_category.h"
29 #include "base/trace_event/trace_log.h"
30 #include "build/build_config.h"
31
32 // By default, const char* argument values are assumed to have long-lived scope
33 // and will not be copied. Use this macro to force a const char* to be copied.
34 #define TRACE_STR_COPY(str) ::base::trace_event::TraceStringWithCopy(str)
35
36 // By default, trace IDs are eventually converted to a single 64-bit number. Use
37 // this macro to add a scope string. For example,
38 //
39 // TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
40 // "network", "ResourceLoad",
41 // TRACE_ID_WITH_SCOPE("BlinkResourceID", resourceID));
42 //
43 // Also, it is possible to prepend the ID with another number, like the process
44 // ID. This is useful in creating IDs that are unique among all processes. To do
45 // that, pass two numbers after the scope string instead of one. For example,
46 //
47 // TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
48 // "network", "ResourceLoad",
49 // TRACE_ID_WITH_SCOPE("BlinkResourceID", pid, resourceID));
50 #define TRACE_ID_WITH_SCOPE(scope, ...) \
51 trace_event_internal::TraceID::WithScope(scope, ##__VA_ARGS__)
52
53 // Use this for ids that are unique across processes. This allows different
54 // processes to use the same id to refer to the same event.
55 #define TRACE_ID_GLOBAL(id) trace_event_internal::TraceID::GlobalId(id)
56
57 // Use this for ids that are unique within a single process. This allows
58 // different processes to use the same id to refer to different events.
59 #define TRACE_ID_LOCAL(id) trace_event_internal::TraceID::LocalId(id)
60
61 #define TRACE_EVENT_API_CURRENT_THREAD_ID \
62 static_cast<int>(base::PlatformThread::CurrentId())
63
64 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
65 UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
66 (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING | \
67 base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT))
68
69 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED() \
70 UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
71 (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING | \
72 base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT | \
73 base::trace_event::TraceCategory::ENABLED_FOR_FILTERING))
74
75 ////////////////////////////////////////////////////////////////////////////////
76 // Implementation specific tracing API definitions.
77
78 // Get a pointer to the enabled state of the given trace category. Only
79 // long-lived literal strings should be given as the category group. The
80 // returned pointer can be held permanently in a local static for example. If
81 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
82 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
83 // between the load of the tracing state and the call to
84 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
85 // for best performance when tracing is disabled.
86 // const unsigned char*
87 // TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
88 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
89 base::trace_event::TraceLog::GetCategoryGroupEnabled
90
91 // Get the number of times traces have been recorded. This is used to implement
92 // the TRACE_EVENT_IS_NEW_TRACE facility.
93 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
94 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
95 trace_event_internal::GetNumTracesRecorded
96
97 // Add a trace event to the platform tracing system.
98 // base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
99 // char phase,
100 // const unsigned char* category_group_enabled,
101 // const char* name,
102 // const char* scope,
103 // unsigned long long id,
104 // base::trace_event::TraceArguments* args,
105 // unsigned int flags)
106 #define TRACE_EVENT_API_ADD_TRACE_EVENT trace_event_internal::AddTraceEvent
107
108 // Add a trace event to the platform tracing system.
109 // base::trace_event::TraceEventHandle
110 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
111 // char phase,
112 // const unsigned char* category_group_enabled,
113 // const char* name,
114 // const char* scope,
115 // unsigned long long id,
116 // unsigned long long bind_id,
117 // base::trace_event::TraceArguments* args,
118 // unsigned int flags)
119 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID \
120 trace_event_internal::AddTraceEventWithBindId
121
122 // Add a trace event to the platform tracing system overriding the pid.
123 // The resulting event will have tid = pid == (process_id passed here).
124 // base::trace_event::TraceEventHandle
125 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
126 // char phase,
127 // const unsigned char* category_group_enabled,
128 // const char* name,
129 // const char* scope,
130 // unsigned long long id,
131 // int process_id,
132 // base::trace_event::TraceArguments* args,
133 // unsigned int flags)
134 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \
135 trace_event_internal::AddTraceEventWithProcessId
136
137 // Add a trace event to the platform tracing system.
138 // base::trace_event::TraceEventHandle
139 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
140 // char phase,
141 // const unsigned char* category_group_enabled,
142 // const char* name,
143 // const char* scope,
144 // unsigned long long id,
145 // int thread_id,
146 // const TimeTicks& timestamp,
147 // base::trace_event::TraceArguments* args,
148 // unsigned int flags)
149 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
150 trace_event_internal::AddTraceEventWithThreadIdAndTimestamp
151
152 // Set the duration field of a COMPLETE trace event.
153 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
154 // const unsigned char* category_group_enabled,
155 // const char* name,
156 // base::trace_event::TraceEventHandle id)
157 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
158 trace_event_internal::UpdateTraceEventDuration
159
160 // Set the duration field of a COMPLETE trace event.
161 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT(
162 // const unsigned char* category_group_enabled,
163 // const char* name,
164 // base::trace_event::TraceEventHandle id,
165 // int thread_id,
166 // bool explicit_timestamps,
167 // const base::TimeTicks& now,
168 // const base::ThreadTicks& thread_now,
169 // base::trace_event::ThreadInstructionCount thread_instruction_now)
170 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT \
171 trace_event_internal::UpdateTraceEventDurationExplicit
172
173 // Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
174 // on the convertable value will be called at flush time.
175 // TRACE_EVENT_API_ADD_METADATA_EVENT(
176 // const unsigned char* category_group_enabled,
177 // const char* event_name,
178 // const char* arg_name,
179 // std::unique_ptr<ConvertableToTraceFormat> arg_value)
180 #define TRACE_EVENT_API_ADD_METADATA_EVENT \
181 trace_event_internal::AddMetadataEvent
182
183 // Defines atomic operations used internally by the tracing system.
184 #define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
185 #define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var))
186 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
187 base::subtle::NoBarrier_Store(&(var), (value))
188
189 // Defines visibility for classes in trace_event.h
190 #define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT
191
192 ////////////////////////////////////////////////////////////////////////////////
193
194 // Implementation detail: trace event macros create temporary variables
195 // to keep instrumentation overhead low. These macros give each temporary
196 // variable a unique name based on the line number to prevent name collisions.
197 #define INTERNAL_TRACE_EVENT_UID3(a,b) \
198 trace_event_unique_##a##b
199 #define INTERNAL_TRACE_EVENT_UID2(a,b) \
200 INTERNAL_TRACE_EVENT_UID3(a,b)
201 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \
202 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
203
204 // Implementation detail: internal macro to create static category.
205 // No barriers are needed, because this code is designed to operate safely
206 // even when the unsigned char* points to garbage data (which may be the case
207 // on processors without cache coherency).
208 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
209 category_group, atomic, category_group_enabled) \
210 category_group_enabled = reinterpret_cast<const unsigned char*>( \
211 TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \
212 if (UNLIKELY(!category_group_enabled)) { \
213 category_group_enabled = \
214 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
215 TRACE_EVENT_API_ATOMIC_STORE( \
216 atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
217 category_group_enabled)); \
218 }
219
220 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_MAYBE_AT_COMPILE_TIME( \
221 category_group, k_category_group_enabled, category_group_enabled) \
222 if (k_category_group_enabled) { \
223 category_group_enabled = k_category_group_enabled; \
224 } else { \
225 static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
226 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
227 category_group, INTERNAL_TRACE_EVENT_UID(atomic), \
228 category_group_enabled); \
229 }
230
231 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
232 static_assert( \
233 base::trace_event::BuiltinCategories::IsAllowedCategory(category_group), \
234 "Unknown tracing category is used. Please register your " \
235 "category in base/trace_event/builtin_categories.h"); \
236 constexpr const unsigned char* INTERNAL_TRACE_EVENT_UID( \
237 k_category_group_enabled) = \
238 base::trace_event::TraceLog::GetBuiltinCategoryEnabled(category_group); \
239 const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
240 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_MAYBE_AT_COMPILE_TIME( \
241 category_group, INTERNAL_TRACE_EVENT_UID(k_category_group_enabled), \
242 INTERNAL_TRACE_EVENT_UID(category_group_enabled));
243
244 // Implementation detail: internal macro to return unoverridden
245 // base::TimeTicks::Now(). This is important because in headless VirtualTime can
246 // override base:TimeTicks::Now().
247 #define INTERNAL_TRACE_TIME_TICKS_NOW() \
248 base::subtle::TimeTicksNowIgnoringOverride()
249
250 // Implementation detail: internal macro to return unoverridden
251 // base::Time::Now(). This is important because in headless VirtualTime can
252 // override base:TimeTicks::Now().
253 #define INTERNAL_TRACE_TIME_NOW() base::subtle::TimeNowIgnoringOverride()
254
255 // Implementation detail: internal macro to create static category and add
256 // event if the category is enabled.
257 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
258 do { \
259 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
260 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
261 trace_event_internal::AddTraceEvent( \
262 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
263 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
264 flags, trace_event_internal::kNoId, ##__VA_ARGS__); \
265 } \
266 } while (0)
267
268 // Implementation detail: internal macro to create static category and add begin
269 // event if the category is enabled. Also adds the end event when the scope
270 // ends.
271 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
272 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
273 trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
274 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
275 base::trace_event::TraceEventHandle h = \
276 trace_event_internal::AddTraceEvent( \
277 TRACE_EVENT_PHASE_COMPLETE, \
278 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
279 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
280 TRACE_EVENT_FLAG_NONE, trace_event_internal::kNoId, \
281 ##__VA_ARGS__); \
282 INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
283 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
284 }
285
286 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLAGS(category_group, name, \
287 flags, ...) \
288 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
289 trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
290 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
291 base::trace_event::TraceEventHandle h = \
292 trace_event_internal::AddTraceEvent( \
293 TRACE_EVENT_PHASE_COMPLETE, \
294 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
295 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
296 flags, trace_event_internal::kNoId, ##__VA_ARGS__); \
297 INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
298 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
299 }
300
301 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \
302 bind_id, flow_flags, ...) \
303 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
304 trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
305 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
306 trace_event_internal::TraceID trace_event_bind_id((bind_id)); \
307 unsigned int trace_event_flags = \
308 flow_flags | trace_event_bind_id.id_flags(); \
309 base::trace_event::TraceEventHandle h = \
310 trace_event_internal::AddTraceEvent( \
311 TRACE_EVENT_PHASE_COMPLETE, \
312 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
313 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
314 trace_event_flags, trace_event_bind_id.raw_id(), ##__VA_ARGS__); \
315 INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
316 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
317 }
318
319 // Implementation detail: internal macro to create static category and add
320 // event if the category is enabled.
321 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
322 flags, ...) \
323 do { \
324 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
325 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
326 trace_event_internal::TraceID trace_event_trace_id((id)); \
327 unsigned int trace_event_flags = \
328 flags | trace_event_trace_id.id_flags(); \
329 trace_event_internal::AddTraceEvent( \
330 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
331 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
332 trace_event_flags, trace_event_internal::kNoId, ##__VA_ARGS__); \
333 } \
334 } while (0)
335
336 // Implementation detail: internal macro to create static category and add
337 // event if the category is enabled.
338 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
339 timestamp, flags, ...) \
340 do { \
341 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
342 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
343 trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \
344 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
345 trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
346 TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, \
347 flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \
348 trace_event_internal::kNoId, ##__VA_ARGS__); \
349 } \
350 } while (0)
351
352 // Implementation detail: internal macro to create static category and add
353 // event if the category is enabled.
354 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
355 phase, category_group, name, id, thread_id, timestamp, flags, ...) \
356 do { \
357 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
358 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
359 trace_event_internal::TraceID trace_event_trace_id((id)); \
360 unsigned int trace_event_flags = \
361 flags | trace_event_trace_id.id_flags(); \
362 trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \
363 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
364 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
365 thread_id, timestamp, \
366 trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \
367 trace_event_internal::kNoId, ##__VA_ARGS__); \
368 } \
369 } while (0)
370
371 // Implementation detail: internal macro to create static category and add
372 // event if the category is enabled.
373 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS( \
374 category_group, name, id, thread_id, begin_timestamp, end_timestamp, \
375 thread_end_timestamp, flags, ...) \
376 do { \
377 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
378 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
379 trace_event_internal::TraceID trace_event_trace_id((id)); \
380 unsigned int trace_event_flags = \
381 flags | trace_event_trace_id.id_flags(); \
382 const unsigned char* uid_category_group_enabled = \
383 INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
384 auto handle = \
385 trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \
386 TRACE_EVENT_PHASE_COMPLETE, uid_category_group_enabled, name, \
387 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
388 thread_id, begin_timestamp, \
389 trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP, \
390 trace_event_internal::kNoId, ##__VA_ARGS__); \
391 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION_EXPLICIT( \
392 uid_category_group_enabled, name, handle, thread_id, \
393 /*explicit_timestamps=*/true, end_timestamp, thread_end_timestamp, \
394 base::trace_event::ThreadInstructionCount()); \
395 } \
396 } while (0)
397
398 // Implementation detail: internal macro to create static category and add
399 // metadata event if the category is enabled.
400 #define INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, ...) \
401 do { \
402 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
403 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
404 TRACE_EVENT_API_ADD_METADATA_EVENT( \
405 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
406 ##__VA_ARGS__); \
407 } \
408 } while (0)
409
410 #define INTERNAL_TRACE_LOG_MESSAGE(file, message, line) \
411 TRACE_EVENT_INSTANT1( \
412 "log", "LogMessage", \
413 TRACE_EVENT_FLAG_TYPED_PROTO_ARGS | TRACE_EVENT_SCOPE_THREAD, "message", \
414 std::make_unique<base::trace_event::LogMessage>(file, message, line))
415
416 #if BUILDFLAG(ENABLE_LOCATION_SOURCE)
417
418 // Implementation detail: internal macro to trace a task execution with the
419 // location where it was posted from.
420 //
421 // This implementation is for when location sources are available.
422 // TODO(ssid): The program counter of the current task should be added here.
423 #define INTERNAL_TRACE_TASK_EXECUTION(run_function, task) \
424 INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLAGS( \
425 "toplevel", run_function, TRACE_EVENT_FLAG_TYPED_PROTO_ARGS, "src_file", \
426 (task).posted_from.file_name(), "src_func", \
427 (task).posted_from.function_name()); \
428 TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID( \
429 task_event)((task).posted_from.file_name()); \
430 TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \
431 INTERNAL_TRACE_EVENT_UID(task_pc_event)((task).posted_from.program_counter());
432
433 #else
434
435 // TODO(http://crbug.com760702) remove file name and just pass the program
436 // counter to the heap profiler macro.
437 // TODO(ssid): The program counter of the current task should be added here.
438 #define INTERNAL_TRACE_TASK_EXECUTION(run_function, task) \
439 INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLAGS( \
440 "toplevel", run_function, TRACE_EVENT_FLAG_TYPED_PROTO_ARGS, "src", \
441 (task).posted_from.ToString()) \
442 TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID( \
443 task_event)((task).posted_from.file_name()); \
444 TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \
445 INTERNAL_TRACE_EVENT_UID(task_pc_event)((task).posted_from.program_counter());
446
447 #endif
448
449 namespace trace_event_internal {
450
451 // Specify these values when the corresponding argument of AddTraceEvent is not
452 // used.
453 const int kZeroNumArgs = 0;
454 const std::nullptr_t kGlobalScope = nullptr;
455 const unsigned long long kNoId = 0;
456
457 // TraceID encapsulates an ID that can either be an integer or pointer.
458 class BASE_EXPORT TraceID {
459 public:
460 // Can be combined with WithScope.
461 class LocalId {
462 public:
LocalId(const void * raw_id)463 explicit LocalId(const void* raw_id)
464 : raw_id_(static_cast<unsigned long long>(
465 reinterpret_cast<uintptr_t>(raw_id))) {}
LocalId(unsigned long long raw_id)466 explicit LocalId(unsigned long long raw_id) : raw_id_(raw_id) {}
raw_id()467 unsigned long long raw_id() const { return raw_id_; }
468 private:
469 unsigned long long raw_id_;
470 };
471
472 // Can be combined with WithScope.
473 class GlobalId {
474 public:
GlobalId(unsigned long long raw_id)475 explicit GlobalId(unsigned long long raw_id) : raw_id_(raw_id) {}
raw_id()476 unsigned long long raw_id() const { return raw_id_; }
477 private:
478 unsigned long long raw_id_;
479 };
480
481 class WithScope {
482 public:
WithScope(const char * scope,unsigned long long raw_id)483 WithScope(const char* scope, unsigned long long raw_id)
484 : scope_(scope), raw_id_(raw_id) {}
WithScope(const char * scope,LocalId local_id)485 WithScope(const char* scope, LocalId local_id)
486 : scope_(scope), raw_id_(local_id.raw_id()) {
487 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
488 }
WithScope(const char * scope,GlobalId global_id)489 WithScope(const char* scope, GlobalId global_id)
490 : scope_(scope), raw_id_(global_id.raw_id()) {
491 id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
492 }
raw_id()493 unsigned long long raw_id() const { return raw_id_; }
scope()494 const char* scope() const { return scope_; }
id_flags()495 unsigned int id_flags() const { return id_flags_; }
496
497 private:
498 const char* scope_ = nullptr;
499 unsigned long long raw_id_;
500 unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
501 };
502
TraceID(const void * raw_id)503 TraceID(const void* raw_id) : raw_id_(static_cast<unsigned long long>(
504 reinterpret_cast<uintptr_t>(raw_id))) {
505 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
506 }
TraceID(unsigned long long raw_id)507 TraceID(unsigned long long raw_id) : raw_id_(raw_id) {}
TraceID(unsigned long raw_id)508 TraceID(unsigned long raw_id) : raw_id_(raw_id) {}
TraceID(unsigned int raw_id)509 TraceID(unsigned int raw_id) : raw_id_(raw_id) {}
TraceID(unsigned short raw_id)510 TraceID(unsigned short raw_id) : raw_id_(raw_id) {}
TraceID(unsigned char raw_id)511 TraceID(unsigned char raw_id) : raw_id_(raw_id) {}
TraceID(long long raw_id)512 TraceID(long long raw_id)
513 : raw_id_(static_cast<unsigned long long>(raw_id)) {}
TraceID(long raw_id)514 TraceID(long raw_id)
515 : raw_id_(static_cast<unsigned long long>(raw_id)) {}
TraceID(int raw_id)516 TraceID(int raw_id)
517 : raw_id_(static_cast<unsigned long long>(raw_id)) {}
TraceID(short raw_id)518 TraceID(short raw_id)
519 : raw_id_(static_cast<unsigned long long>(raw_id)) {}
TraceID(signed char raw_id)520 TraceID(signed char raw_id)
521 : raw_id_(static_cast<unsigned long long>(raw_id)) {}
TraceID(LocalId raw_id)522 TraceID(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
523 id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
524 }
TraceID(GlobalId raw_id)525 TraceID(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
526 id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
527 }
TraceID(WithScope scoped_id)528 TraceID(WithScope scoped_id)
529 : scope_(scoped_id.scope()),
530 raw_id_(scoped_id.raw_id()),
531 id_flags_(scoped_id.id_flags()) {}
532
raw_id()533 unsigned long long raw_id() const { return raw_id_; }
scope()534 const char* scope() const { return scope_; }
id_flags()535 unsigned int id_flags() const { return id_flags_; }
536
537 private:
538 const char* scope_ = nullptr;
539 unsigned long long raw_id_;
540 unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
541 };
542
543 // These functions all internally call
544 // base::trace_event::TraceLog::GetInstance() then call the method with the same
545 // name on it. This is used to reduce the generated machine code at each
546 // TRACE_EVENTXXX macro call.
547
548 base::trace_event::TraceEventHandle BASE_EXPORT
549 AddTraceEvent(char phase,
550 const unsigned char* category_group_enabled,
551 const char* name,
552 const char* scope,
553 unsigned long long id,
554 base::trace_event::TraceArguments* args,
555 unsigned int flags);
556
557 base::trace_event::TraceEventHandle BASE_EXPORT
558 AddTraceEventWithBindId(char phase,
559 const unsigned char* category_group_enabled,
560 const char* name,
561 const char* scope,
562 unsigned long long id,
563 unsigned long long bind_id,
564 base::trace_event::TraceArguments* args,
565 unsigned int flags);
566
567 base::trace_event::TraceEventHandle BASE_EXPORT
568 AddTraceEventWithProcessId(char phase,
569 const unsigned char* category_group_enabled,
570 const char* name,
571 const char* scope,
572 unsigned long long id,
573 int process_id,
574 base::trace_event::TraceArguments* args,
575 unsigned int flags);
576
577 base::trace_event::TraceEventHandle BASE_EXPORT
578 AddTraceEventWithThreadIdAndTimestamp(
579 char phase,
580 const unsigned char* category_group_enabled,
581 const char* name,
582 const char* scope,
583 unsigned long long id,
584 int thread_id,
585 const base::TimeTicks& timestamp,
586 base::trace_event::TraceArguments* args,
587 unsigned int flags);
588
589 base::trace_event::TraceEventHandle BASE_EXPORT
590 AddTraceEventWithThreadIdAndTimestamp(
591 char phase,
592 const unsigned char* category_group_enabled,
593 const char* name,
594 const char* scope,
595 unsigned long long id,
596 unsigned long long bind_id,
597 int thread_id,
598 const base::TimeTicks& timestamp,
599 base::trace_event::TraceArguments* args,
600 unsigned int flags);
601
602 void BASE_EXPORT AddMetadataEvent(const unsigned char* category_group_enabled,
603 const char* name,
604 base::trace_event::TraceArguments* args,
605 unsigned int flags);
606
607 int BASE_EXPORT GetNumTracesRecorded();
608
609 void BASE_EXPORT
610 UpdateTraceEventDuration(const unsigned char* category_group_enabled,
611 const char* name,
612 base::trace_event::TraceEventHandle handle);
613
614 void BASE_EXPORT UpdateTraceEventDurationExplicit(
615 const unsigned char* category_group_enabled,
616 const char* name,
617 base::trace_event::TraceEventHandle handle,
618 int thread_id,
619 bool explicit_timestamps,
620 const base::TimeTicks& now,
621 const base::ThreadTicks& thread_now,
622 base::trace_event::ThreadInstructionCount thread_instruction_now);
623
624 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
625 // functions are defined here instead of in the macro, because the arg_values
626 // could be temporary objects, such as std::string. In order to store
627 // pointers to the internal c_str and pass through to the tracing API,
628 // the arg_values must live throughout these procedures.
629
630 template <class ARG1_TYPE>
631 static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,int thread_id,const base::TimeTicks & timestamp,unsigned int flags,unsigned long long bind_id,const char * arg1_name,ARG1_TYPE && arg1_val)632 AddTraceEventWithThreadIdAndTimestamp(
633 char phase,
634 const unsigned char* category_group_enabled,
635 const char* name,
636 const char* scope,
637 unsigned long long id,
638 int thread_id,
639 const base::TimeTicks& timestamp,
640 unsigned int flags,
641 unsigned long long bind_id,
642 const char* arg1_name,
643 ARG1_TYPE&& arg1_val) {
644 base::trace_event::TraceArguments args(arg1_name,
645 std::forward<ARG1_TYPE>(arg1_val));
646 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
647 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
648 timestamp, &args, flags);
649 }
650
651 template <class ARG1_TYPE, class ARG2_TYPE>
652 static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,int thread_id,const base::TimeTicks & timestamp,unsigned int flags,unsigned long long bind_id,const char * arg1_name,ARG1_TYPE && arg1_val,const char * arg2_name,ARG2_TYPE && arg2_val)653 AddTraceEventWithThreadIdAndTimestamp(
654 char phase,
655 const unsigned char* category_group_enabled,
656 const char* name,
657 const char* scope,
658 unsigned long long id,
659 int thread_id,
660 const base::TimeTicks& timestamp,
661 unsigned int flags,
662 unsigned long long bind_id,
663 const char* arg1_name,
664 ARG1_TYPE&& arg1_val,
665 const char* arg2_name,
666 ARG2_TYPE&& arg2_val) {
667 base::trace_event::TraceArguments args(
668 arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
669 std::forward<ARG2_TYPE>(arg2_val));
670 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
671 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
672 timestamp, &args, flags);
673 }
674
675 static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,int thread_id,const base::TimeTicks & timestamp,unsigned int flags,unsigned long long bind_id)676 AddTraceEventWithThreadIdAndTimestamp(
677 char phase,
678 const unsigned char* category_group_enabled,
679 const char* name,
680 const char* scope,
681 unsigned long long id,
682 int thread_id,
683 const base::TimeTicks& timestamp,
684 unsigned int flags,
685 unsigned long long bind_id) {
686 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
687 phase, category_group_enabled, name, scope, id, bind_id, thread_id,
688 timestamp, nullptr, flags);
689 }
690
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,unsigned int flags,unsigned long long bind_id)691 static inline base::trace_event::TraceEventHandle AddTraceEvent(
692 char phase,
693 const unsigned char* category_group_enabled,
694 const char* name,
695 const char* scope,
696 unsigned long long id,
697 unsigned int flags,
698 unsigned long long bind_id) {
699 const int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
700 const base::TimeTicks now = TRACE_TIME_TICKS_NOW();
701 return AddTraceEventWithThreadIdAndTimestamp(
702 phase, category_group_enabled, name, scope, id, thread_id, now, flags,
703 bind_id);
704 }
705
706 template <class ARG1_TYPE>
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,unsigned int flags,unsigned long long bind_id,const char * arg1_name,ARG1_TYPE && arg1_val)707 static inline base::trace_event::TraceEventHandle AddTraceEvent(
708 char phase,
709 const unsigned char* category_group_enabled,
710 const char* name,
711 const char* scope,
712 unsigned long long id,
713 unsigned int flags,
714 unsigned long long bind_id,
715 const char* arg1_name,
716 ARG1_TYPE&& arg1_val) {
717 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
718 base::TimeTicks now = TRACE_TIME_TICKS_NOW();
719 return AddTraceEventWithThreadIdAndTimestamp(
720 phase, category_group_enabled, name, scope, id, thread_id, now, flags,
721 bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val));
722 }
723
724 template <class ARG1_TYPE, class ARG2_TYPE>
AddTraceEvent(char phase,const unsigned char * category_group_enabled,const char * name,const char * scope,unsigned long long id,unsigned int flags,unsigned long long bind_id,const char * arg1_name,ARG1_TYPE && arg1_val,const char * arg2_name,ARG2_TYPE && arg2_val)725 static inline base::trace_event::TraceEventHandle AddTraceEvent(
726 char phase,
727 const unsigned char* category_group_enabled,
728 const char* name,
729 const char* scope,
730 unsigned long long id,
731 unsigned int flags,
732 unsigned long long bind_id,
733 const char* arg1_name,
734 ARG1_TYPE&& arg1_val,
735 const char* arg2_name,
736 ARG2_TYPE&& arg2_val) {
737 int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
738 base::TimeTicks now = TRACE_TIME_TICKS_NOW();
739 return AddTraceEventWithThreadIdAndTimestamp(
740 phase, category_group_enabled, name, scope, id, thread_id, now, flags,
741 bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name,
742 std::forward<ARG2_TYPE>(arg2_val));
743 }
744
745 template <class ARG1_TYPE>
AddMetadataEvent(const unsigned char * category_group_enabled,const char * event_name,const char * arg_name,ARG1_TYPE && arg_val)746 static void AddMetadataEvent(const unsigned char* category_group_enabled,
747 const char* event_name,
748 const char* arg_name,
749 ARG1_TYPE&& arg_val) {
750 base::trace_event::TraceArguments args(arg_name,
751 std::forward<ARG1_TYPE>(arg_val));
752 trace_event_internal::AddMetadataEvent(category_group_enabled, event_name,
753 &args, TRACE_EVENT_FLAG_NONE);
754 }
755
756 // Used by TRACE_EVENTx macros. Do not use directly.
757 class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer {
758 public:
759 ScopedTracer() = default;
760
~ScopedTracer()761 ~ScopedTracer() {
762 if (category_group_enabled_ && *category_group_enabled_) {
763 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_,
764 name_, event_handle_);
765 }
766 }
767
Initialize(const unsigned char * category_group_enabled,const char * name,base::trace_event::TraceEventHandle event_handle)768 void Initialize(const unsigned char* category_group_enabled,
769 const char* name,
770 base::trace_event::TraceEventHandle event_handle) {
771 category_group_enabled_ = category_group_enabled;
772 name_ = name;
773 event_handle_ = event_handle;
774 }
775
776 private:
777 // NOTE: Only initialize the first member to reduce generated code size,
778 // since there is no point in initializing the other members if Initialize()
779 // is never called.
780 const unsigned char* category_group_enabled_ = nullptr;
781 const char* name_;
782 base::trace_event::TraceEventHandle event_handle_;
783 };
784
785 // Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly.
786 class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient {
787 public:
788 ScopedTraceBinaryEfficient(const char* category_group, const char* name);
789 ~ScopedTraceBinaryEfficient();
790
791 private:
792 const unsigned char* category_group_enabled_;
793 const char* name_;
794 base::trace_event::TraceEventHandle event_handle_;
795 };
796
797 // This macro generates less code then TRACE_EVENT0 but is also
798 // slower to execute when tracing is off. It should generally only be
799 // used with code that is seldom executed or conditionally executed
800 // when debugging.
801 // For now the category_group must be "gpu".
802 #define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \
803 trace_event_internal::ScopedTraceBinaryEfficient \
804 INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name);
805
806 } // namespace trace_event_internal
807
808 namespace base {
809 namespace trace_event {
810
811 template <typename IDType, const char* category>
812 class TraceScopedTrackableObject {
813 public:
TraceScopedTrackableObject(const char * name,IDType id)814 TraceScopedTrackableObject(const char* name, IDType id)
815 : name_(name), id_(id) {
816 TRACE_EVENT_OBJECT_CREATED_WITH_ID(category, name_, id_);
817 }
818
snapshot(ArgType snapshot)819 template <typename ArgType> void snapshot(ArgType snapshot) {
820 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category, name_, id_, snapshot);
821 }
822
~TraceScopedTrackableObject()823 ~TraceScopedTrackableObject() {
824 TRACE_EVENT_OBJECT_DELETED_WITH_ID(category, name_, id_);
825 }
826
827 private:
828 const char* name_;
829 IDType id_;
830
831 DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject);
832 };
833
834 } // namespace trace_event
835 } // namespace base
836
837 #endif // BASE_TRACE_EVENT_TRACE_EVENT_H_
838