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