diff options
-rw-r--r-- | base/BUILD.gn | 38 | ||||
-rw-r--r-- | base/base.gyp | 12 | ||||
-rw-r--r-- | base/base.gypi | 25 | ||||
-rw-r--r-- | base/debug/trace_event.h | 1585 | ||||
-rw-r--r-- | base/debug/trace_event_argument.h | 57 | ||||
-rw-r--r-- | base/debug/trace_event_impl.h | 809 | ||||
-rw-r--r-- | base/debug/trace_event_synthetic_delay.h | 162 | ||||
-rw-r--r-- | base/debug/trace_event_win.h | 121 | ||||
-rw-r--r-- | base/trace_event/OWNERS | 3 | ||||
-rw-r--r-- | base/trace_event/trace_event.h | 1589 | ||||
-rw-r--r-- | base/trace_event/trace_event_android.cc (renamed from base/debug/trace_event_android.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_argument.cc (renamed from base/debug/trace_event_argument.cc) | 2 | ||||
-rw-r--r-- | base/trace_event/trace_event_argument.h | 59 | ||||
-rw-r--r-- | base/trace_event/trace_event_argument_unittest.cc (renamed from base/debug/trace_event_argument_unittest.cc) | 2 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl.cc (renamed from base/debug/trace_event_impl.cc) | 8 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl.h | 813 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl_constants.cc (renamed from base/debug/trace_event_impl_constants.cc) | 2 | ||||
-rw-r--r-- | base/trace_event/trace_event_memory.cc (renamed from base/debug/trace_event_memory.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_memory.h (renamed from base/debug/trace_event_memory.h) | 8 | ||||
-rw-r--r-- | base/trace_event/trace_event_memory_unittest.cc (renamed from base/debug/trace_event_memory_unittest.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_synthetic_delay.cc (renamed from base/debug/trace_event_synthetic_delay.cc) | 2 | ||||
-rw-r--r-- | base/trace_event/trace_event_synthetic_delay.h | 166 | ||||
-rw-r--r-- | base/trace_event/trace_event_synthetic_delay_unittest.cc (renamed from base/debug/trace_event_synthetic_delay_unittest.cc) | 2 | ||||
-rw-r--r-- | base/trace_event/trace_event_system_stats_monitor.cc (renamed from base/debug/trace_event_system_stats_monitor.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_system_stats_monitor.h (renamed from base/debug/trace_event_system_stats_monitor.h) | 8 | ||||
-rw-r--r-- | base/trace_event/trace_event_system_stats_monitor_unittest.cc (renamed from base/debug/trace_event_system_stats_monitor_unittest.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_unittest.cc (renamed from base/debug/trace_event_unittest.cc) | 4 | ||||
-rw-r--r-- | base/trace_event/trace_event_win.cc (renamed from base/debug/trace_event_win.cc) | 3 | ||||
-rw-r--r-- | base/trace_event/trace_event_win.h | 125 | ||||
-rw-r--r-- | base/trace_event/trace_event_win_unittest.cc (renamed from base/debug/trace_event_win_unittest.cc) | 6 | ||||
-rwxr-xr-x | tools/gn/bootstrap/bootstrap.py | 8 |
31 files changed, 2863 insertions, 2776 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn index 616e404..b31fed1 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -169,19 +169,10 @@ component("base") { "debug/task_annotator.cc", "debug/task_annotator.h", "debug/trace_event.h", - "debug/trace_event_android.cc", - "debug/trace_event_argument.cc", "debug/trace_event_argument.h", - "debug/trace_event_impl.cc", "debug/trace_event_impl.h", - "debug/trace_event_impl_constants.cc", - "debug/trace_event_memory.cc", - "debug/trace_event_memory.h", - "debug/trace_event_synthetic_delay.cc", "debug/trace_event_synthetic_delay.h", - "debug/trace_event_system_stats_monitor.cc", - "debug/trace_event_system_stats_monitor.h", - "debug/trace_event_win.cc", + "debug/trace_event_win.h", "deferred_sequenced_task_runner.cc", "deferred_sequenced_task_runner.h", "environment.cc", @@ -687,6 +678,21 @@ component("base") { "timer/mock_timer.h", "timer/timer.cc", "timer/timer.h", + "trace_event/trace_event.h", + "trace_event/trace_event_android.cc", + "trace_event/trace_event_argument.cc", + "trace_event/trace_event_argument.h", + "trace_event/trace_event_impl.cc", + "trace_event/trace_event_impl.h", + "trace_event/trace_event_impl_constants.cc", + "trace_event/trace_event_memory.cc", + "trace_event/trace_event_memory.h", + "trace_event/trace_event_synthetic_delay.cc", + "trace_event/trace_event_synthetic_delay.h", + "trace_event/trace_event_system_stats_monitor.cc", + "trace_event/trace_event_system_stats_monitor.h", + "trace_event/trace_event_win.cc", + "trace_event/trace_event_win.h", "tracked_objects.cc", "tracked_objects.h", "tracking_info.cc", @@ -1167,12 +1173,6 @@ test("base_unittests") { "debug/proc_maps_linux_unittest.cc", "debug/stack_trace_unittest.cc", "debug/task_annotator_unittest.cc", - "debug/trace_event_argument_unittest.cc", - "debug/trace_event_memory_unittest.cc", - "debug/trace_event_synthetic_delay_unittest.cc", - "debug/trace_event_system_stats_monitor_unittest.cc", - "debug/trace_event_unittest.cc", - "debug/trace_event_win_unittest.cc", "deferred_sequenced_task_runner_unittest.cc", "environment_unittest.cc", "file_version_info_unittest.cc", @@ -1334,6 +1334,12 @@ test("base_unittests") { "timer/mock_timer_unittest.cc", "timer/timer_unittest.cc", "tools_sanity_unittest.cc", + "trace_event/trace_event_argument_unittest.cc", + "trace_event/trace_event_memory_unittest.cc", + "trace_event/trace_event_synthetic_delay_unittest.cc", + "trace_event/trace_event_system_stats_monitor_unittest.cc", + "trace_event/trace_event_unittest.cc", + "trace_event/trace_event_win_unittest.cc", "tracked_objects_unittest.cc", "tuple_unittest.cc", "values_unittest.cc", diff --git a/base/base.gyp b/base/base.gyp index c5b28c4..7565646 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -482,12 +482,6 @@ 'debug/proc_maps_linux_unittest.cc', 'debug/stack_trace_unittest.cc', 'debug/task_annotator_unittest.cc', - 'debug/trace_event_argument_unittest.cc', - 'debug/trace_event_memory_unittest.cc', - 'debug/trace_event_synthetic_delay_unittest.cc', - 'debug/trace_event_system_stats_monitor_unittest.cc', - 'debug/trace_event_unittest.cc', - 'debug/trace_event_win_unittest.cc', 'deferred_sequenced_task_runner_unittest.cc', 'environment_unittest.cc', 'file_version_info_unittest.cc', @@ -652,6 +646,12 @@ 'timer/mock_timer_unittest.cc', 'timer/timer_unittest.cc', 'tools_sanity_unittest.cc', + 'trace_event/trace_event_argument_unittest.cc', + 'trace_event/trace_event_memory_unittest.cc', + 'trace_event/trace_event_synthetic_delay_unittest.cc', + 'trace_event/trace_event_system_stats_monitor_unittest.cc', + 'trace_event/trace_event_unittest.cc', + 'trace_event/trace_event_win_unittest.cc', 'tracked_objects_unittest.cc', 'tuple_unittest.cc', 'values_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 1d19597..6cc177c 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -171,18 +171,10 @@ 'debug/task_annotator.cc', 'debug/task_annotator.h', 'debug/trace_event.h', - 'debug/trace_event_android.cc', - 'debug/trace_event_argument.cc', 'debug/trace_event_argument.h', - 'debug/trace_event_impl.cc', 'debug/trace_event_impl.h', - 'debug/trace_event_impl_constants.cc', - 'debug/trace_event_synthetic_delay.cc', 'debug/trace_event_synthetic_delay.h', - 'debug/trace_event_system_stats_monitor.cc', - 'debug/trace_event_memory.cc', - 'debug/trace_event_memory.h', - 'debug/trace_event_win.cc', + 'debug/trace_event_win.h', 'deferred_sequenced_task_runner.cc', 'deferred_sequenced_task_runner.h', 'environment.cc', @@ -680,6 +672,21 @@ 'timer/mock_timer.h', 'timer/timer.cc', 'timer/timer.h', + 'trace_event/trace_event.h', + 'trace_event/trace_event_android.cc', + 'trace_event/trace_event_argument.cc', + 'trace_event/trace_event_argument.h', + 'trace_event/trace_event_impl.cc', + 'trace_event/trace_event_impl.h', + 'trace_event/trace_event_impl_constants.cc', + 'trace_event/trace_event_memory.cc', + 'trace_event/trace_event_memory.h', + 'trace_event/trace_event_synthetic_delay.cc', + 'trace_event/trace_event_synthetic_delay.h', + 'trace_event/trace_event_system_stats_monitor.cc', + 'trace_event/trace_event_system_stats_monitor.h', + 'trace_event/trace_event_win.cc', + 'trace_event/trace_event_win.h', 'tracked_objects.cc', 'tracked_objects.h', 'tracking_info.cc', diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h index 9754036..7d97e16 100644 --- a/base/debug/trace_event.h +++ b/base/debug/trace_event.h @@ -2,1588 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This header file defines the set of trace_event macros without specifying -// how the events actually get collected and stored. If you need to expose trace -// events to some other universe, you can copy-and-paste this file as well as -// trace_event.h, modifying the macros contained there as necessary for the -// target platform. The end result is that multiple libraries can funnel events -// through to a shared trace event collector. - -// Trace events are for tracking application performance and resource usage. -// Macros are provided to track: -// Begin and end of function calls -// Counters -// -// Events are issued against categories. Whereas LOG's -// categories are statically defined, TRACE categories are created -// implicitly with a string. For example: -// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent", -// TRACE_EVENT_SCOPE_THREAD) -// -// It is often the case that one trace may belong in multiple categories at the -// same time. The first argument to the trace can be a comma-separated list of -// categories, forming a category group, like: -// -// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD) -// -// We can enable/disable tracing of OnMouseOver by enabling/disabling either -// category. -// -// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: -// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") -// doSomethingCostly() -// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") -// Note: our tools can't always determine the correct BEGIN/END pairs unless -// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you -// need them to be in separate scopes. -// -// A common use case is to trace entire function scopes. This -// issues a trace BEGIN and END automatically: -// void doSomethingCostly() { -// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); -// ... -// } -// -// Additional parameters can be associated with an event: -// void doSomethingCostly2(int howMuch) { -// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", -// "howMuch", howMuch); -// ... -// } -// -// The trace system will automatically add to this information the -// current process id, thread id, and a timestamp in microseconds. -// -// To trace an asynchronous procedure such as an IPC send/receive, use -// ASYNC_BEGIN and ASYNC_END: -// [single threaded sender code] -// static int send_count = 0; -// ++send_count; -// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); -// Send(new MyMessage(send_count)); -// [receive code] -// void OnMyMessage(send_count) { -// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); -// } -// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. -// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. -// Pointers can be used for the ID parameter, and they will be mangled -// internally so that the same pointer on two different processes will not -// match. For example: -// class MyTracedClass { -// public: -// MyTracedClass() { -// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); -// } -// ~MyTracedClass() { -// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); -// } -// } -// -// Trace event also supports counters, which is a way to track a quantity -// as it varies over time. Counters are created with the following macro: -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); -// -// Counters are process-specific. The macro itself can be issued from any -// thread, however. -// -// Sometimes, you want to track two counters at once. You can do this with two -// counter macros: -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); -// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); -// Or you can do it with a combined macro: -// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", -// "bytesPinned", g_myCounterValue[0], -// "bytesAllocated", g_myCounterValue[1]); -// This indicates to the tracing UI that these counters should be displayed -// in a single graph, as a summed area chart. -// -// Since counters are in a global namespace, you may want to disambiguate with a -// unique ID, by using the TRACE_COUNTER_ID* variations. -// -// By default, trace collection is compiled in, but turned off at runtime. -// Collecting trace data is the responsibility of the embedding -// application. In Chrome's case, navigating to about:tracing will turn on -// tracing and display data collected across all active processes. -// -// -// Memory scoping note: -// Tracing copies the pointers, not the string content, of the strings passed -// in for category_group, name, and arg_names. Thus, the following code will -// cause problems: -// char* str = strdup("importantName"); -// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! -// free(str); // Trace system now has dangling pointer -// -// To avoid this issue with the |name| and |arg_name| parameters, use the -// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. -// Notes: The category must always be in a long-lived char* (i.e. static const). -// The |arg_values|, when used, are always deep copied with the _COPY -// macros. -// -// When are string argument values copied: -// const char* arg_values are only referenced by default: -// TRACE_EVENT1("category", "name", -// "arg1", "literal string is only referenced"); -// Use TRACE_STR_COPY to force copying of a const char*: -// TRACE_EVENT1("category", "name", -// "arg1", TRACE_STR_COPY("string will be copied")); -// std::string arg_values are always copied: -// TRACE_EVENT1("category", "name", -// "arg1", std::string("string will be copied")); -// -// -// Convertable notes: -// Converting a large data type to a string can be costly. To help with this, -// the trace framework provides an interface ConvertableToTraceFormat. If you -// inherit from it and implement the AppendAsTraceFormat method the trace -// framework will call back to your object to convert a trace output time. This -// means, if the category for the event is disabled, the conversion will not -// happen. -// -// class MyData : public base::debug::ConvertableToTraceFormat { -// public: -// MyData() {} -// virtual void AppendAsTraceFormat(std::string* out) const override { -// out->append("{\"foo\":1}"); -// } -// private: -// virtual ~MyData() {} -// DISALLOW_COPY_AND_ASSIGN(MyData); -// }; -// -// TRACE_EVENT1("foo", "bar", "data", -// scoped_refptr<ConvertableToTraceFormat>(new MyData())); -// -// The trace framework will take ownership if the passed pointer and it will -// be free'd when the trace buffer is flushed. -// -// Note, we only do the conversion when the buffer is flushed, so the provided -// data object should not be modified after it's passed to the trace framework. -// -// -// Thread Safety: -// A thread safe singleton and mutex are used for thread safety. Category -// enabled flags are used to limit the performance impact when the system -// is not enabled. -// -// TRACE_EVENT macros first cache a pointer to a category. The categories are -// statically allocated and safe at all times, even after exit. Fetching a -// category is protected by the TraceLog::lock_. Multiple threads initializing -// the static variable is safe, as they will be serialized by the lock and -// multiple calls will return the same pointer to the category. -// -// Then the category_group_enabled flag is checked. This is a unsigned char, and -// not intended to be multithread safe. It optimizes access to AddTraceEvent -// which is threadsafe internally via TraceLog::lock_. The enabled flag may -// cause some threads to incorrectly call or skip calling AddTraceEvent near -// the time of the system being enabled or disabled. This is acceptable as -// we tolerate some data loss while the system is being enabled/disabled and -// because AddTraceEvent is threadsafe internally and checks the enabled state -// again under lock. -// -// Without the use of these static category pointers and enabled flags all -// trace points would carry a significant performance cost of acquiring a lock -// and resolving the category. +// In the process of moving the trace event files. Right now the headers +// are being forwarded. In next CLs the change will get completed +// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032 #ifndef BASE_DEBUG_TRACE_EVENT_H_ #define BASE_DEBUG_TRACE_EVENT_H_ -#include <string> - -#include "base/atomicops.h" -#include "base/debug/trace_event_impl.h" -#include "base/debug/trace_event_memory.h" -#include "base/debug/trace_event_system_stats_monitor.h" -#include "base/time/time.h" -#include "build/build_config.h" - -// By default, const char* argument values are assumed to have long-lived scope -// and will not be copied. Use this macro to force a const char* to be copied. -#define TRACE_STR_COPY(str) \ - trace_event_internal::TraceStringWithCopy(str) - -// This will mark the trace event as disabled by default. The user will need -// to explicitly enable the event. -#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name - -// By default, uint64 ID argument values are not mangled with the Process ID in -// TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling. -#define TRACE_ID_MANGLE(id) \ - trace_event_internal::TraceID::ForceMangle(id) - -// By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC -// macros. Use this macro to prevent Process ID mangling. -#define TRACE_ID_DONT_MANGLE(id) \ - trace_event_internal::TraceID::DontMangle(id) - -// Records a pair of begin and end events called "name" for the current -// scope, with 0, 1 or 2 associated arguments. If the category is not -// enabled, then this does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT0(category_group, name) \ - INTERNAL_TRACE_MEMORY(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name) -#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_MEMORY(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val) -#define TRACE_EVENT2( \ - category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_MEMORY(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED( \ - category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) - -// Records events like TRACE_EVENT2 but uses |memory_tag| for memory tracing. -// Use this where |name| is too generic to accurately aggregate allocations. -#define TRACE_EVENT_WITH_MEMORY_TAG2( \ - category, name, memory_tag, arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_MEMORY(category, memory_tag) \ - INTERNAL_TRACE_EVENT_ADD_SCOPED( \ - category, name, arg1_name, arg1_val, arg2_name, arg2_val) - -// UNSHIPPED_TRACE_EVENT* are like TRACE_EVENT* except that they are not -// included in official builds. - -#if OFFICIAL_BUILD -#undef TRACING_IS_OFFICIAL_BUILD -#define TRACING_IS_OFFICIAL_BUILD 1 -#elif !defined(TRACING_IS_OFFICIAL_BUILD) -#define TRACING_IS_OFFICIAL_BUILD 0 -#endif - -#if TRACING_IS_OFFICIAL_BUILD -#define UNSHIPPED_TRACE_EVENT0(category_group, name) (void)0 -#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ - (void)0 -#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) (void)0 -#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) (void)0 -#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \ - arg1_name, arg1_val) (void)0 -#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \ - arg1_name, arg1_val, \ - arg2_name, arg2_val) (void)0 -#else -#define UNSHIPPED_TRACE_EVENT0(category_group, name) \ - TRACE_EVENT0(category_group, name) -#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ - TRACE_EVENT1(category_group, name, arg1_name, arg1_val) -#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) -#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) \ - TRACE_EVENT_INSTANT0(category_group, name, scope) -#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \ - arg1_name, arg1_val) \ - TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) -#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \ - arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#endif - -// Records a single event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_INSTANT0(category_group, name, scope) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_NONE | scope) -#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_NONE | scope, \ - arg1_name, arg1_val) -#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_NONE | scope, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_COPY | scope) -#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_COPY | scope, arg1_name, \ - arg1_val) -#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, \ - arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ - category_group, name, TRACE_EVENT_FLAG_COPY | scope, \ - arg1_name, arg1_val, arg2_name, arg2_val) - -// Sets the current sample state to the given category and name (both must be -// constant strings). These states are intended for a sampling profiler. -// Implementation note: we store category and name together because we don't -// want the inconsistency/expense of storing two pointers. -// |thread_bucket| is [0..2] and is used to statically isolate samples in one -// thread from others. -#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET( \ - bucket_number, category, name) \ - trace_event_internal:: \ - TraceEventSamplingStateScope<bucket_number>::Set(category "\0" name) - -// Returns a current sampling state of the given bucket. -#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ - trace_event_internal::TraceEventSamplingStateScope<bucket_number>::Current() - -// Creates a scope of a sampling state of the given bucket. -// -// { // The sampling state is set within this scope. -// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); -// ...; -// } -#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET( \ - bucket_number, category, name) \ - trace_event_internal::TraceEventSamplingStateScope<bucket_number> \ - traceEventSamplingScope(category "\0" name); - -// Syntactic sugars for the sampling tracing in the main thread. -#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ - TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) -#define TRACE_EVENT_GET_SAMPLING_STATE() \ - TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) -#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ - TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) - - -// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_BEGIN0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_BEGIN0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_BEGIN1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ - category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Similar to TRACE_EVENT_BEGINx but with a custom |at| timestamp provided. -// - |id| is used to match the _BEGIN event with the _END event. -// Events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, \ - name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \ - category_group, name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) - -// Records a single END event for "name" immediately. If the category -// is not enabled, then this does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_EVENT_END0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -#define TRACE_EVENT_COPY_END0(category_group, name) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_END1(category_group, name, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) -#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ - category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Similar to TRACE_EVENT_ENDx but with a custom |at| timestamp provided. -// - |id| is used to match the _BEGIN event with the _END event. -// Events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, \ - name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \ - category_group, name, id, thread_id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( \ - category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ - timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) - -// Records the value of a counter called "name" immediately. Value -// must be representable as a 32 bit integer. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_COUNTER1(category_group, name, value) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, TRACE_EVENT_FLAG_NONE, \ - "value", static_cast<int>(value)) -#define TRACE_COPY_COUNTER1(category_group, name, value) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, TRACE_EVENT_FLAG_COPY, \ - "value", static_cast<int>(value)) - -// Records the values of a multi-parted counter called "name" immediately. -// The UI will treat value1 and value2 as parts of a whole, displaying their -// values as a stacked-bar chart. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, TRACE_EVENT_FLAG_NONE, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) -#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, TRACE_EVENT_FLAG_COPY, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) - -// Records the value of a counter called "name" immediately. Value -// must be representable as a 32 bit integer. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to disambiguate counters with the same name. It must either -// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits -// will be xored with a hash of the process ID so that the same pointer on -// two different processes will not collide. -#define TRACE_COUNTER_ID1(category_group, name, id, value) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - "value", static_cast<int>(value)) -#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - "value", static_cast<int>(value)) - -// Records the values of a multi-parted counter called "name" immediately. -// The UI will treat value1 and value2 as parts of a whole, displaying their -// values as a stacked-bar chart. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to disambiguate counters with the same name. It must either -// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits -// will be xored with a hash of the process ID so that the same pointer on -// two different processes will not collide. -#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \ - value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) -#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \ - value1_val, value2_name, value2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - value1_name, static_cast<int>(value1_val), \ - value2_name, static_cast<int>(value2_val)) - -// ASYNC_STEP_* APIs should be only used by legacy code. New code should -// consider using NESTABLE_ASYNC_* APIs to describe substeps within an async -// event. -// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC -// events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -// -// An asynchronous operation can consist of multiple phases. The first phase is -// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the -// ASYNC_STEP_INTO or ASYNC_STEP_PAST macros. The ASYNC_STEP_INTO macro will -// annotate the block following the call. The ASYNC_STEP_PAST macro will -// annotate the block prior to the call. Note that any particular event must use -// only STEP_INTO or STEP_PAST macros; they can not mix and match. When the -// operation completes, call ASYNC_END. -// -// An ASYNC trace typically occurs on a single thread (if not, they will only be -// drawn on the thread defined in the ASYNC_BEGIN event), but all events in that -// operation must use the same |name| and |id|. Each step can have its own -// args. -#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val) -#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val, arg2_name, arg2_val) - -// Similar to TRACE_EVENT_ASYNC_BEGINx but with a custom |at| timestamp -// provided. -#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, \ - name, id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ - static_cast<int>(base::PlatformThread::CurrentId()), \ - timestamp, TRACE_EVENT_FLAG_NONE) - -// Records a single ASYNC_STEP_INTO event for |step| immediately. If the -// category is not enabled, then this does nothing. The |name| and |id| must -// match the ASYNC_BEGIN event above. The |step| param identifies this step -// within the async event. This should be called at the beginning of the next -// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any -// ASYNC_STEP_PAST events. -#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ - arg1_name, arg1_val) - -// Records a single ASYNC_STEP_PAST event for |step| immediately. If the -// category is not enabled, then this does nothing. The |name| and |id| must -// match the ASYNC_BEGIN event above. The |step| param identifies this step -// within the async event. This should be called at the beginning of the next -// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any -// ASYNC_STEP_INTO events. -#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ - arg1_name, arg1_val) - -// Records a single ASYNC_END event for "name" immediately. If the category -// is not enabled, then this does nothing. -#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val) -#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val, arg2_name, arg2_val) - -// Similar to TRACE_EVENT_ASYNC_ENDx but with a custom |at| timestamp provided. -#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, \ - name, id, timestamp) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ - TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ - static_cast<int>(base::PlatformThread::CurrentId()), \ - timestamp, TRACE_EVENT_FLAG_NONE) - -// NESTABLE_ASYNC_* APIs are used to describe an async operation, which can -// be nested within a NESTABLE_ASYNC event and/or have inner NESTABLE_ASYNC -// events. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to match the NESTABLE_ASYNC_BEGIN event with the -// NESTABLE_ASYNC_END event. Events are considered to match if their -// category_group, name and id values all match. |id| must either be a -// pointer or an integer value up to 64 bits. If it's a pointer, the bits -// will be xored with a hash of the process ID so that the same pointer on two -// different processes will not collide. -// -// Unmatched NESTABLE_ASYNC_END event will be parsed as an instant event, -// and unmatched NESTABLE_ASYNC_BEGIN event will be parsed as an event that -// ends at the last NESTABLE_ASYNC_END event of that |id|. - -// Records a single NESTABLE_ASYNC_BEGIN event called "name" immediately, with 2 -// associated arguments. If the category is not enabled, then this does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -// Records a single NESTABLE_ASYNC_END event called "name" immediately, with 2 -// associated arguments. If the category is not enabled, then this does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) -// Records a single NESTABLE_ASYNC_INSTANT event called "name" immediately, -// with 2 associated arguments. If the category is not enabled, then this -// does nothing. -#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(category_group, name, id, \ - arg1_name, arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ - arg2_name, arg2_val) - -// Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2 -// associated arguments. If the category is not enabled, then this -// does nothing. -// - category and name strings must have application lifetime (statics or -// literals). They may not include " chars. -// - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW -// events are considered to match if their category_group, name and id values -// all match. |id| must either be a pointer or an integer value up to 64 bits. -// If it's a pointer, the bits will be xored with a hash of the process ID so -// that the same pointer on two different processes will not collide. -// FLOW events are different from ASYNC events in how they are drawn by the -// tracing UI. A FLOW defines asynchronous data flow, such as posting a task -// (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be -// drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar -// to ASYNC, a FLOW can consist of multiple phases. The first phase is defined -// by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP -// macros. When the operation completes, call FLOW_END. An async operation can -// span threads and processes, but all events in that operation must use the -// same |name| and |id|. Each event can have its own args. -#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val) -#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val, arg2_name, arg2_val) - -// Records a single FLOW_STEP event for |step| immediately. If the category -// is not enabled, then this does nothing. The |name| and |id| must match the -// FLOW_BEGIN event above. The |step| param identifies this step within the -// async event. This should be called at the beginning of the next phase of an -// asynchronous operation. -#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) -#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ - arg1_name, arg1_val) -#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step) -#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, \ - arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ - arg1_name, arg1_val) - -// Records a single FLOW_END event for "name" immediately. If the category -// is not enabled, then this does nothing. -#define TRACE_EVENT_FLOW_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE) -#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) -#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val, \ - arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_NONE, \ - arg1_name, arg1_val, arg2_name, arg2_val) -#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY) -#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name, \ - arg1_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val) -#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name, \ - arg1_val, arg2_name, arg2_val) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ - category_group, name, id, TRACE_EVENT_FLAG_COPY, \ - arg1_name, arg1_val, arg2_name, arg2_val) - -// Macros to track the life time and value of arbitrary client objects. -// See also TraceTrackableObject. -#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \ - category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE) - -#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, \ - category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE,\ - "snapshot", snapshot) - -#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \ - INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \ - category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE) - -#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ - UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ - (base::debug::TraceLog::ENABLED_FOR_RECORDING | \ - base::debug::TraceLog::ENABLED_FOR_EVENT_CALLBACK)) - -// Macro to efficiently determine if a given category group is enabled. -#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - *ret = true; \ - } else { \ - *ret = false; \ - } \ - } while (0) - -// Macro to efficiently determine, through polling, if a new trace has begun. -#define TRACE_EVENT_IS_NEW_TRACE(ret) \ - do { \ - static int INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = 0; \ - int num_traces_recorded = TRACE_EVENT_API_GET_NUM_TRACES_RECORDED(); \ - if (num_traces_recorded != -1 && \ - num_traces_recorded != \ - INTERNAL_TRACE_EVENT_UID(lastRecordingNumber)) { \ - INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = \ - num_traces_recorded; \ - *ret = true; \ - } else { \ - *ret = false; \ - } \ - } while (0) - -//////////////////////////////////////////////////////////////////////////////// -// Implementation specific tracing API definitions. - -// Get a pointer to the enabled state of the given trace category. Only -// long-lived literal strings should be given as the category group. The -// returned pointer can be held permanently in a local static for example. If -// the unsigned char is non-zero, tracing is enabled. If tracing is enabled, -// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled -// between the load of the tracing state and the call to -// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out -// for best performance when tracing is disabled. -// const unsigned char* -// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group) -#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ - base::debug::TraceLog::GetCategoryGroupEnabled - -// Get the number of times traces have been recorded. This is used to implement -// the TRACE_EVENT_IS_NEW_TRACE facility. -// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED() -#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \ - base::debug::TraceLog::GetInstance()->GetNumTracesRecorded - -// Add a trace event to the platform tracing system. -// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// unsigned long long id, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// unsigned char flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT \ - base::debug::TraceLog::GetInstance()->AddTraceEvent - -// Add a trace event to the platform tracing system. -// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( -// char phase, -// const unsigned char* category_group_enabled, -// const char* name, -// unsigned long long id, -// int thread_id, -// const TimeTicks& timestamp, -// int num_args, -// const char** arg_names, -// const unsigned char* arg_types, -// const unsigned long long* arg_values, -// unsigned char flags) -#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \ - base::debug::TraceLog::GetInstance()->AddTraceEventWithThreadIdAndTimestamp - -// Set the duration field of a COMPLETE trace event. -// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( -// const unsigned char* category_group_enabled, -// const char* name, -// base::debug::TraceEventHandle id) -#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ - base::debug::TraceLog::GetInstance()->UpdateTraceEventDuration - -// Defines atomic operations used internally by the tracing system. -#define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord -#define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var)) -#define TRACE_EVENT_API_ATOMIC_STORE(var, value) \ - base::subtle::NoBarrier_Store(&(var), (value)) - -// Defines visibility for classes in trace_event.h -#define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT - -// The thread buckets for the sampling profiler. -TRACE_EVENT_API_CLASS_EXPORT extern \ - TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3]; - -#define TRACE_EVENT_API_THREAD_BUCKET(thread_bucket) \ - g_trace_state[thread_bucket] - -//////////////////////////////////////////////////////////////////////////////// - -// Implementation detail: trace event macros create temporary variables -// to keep instrumentation overhead low. These macros give each temporary -// variable a unique name based on the line number to prevent name collisions. -#define INTERNAL_TRACE_EVENT_UID3(a,b) \ - trace_event_unique_##a##b -#define INTERNAL_TRACE_EVENT_UID2(a,b) \ - INTERNAL_TRACE_EVENT_UID3(a,b) -#define INTERNAL_TRACE_EVENT_UID(name_prefix) \ - INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) - -// Implementation detail: internal macro to create static category. -// No barriers are needed, because this code is designed to operate safely -// even when the unsigned char* points to garbage data (which may be the case -// on processors without cache coherency). -#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ - category_group, atomic, category_group_enabled) \ - category_group_enabled = \ - reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( \ - atomic)); \ - if (UNLIKELY(!category_group_enabled)) { \ - category_group_enabled = \ - TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \ - TRACE_EVENT_API_ATOMIC_STORE(atomic, \ - reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \ - category_group_enabled)); \ - } - -#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \ - static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \ - const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \ - INTERNAL_TRACE_EVENT_UID(atomic), \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled)); - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - trace_event_internal::AddTraceEvent( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - trace_event_internal::kNoEventId, flags, ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add begin -// event if the category is enabled. Also adds the end event when the scope -// ends. -#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - base::debug::TraceEventHandle h = trace_event_internal::AddTraceEvent( \ - TRACE_EVENT_PHASE_COMPLETE, \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ - name, trace_event_internal::kNoEventId, \ - TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ - INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ - INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ - } - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \ - flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ - trace_event_internal::TraceID trace_event_trace_id( \ - id, &trace_event_flags); \ - trace_event_internal::AddTraceEvent( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ - name, trace_event_trace_id.data(), trace_event_flags, \ - ##__VA_ARGS__); \ - } \ - } while (0) - -// Implementation detail: internal macro to create static category and add -// event if the category is enabled. -#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(phase, \ - category_group, name, id, thread_id, timestamp, flags, ...) \ - do { \ - INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ - if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ - unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ - trace_event_internal::TraceID trace_event_trace_id( \ - id, &trace_event_flags); \ - trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ - phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ - name, trace_event_trace_id.data(), \ - thread_id, base::TimeTicks::FromInternalValue(timestamp), \ - trace_event_flags, ##__VA_ARGS__); \ - } \ - } while (0) - -// Notes regarding the following definitions: -// New values can be added and propagated to third party libraries, but existing -// definitions must never be changed, because third party libraries may use old -// definitions. - -// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. -#define TRACE_EVENT_PHASE_BEGIN ('B') -#define TRACE_EVENT_PHASE_END ('E') -#define TRACE_EVENT_PHASE_COMPLETE ('X') -#define TRACE_EVENT_PHASE_INSTANT ('I') -#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') -#define TRACE_EVENT_PHASE_ASYNC_STEP_INTO ('T') -#define TRACE_EVENT_PHASE_ASYNC_STEP_PAST ('p') -#define TRACE_EVENT_PHASE_ASYNC_END ('F') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN ('b') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_END ('e') -#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT ('n') -#define TRACE_EVENT_PHASE_FLOW_BEGIN ('s') -#define TRACE_EVENT_PHASE_FLOW_STEP ('t') -#define TRACE_EVENT_PHASE_FLOW_END ('f') -#define TRACE_EVENT_PHASE_METADATA ('M') -#define TRACE_EVENT_PHASE_COUNTER ('C') -#define TRACE_EVENT_PHASE_SAMPLE ('P') -#define TRACE_EVENT_PHASE_CREATE_OBJECT ('N') -#define TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ('O') -#define TRACE_EVENT_PHASE_DELETE_OBJECT ('D') - -// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. -#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0)) -#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0)) -#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1)) -#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2)) -#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned char>(1 << 3)) - -#define TRACE_EVENT_FLAG_SCOPE_MASK (static_cast<unsigned char>( \ - TRACE_EVENT_FLAG_SCOPE_OFFSET | (TRACE_EVENT_FLAG_SCOPE_OFFSET << 1))) - -// Type values for identifying types in the TraceValue union. -#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) -#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) -#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) -#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) -#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) -#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) -#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) -#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8)) - -// Enum reflecting the scope of an INSTANT event. Must fit within -// TRACE_EVENT_FLAG_SCOPE_MASK. -#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3)) -#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3)) -#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3)) - -#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g') -#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p') -#define TRACE_EVENT_SCOPE_NAME_THREAD ('t') - -namespace trace_event_internal { - -// Specify these values when the corresponding argument of AddTraceEvent is not -// used. -const int kZeroNumArgs = 0; -const unsigned long long kNoEventId = 0; - -// TraceID encapsulates an ID that can either be an integer or pointer. Pointers -// are by default mangled with the Process ID so that they are unlikely to -// collide when the same pointer is used on different processes. -class TraceID { - public: - class DontMangle { - public: - explicit DontMangle(const void* id) - : data_(static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(id))) {} - explicit DontMangle(unsigned long long id) : data_(id) {} - explicit DontMangle(unsigned long id) : data_(id) {} - explicit DontMangle(unsigned int id) : data_(id) {} - explicit DontMangle(unsigned short id) : data_(id) {} - explicit DontMangle(unsigned char id) : data_(id) {} - explicit DontMangle(long long id) - : data_(static_cast<unsigned long long>(id)) {} - explicit DontMangle(long id) - : data_(static_cast<unsigned long long>(id)) {} - explicit DontMangle(int id) - : data_(static_cast<unsigned long long>(id)) {} - explicit DontMangle(short id) - : data_(static_cast<unsigned long long>(id)) {} - explicit DontMangle(signed char id) - : data_(static_cast<unsigned long long>(id)) {} - unsigned long long data() const { return data_; } - private: - unsigned long long data_; - }; - - class ForceMangle { - public: - explicit ForceMangle(unsigned long long id) : data_(id) {} - explicit ForceMangle(unsigned long id) : data_(id) {} - explicit ForceMangle(unsigned int id) : data_(id) {} - explicit ForceMangle(unsigned short id) : data_(id) {} - explicit ForceMangle(unsigned char id) : data_(id) {} - explicit ForceMangle(long long id) - : data_(static_cast<unsigned long long>(id)) {} - explicit ForceMangle(long id) - : data_(static_cast<unsigned long long>(id)) {} - explicit ForceMangle(int id) - : data_(static_cast<unsigned long long>(id)) {} - explicit ForceMangle(short id) - : data_(static_cast<unsigned long long>(id)) {} - explicit ForceMangle(signed char id) - : data_(static_cast<unsigned long long>(id)) {} - unsigned long long data() const { return data_; } - private: - unsigned long long data_; - }; - TraceID(const void* id, unsigned char* flags) - : data_(static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(id))) { - *flags |= TRACE_EVENT_FLAG_MANGLE_ID; - } - TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) { - *flags |= TRACE_EVENT_FLAG_MANGLE_ID; - } - TraceID(DontMangle id, unsigned char* flags) : data_(id.data()) { - } - TraceID(unsigned long long id, unsigned char* flags) - : data_(id) { (void)flags; } - TraceID(unsigned long id, unsigned char* flags) - : data_(id) { (void)flags; } - TraceID(unsigned int id, unsigned char* flags) - : data_(id) { (void)flags; } - TraceID(unsigned short id, unsigned char* flags) - : data_(id) { (void)flags; } - TraceID(unsigned char id, unsigned char* flags) - : data_(id) { (void)flags; } - TraceID(long long id, unsigned char* flags) - : data_(static_cast<unsigned long long>(id)) { (void)flags; } - TraceID(long id, unsigned char* flags) - : data_(static_cast<unsigned long long>(id)) { (void)flags; } - TraceID(int id, unsigned char* flags) - : data_(static_cast<unsigned long long>(id)) { (void)flags; } - TraceID(short id, unsigned char* flags) - : data_(static_cast<unsigned long long>(id)) { (void)flags; } - TraceID(signed char id, unsigned char* flags) - : data_(static_cast<unsigned long long>(id)) { (void)flags; } - - unsigned long long data() const { return data_; } - - private: - unsigned long long data_; -}; - -// Simple union to store various types as unsigned long long. -union TraceValueUnion { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; -}; - -// Simple container for const char* that should be copied instead of retained. -class TraceStringWithCopy { - public: - explicit TraceStringWithCopy(const char* str) : str_(str) {} - const char* str() const { return str_; } - private: - const char* str_; -}; - -// Define SetTraceValue for each allowed type. It stores the type and -// value in the return arguments. This allows this API to avoid declaring any -// structures so that it is portable to third_party libraries. -#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ - arg_expression, \ - union_member, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - TraceValueUnion type_value; \ - type_value.union_member = arg_expression; \ - *type = value_type_id; \ - *value = type_value.as_uint; \ - } -// Simpler form for int types that can be safely casted. -#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - *type = value_type_id; \ - *value = static_cast<unsigned long long>(arg); \ - } - -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL) -INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double, - TRACE_VALUE_TYPE_DOUBLE) -INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer, - TRACE_VALUE_TYPE_POINTER) -INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string, - TRACE_VALUE_TYPE_STRING) -INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), - as_string, TRACE_VALUE_TYPE_COPY_STRING) - -#undef INTERNAL_DECLARE_SET_TRACE_VALUE -#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT - -// std::string version of SetTraceValue so that trace arguments can be strings. -static inline void SetTraceValue(const std::string& arg, - unsigned char* type, - unsigned long long* value) { - TraceValueUnion type_value; - type_value.as_string = arg.c_str(); - *type = TRACE_VALUE_TYPE_COPY_STRING; - *value = type_value.as_uint; -} - -// base::Time and base::TimeTicks version of SetTraceValue to make it easier to -// trace these types. -static inline void SetTraceValue(const base::Time arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -static inline void SetTraceValue(const base::TimeTicks arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -// These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template -// functions are defined here instead of in the macro, because the arg_values -// could be temporary objects, such as std::string. In order to store -// pointers to the internal c_str and pass through to the tracing API, -// the arg_values must live throughout these procedures. - -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val) { - const int num_args = 1; - unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE }; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, &arg1_name, arg_types, NULL, &arg1_val, flags); -} - -template<class ARG1_TYPE> -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE; - - scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2]; - convertable_values[1] = arg2_val; - - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, arg_names, arg_types, arg_values, convertable_values, flags); -} - -template<class ARG2_TYPE> -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE; - arg_values[0] = 0; - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - - scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2]; - convertable_values[0] = arg1_val; - - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, arg_names, arg_types, arg_values, convertable_values, flags); -} - -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val, - const char* arg2_name, - const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2] = - { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE }; - scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2] = - { arg1_val, arg2_val }; - - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, arg_names, arg_types, NULL, convertable_values, flags); -} - -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags) { - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - kZeroNumArgs, NULL, NULL, NULL, NULL, flags); -} - -static inline base::debug::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - unsigned char flags) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); - return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, - name, id, thread_id, now, flags); -} - -template<class ARG1_TYPE> -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const ARG1_TYPE& arg1_val) { - const int num_args = 1; - unsigned char arg_types[1]; - unsigned long long arg_values[1]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, &arg1_name, arg_types, arg_values, NULL, flags); -} - -template<class ARG1_TYPE> -static inline base::debug::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - unsigned char flags, - const char* arg1_name, - const ARG1_TYPE& arg1_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); - return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, - name, id, thread_id, now, flags, - arg1_name, arg1_val); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::debug::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned char flags, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, id, thread_id, timestamp, - num_args, arg_names, arg_types, arg_values, NULL, flags); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::debug::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - unsigned char flags, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); - return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, - name, id, thread_id, now, flags, - arg1_name, arg1_val, - arg2_name, arg2_val); -} - -// Used by TRACE_EVENTx macros. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { - public: - // Note: members of data_ intentionally left uninitialized. See Initialize. - ScopedTracer() : p_data_(NULL) {} - - ~ScopedTracer() { - if (p_data_ && *data_.category_group_enabled) - TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( - data_.category_group_enabled, data_.name, data_.event_handle); - } - - void Initialize(const unsigned char* category_group_enabled, - const char* name, - base::debug::TraceEventHandle event_handle) { - data_.category_group_enabled = category_group_enabled; - data_.name = name; - data_.event_handle = event_handle; - p_data_ = &data_; - } - - private: - // This Data struct workaround is to avoid initializing all the members - // in Data during construction of this object, since this object is always - // constructed, even when tracing is disabled. If the members of Data were - // members of this class instead, compiler warnings occur about potential - // uninitialized accesses. - struct Data { - const unsigned char* category_group_enabled; - const char* name; - base::debug::TraceEventHandle event_handle; - }; - Data* p_data_; - Data data_; -}; - -// Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient { - public: - ScopedTraceBinaryEfficient(const char* category_group, const char* name); - ~ScopedTraceBinaryEfficient(); - - private: - const unsigned char* category_group_enabled_; - const char* name_; - base::debug::TraceEventHandle event_handle_; -}; - -// This macro generates less code then TRACE_EVENT0 but is also -// slower to execute when tracing is off. It should generally only be -// used with code that is seldom executed or conditionally executed -// when debugging. -// For now the category_group must be "gpu". -#define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \ - trace_event_internal::ScopedTraceBinaryEfficient \ - INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name); - -// TraceEventSamplingStateScope records the current sampling state -// and sets a new sampling state. When the scope exists, it restores -// the sampling state having recorded. -template<size_t BucketNumber> -class TraceEventSamplingStateScope { - public: - TraceEventSamplingStateScope(const char* category_and_name) { - previous_state_ = TraceEventSamplingStateScope<BucketNumber>::Current(); - TraceEventSamplingStateScope<BucketNumber>::Set(category_and_name); - } - - ~TraceEventSamplingStateScope() { - TraceEventSamplingStateScope<BucketNumber>::Set(previous_state_); - } - - static inline const char* Current() { - return reinterpret_cast<const char*>(TRACE_EVENT_API_ATOMIC_LOAD( - g_trace_state[BucketNumber])); - } - - static inline void Set(const char* category_and_name) { - TRACE_EVENT_API_ATOMIC_STORE( - g_trace_state[BucketNumber], - reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( - const_cast<char*>(category_and_name))); - } - - private: - const char* previous_state_; -}; - -} // namespace trace_event_internal - -namespace base { -namespace debug { - -template<typename IDType> class TraceScopedTrackableObject { - public: - TraceScopedTrackableObject(const char* category_group, const char* name, - IDType id) - : category_group_(category_group), - name_(name), - id_(id) { - TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group_, name_, id_); - } - - template <typename ArgType> void snapshot(ArgType snapshot) { - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group_, name_, id_, snapshot); - } - - ~TraceScopedTrackableObject() { - TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group_, name_, id_); - } - - private: - const char* category_group_; - const char* name_; - IDType id_; - - DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject); -}; - -} // namespace debug -} // namespace base +#include "base/trace_event/trace_event.h" -#endif /* BASE_DEBUG_TRACE_EVENT_H_ */ +#endif // BASE_DEBUG_TRACE_EVENT_H_ diff --git a/base/debug/trace_event_argument.h b/base/debug/trace_event_argument.h index 98f1bcf..167b46c 100644 --- a/base/debug/trace_event_argument.h +++ b/base/debug/trace_event_argument.h @@ -2,58 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// In the process of moving the trace event files. Right now the headers +// are being forwarded. In next CLs the change will get completed +// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032 + #ifndef BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_ #define BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_ -#include <string> -#include <vector> - -#include "base/debug/trace_event.h" -#include "base/memory/scoped_ptr.h" - -namespace base { -class DictionaryValue; -class ListValue; -class Value; - -namespace debug { - -class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { - public: - TracedValue(); - - void EndDictionary(); - void EndArray(); - - void SetInteger(const char* name, int value); - void SetDouble(const char* name, double); - void SetBoolean(const char* name, bool value); - void SetString(const char* name, const std::string& value); - void SetValue(const char* name, Value* value); - void BeginDictionary(const char* name); - void BeginArray(const char* name); - - void AppendInteger(int); - void AppendDouble(double); - void AppendBoolean(bool); - void AppendString(const std::string&); - void BeginArray(); - void BeginDictionary(); - - void AppendAsTraceFormat(std::string* out) const override; - - private: - ~TracedValue() override; - - DictionaryValue* GetCurrentDictionary(); - ListValue* GetCurrentArray(); - - scoped_ptr<base::Value> root_; - std::vector<Value*> stack_; - DISALLOW_COPY_AND_ASSIGN(TracedValue); -}; - -} // namespace debug -} // namespace base +#include "base/trace_event/trace_event_argument.h" -#endif // BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_ +#endif // BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_ diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h index 1b1fce3..a619d29 100644 --- a/base/debug/trace_event_impl.h +++ b/base/debug/trace_event_impl.h @@ -1,813 +1,14 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// In the process of moving the trace event files. Right now the headers +// are being forwarded. In next CLs the change will get completed +// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032 #ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_ #define BASE_DEBUG_TRACE_EVENT_IMPL_H_ -#include <stack> -#include <string> -#include <vector> - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted_memory.h" -#include "base/memory/scoped_vector.h" -#include "base/observer_list.h" -#include "base/strings/string_util.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread.h" -#include "base/threading/thread_local.h" - -// Older style trace macros with explicit id and extra data -// Only these macros result in publishing data to ETW as currently implemented. -#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ - base::debug::TraceLog::AddTraceEventEtw( \ - TRACE_EVENT_PHASE_BEGIN, \ - name, reinterpret_cast<const void*>(id), extra) - -#define TRACE_EVENT_END_ETW(name, id, extra) \ - base::debug::TraceLog::AddTraceEventEtw( \ - TRACE_EVENT_PHASE_END, \ - name, reinterpret_cast<const void*>(id), extra) - -#define TRACE_EVENT_INSTANT_ETW(name, id, extra) \ - base::debug::TraceLog::AddTraceEventEtw( \ - TRACE_EVENT_PHASE_INSTANT, \ - name, reinterpret_cast<const void*>(id), extra) - -template <typename Type> -struct DefaultSingletonTraits; - -namespace base { - -class WaitableEvent; -class MessageLoop; - -namespace debug { - -// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided -// class must implement this interface. -class BASE_EXPORT ConvertableToTraceFormat - : public RefCounted<ConvertableToTraceFormat> { - public: - // Append the class info to the provided |out| string. The appended - // data must be a valid JSON object. Strings must be properly quoted, and - // escaped. There is no processing applied to the content after it is - // appended. - virtual void AppendAsTraceFormat(std::string* out) const = 0; - - std::string ToString() const { - std::string result; - AppendAsTraceFormat(&result); - return result; - } - - protected: - virtual ~ConvertableToTraceFormat() {} - - private: - friend class RefCounted<ConvertableToTraceFormat>; -}; - -struct TraceEventHandle { - uint32 chunk_seq; - uint16 chunk_index; - uint16 event_index; -}; - -const int kTraceMaxNumArgs = 2; - -class BASE_EXPORT TraceEvent { - public: - union TraceValue { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; - }; - - TraceEvent(); - ~TraceEvent(); - - // We don't need to copy TraceEvent except when TraceEventBuffer is cloned. - // Use explicit copy method to avoid accidentally misuse of copy. - void CopyFrom(const TraceEvent& other); - - void Initialize( - int thread_id, - TimeTicks timestamp, - TimeTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - const scoped_refptr<ConvertableToTraceFormat>* convertable_values, - unsigned char flags); - - void Reset(); - - void UpdateDuration(const TimeTicks& now, const TimeTicks& thread_now); - - // Serialize event data to JSON - void AppendAsJSON(std::string* out) const; - void AppendPrettyPrinted(std::ostringstream* out) const; - - static void AppendValueAsJSON(unsigned char type, - TraceValue value, - std::string* out); - - TimeTicks timestamp() const { return timestamp_; } - TimeTicks thread_timestamp() const { return thread_timestamp_; } - char phase() const { return phase_; } - int thread_id() const { return thread_id_; } - TimeDelta duration() const { return duration_; } - TimeDelta thread_duration() const { return thread_duration_; } - unsigned long long id() const { return id_; } - unsigned char flags() const { return flags_; } - - // Exposed for unittesting: - - const base::RefCountedString* parameter_copy_storage() const { - return parameter_copy_storage_.get(); - } - - const unsigned char* category_group_enabled() const { - return category_group_enabled_; - } - - const char* name() const { return name_; } - -#if defined(OS_ANDROID) - void SendToATrace(); -#endif - - private: - // Note: these are ordered by size (largest first) for optimal packing. - TimeTicks timestamp_; - TimeTicks thread_timestamp_; - TimeDelta duration_; - TimeDelta thread_duration_; - // id_ can be used to store phase-specific data. - unsigned long long id_; - TraceValue arg_values_[kTraceMaxNumArgs]; - const char* arg_names_[kTraceMaxNumArgs]; - scoped_refptr<ConvertableToTraceFormat> convertable_values_[kTraceMaxNumArgs]; - const unsigned char* category_group_enabled_; - const char* name_; - scoped_refptr<base::RefCountedString> parameter_copy_storage_; - int thread_id_; - char phase_; - unsigned char flags_; - unsigned char arg_types_[kTraceMaxNumArgs]; - - DISALLOW_COPY_AND_ASSIGN(TraceEvent); -}; - -// TraceBufferChunk is the basic unit of TraceBuffer. -class BASE_EXPORT TraceBufferChunk { - public: - explicit TraceBufferChunk(uint32 seq) - : next_free_(0), - seq_(seq) { - } - - void Reset(uint32 new_seq); - TraceEvent* AddTraceEvent(size_t* event_index); - bool IsFull() const { return next_free_ == kTraceBufferChunkSize; } - - uint32 seq() const { return seq_; } - size_t capacity() const { return kTraceBufferChunkSize; } - size_t size() const { return next_free_; } - - TraceEvent* GetEventAt(size_t index) { - DCHECK(index < size()); - return &chunk_[index]; - } - const TraceEvent* GetEventAt(size_t index) const { - DCHECK(index < size()); - return &chunk_[index]; - } - - scoped_ptr<TraceBufferChunk> Clone() const; - - static const size_t kTraceBufferChunkSize = 64; - - private: - size_t next_free_; - TraceEvent chunk_[kTraceBufferChunkSize]; - uint32 seq_; -}; - -// TraceBuffer holds the events as they are collected. -class BASE_EXPORT TraceBuffer { - public: - virtual ~TraceBuffer() {} - - virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t *index) = 0; - virtual void ReturnChunk(size_t index, - scoped_ptr<TraceBufferChunk> chunk) = 0; - - virtual bool IsFull() const = 0; - virtual size_t Size() const = 0; - virtual size_t Capacity() const = 0; - virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) = 0; - - // For iteration. Each TraceBuffer can only be iterated once. - virtual const TraceBufferChunk* NextChunk() = 0; - - virtual scoped_ptr<TraceBuffer> CloneForIteration() const = 0; -}; - -// TraceResultBuffer collects and converts trace fragments returned by TraceLog -// to JSON output. -class BASE_EXPORT TraceResultBuffer { - public: - typedef base::Callback<void(const std::string&)> OutputCallback; - - // If you don't need to stream JSON chunks out efficiently, and just want to - // get a complete JSON string after calling Finish, use this struct to collect - // JSON trace output. - struct BASE_EXPORT SimpleOutput { - OutputCallback GetCallback(); - void Append(const std::string& json_string); - - // Do what you want with the json_output_ string after calling - // TraceResultBuffer::Finish. - std::string json_output; - }; - - TraceResultBuffer(); - ~TraceResultBuffer(); - - // Set callback. The callback will be called during Start with the initial - // JSON output and during AddFragment and Finish with following JSON output - // chunks. The callback target must live past the last calls to - // TraceResultBuffer::Start/AddFragment/Finish. - void SetOutputCallback(const OutputCallback& json_chunk_callback); - - // Start JSON output. This resets all internal state, so you can reuse - // the TraceResultBuffer by calling Start. - void Start(); - - // Call AddFragment 0 or more times to add trace fragments from TraceLog. - void AddFragment(const std::string& trace_fragment); - - // When all fragments have been added, call Finish to complete the JSON - // formatted output. - void Finish(); - - private: - OutputCallback output_callback_; - bool append_comma_; -}; - -class BASE_EXPORT CategoryFilter { - public: - typedef std::vector<std::string> StringList; - - // The default category filter, used when none is provided. - // Allows all categories through, except if they end in the suffix 'Debug' or - // 'Test'. - static const char kDefaultCategoryFilterString[]; - - // |filter_string| is a comma-delimited list of category wildcards. - // A category can have an optional '-' prefix to make it an excluded category. - // All the same rules apply above, so for example, having both included and - // excluded categories in the same list would not be supported. - // - // Example: CategoryFilter"test_MyTest*"); - // Example: CategoryFilter("test_MyTest*,test_OtherStuff"); - // Example: CategoryFilter("-excluded_category1,-excluded_category2"); - // Example: CategoryFilter("-*,webkit"); would disable everything but webkit. - // Example: CategoryFilter("-webkit"); would enable everything but webkit. - // - // Category filters can also be used to configure synthetic delays. - // - // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16)"); would make swap - // buffers always take at least 16 ms. - // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16;oneshot)"); would - // make swap buffers take at least 16 ms the first time it is - // called. - // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16;alternating)"); - // would make swap buffers take at least 16 ms every other time it - // is called. - explicit CategoryFilter(const std::string& filter_string); - - CategoryFilter(); - - CategoryFilter(const CategoryFilter& cf); - - ~CategoryFilter(); - - CategoryFilter& operator=(const CategoryFilter& rhs); - - // Writes the string representation of the CategoryFilter. This is a comma - // separated string, similar in nature to the one used to determine - // enabled/disabled category patterns, except here there is an arbitrary - // order, included categories go first, then excluded categories. Excluded - // categories are distinguished from included categories by the prefix '-'. - std::string ToString() const; - - // Returns true if at least one category in the list is enabled by this - // category filter. - bool IsCategoryGroupEnabled(const char* category_group) const; - - // Return a list of the synthetic delays specified in this category filter. - const StringList& GetSyntheticDelayValues() const; - - // Merges nested_filter with the current CategoryFilter - void Merge(const CategoryFilter& nested_filter); - - // Clears both included/excluded pattern lists. This would be equivalent to - // creating a CategoryFilter with an empty string, through the constructor. - // i.e: CategoryFilter(). - // - // When using an empty filter, all categories are considered included as we - // are not excluding anything. - void Clear(); - - private: - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, CategoryFilter); - - // Returns true if category is enable according to this filter. - bool IsCategoryEnabled(const char* category_name) const; - - static bool IsEmptyOrContainsLeadingOrTrailingWhitespace( - const std::string& str); - - void Initialize(const std::string& filter_string); - void WriteString(const StringList& values, - std::string* out, - bool included) const; - void WriteString(const StringList& delays, std::string* out) const; - bool HasIncludedPatterns() const; - - StringList included_; - StringList disabled_; - StringList excluded_; - StringList delays_; -}; - -class TraceSamplingThread; - -// Options determines how the trace buffer stores data. -enum TraceRecordMode { - // Record until the trace buffer is full. - RECORD_UNTIL_FULL, - - // Record until the user ends the trace. The trace buffer is a fixed size - // and we use it as a ring buffer during recording. - RECORD_CONTINUOUSLY, - - // Echo to console. Events are discarded. - ECHO_TO_CONSOLE, - - // Record until the trace buffer is full, but with a huge buffer size. - RECORD_AS_MUCH_AS_POSSIBLE -}; - -struct BASE_EXPORT TraceOptions { - TraceOptions() - : record_mode(RECORD_UNTIL_FULL), - enable_sampling(false), - enable_systrace(false) {} - - explicit TraceOptions(TraceRecordMode record_mode) - : record_mode(record_mode), - enable_sampling(false), - enable_systrace(false) {} - - // |options_string| is a comma-delimited list of trace options. - // Possible options are: "record-until-full", "record-continuously", - // "trace-to-console", "enable-sampling" and "enable-systrace". - // The first 3 options are trace recoding modes and hence - // mutually exclusive. If more than one trace recording modes appear in the - // options_string, the last one takes precedence. If none of the trace - // recording mode is specified, recording mode is RECORD_UNTIL_FULL. - // - // The trace option will first be reset to the default option - // (record_mode set to RECORD_UNTIL_FULL, enable_sampling and enable_systrace - // set to false) before options parsed from |options_string| are applied on - // it. - // If |options_string| is invalid, the final state of trace_options is - // undefined. - // - // Example: trace_options.SetFromString("record-until-full") - // Example: trace_options.SetFromString( - // "record-continuously, enable-sampling") - // Example: trace_options.SetFromString("record-until-full, trace-to-console") - // will set ECHO_TO_CONSOLE as the recording mode. - // - // Returns true on success. - bool SetFromString(const std::string& options_string); - - std::string ToString() const; - - TraceRecordMode record_mode; - bool enable_sampling; - bool enable_systrace; -}; - -struct BASE_EXPORT TraceLogStatus { - TraceLogStatus(); - ~TraceLogStatus(); - size_t event_capacity; - size_t event_count; -}; - -class BASE_EXPORT TraceLog { - public: - enum Mode { - DISABLED = 0, - RECORDING_MODE, - MONITORING_MODE, - }; - - // The pointer returned from GetCategoryGroupEnabledInternal() points to a - // value with zero or more of the following bits. Used in this class only. - // The TRACE_EVENT macros should only use the value as a bool. - // These values must be in sync with macro values in TraceEvent.h in Blink. - enum CategoryGroupEnabledFlags { - // Category group enabled for the recording mode. - ENABLED_FOR_RECORDING = 1 << 0, - // Category group enabled for the monitoring mode. - ENABLED_FOR_MONITORING = 1 << 1, - // Category group enabled by SetEventCallbackEnabled(). - ENABLED_FOR_EVENT_CALLBACK = 1 << 2, - }; - - static TraceLog* GetInstance(); - - // Get set of known category groups. This can change as new code paths are - // reached. The known category groups are inserted into |category_groups|. - void GetKnownCategoryGroups(std::vector<std::string>* category_groups); - - // Retrieves a copy (for thread-safety) of the current CategoryFilter. - CategoryFilter GetCurrentCategoryFilter(); - - // Retrieves a copy (for thread-safety) of the current TraceOptions. - TraceOptions GetCurrentTraceOptions() const; - - // Enables normal tracing (recording trace events in the trace buffer). - // See CategoryFilter comments for details on how to control what categories - // will be traced. If tracing has already been enabled, |category_filter| will - // be merged into the current category filter. - void SetEnabled(const CategoryFilter& category_filter, - Mode mode, const TraceOptions& options); - - // Disables normal tracing for all categories. - void SetDisabled(); - - bool IsEnabled() { return mode_ != DISABLED; } - - // The number of times we have begun recording traces. If tracing is off, - // returns -1. If tracing is on, then it returns the number of times we have - // recorded a trace. By watching for this number to increment, you can - // passively discover when a new trace has begun. This is then used to - // implement the TRACE_EVENT_IS_NEW_TRACE() primitive. - int GetNumTracesRecorded(); - -#if defined(OS_ANDROID) - void StartATrace(); - void StopATrace(); - void AddClockSyncMetadataEvent(); -#endif - - // Enabled state listeners give a callback when tracing is enabled or - // disabled. This can be used to tie into other library's tracing systems - // on-demand. - class BASE_EXPORT EnabledStateObserver { - public: - // Called just after the tracing system becomes enabled, outside of the - // |lock_|. TraceLog::IsEnabled() is true at this point. - virtual void OnTraceLogEnabled() = 0; - - // Called just after the tracing system disables, outside of the |lock_|. - // TraceLog::IsEnabled() is false at this point. - virtual void OnTraceLogDisabled() = 0; - }; - void AddEnabledStateObserver(EnabledStateObserver* listener); - void RemoveEnabledStateObserver(EnabledStateObserver* listener); - bool HasEnabledStateObserver(EnabledStateObserver* listener) const; - - TraceLogStatus GetStatus() const; - bool BufferIsFull() const; - - // Not using base::Callback because of its limited by 7 parameters. - // Also, using primitive type allows directly passing callback from WebCore. - // WARNING: It is possible for the previously set callback to be called - // after a call to SetEventCallbackEnabled() that replaces or a call to - // SetEventCallbackDisabled() that disables the callback. - // This callback may be invoked on any thread. - // For TRACE_EVENT_PHASE_COMPLETE events, the client will still receive pairs - // of TRACE_EVENT_PHASE_BEGIN and TRACE_EVENT_PHASE_END events to keep the - // interface simple. - typedef void (*EventCallback)(TimeTicks timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char* const arg_names[], - const unsigned char arg_types[], - const unsigned long long arg_values[], - unsigned char flags); - - // Enable tracing for EventCallback. - void SetEventCallbackEnabled(const CategoryFilter& category_filter, - EventCallback cb); - void SetEventCallbackDisabled(); - - // Flush all collected events to the given output callback. The callback will - // be called one or more times either synchronously or asynchronously from - // the current thread with IPC-bite-size chunks. The string format is - // undefined. Use TraceResultBuffer to convert one or more trace strings to - // JSON. The callback can be null if the caller doesn't want any data. - // Due to the implementation of thread-local buffers, flush can't be - // done when tracing is enabled. If called when tracing is enabled, the - // callback will be called directly with (empty_string, false) to indicate - // the end of this unsuccessful flush. - typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&, - bool has_more_events)> OutputCallback; - void Flush(const OutputCallback& cb); - void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback); - - // Called by TRACE_EVENT* macros, don't call this directly. - // The name parameter is a category group for example: - // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") - static const unsigned char* GetCategoryGroupEnabled(const char* name); - static const char* GetCategoryGroupName( - const unsigned char* category_group_enabled); - - // Called by TRACE_EVENT* macros, don't call this directly. - // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied - // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. - TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - const scoped_refptr<ConvertableToTraceFormat>* convertable_values, - unsigned char flags); - TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int thread_id, - const TimeTicks& timestamp, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - const scoped_refptr<ConvertableToTraceFormat>* convertable_values, - unsigned char flags); - static void AddTraceEventEtw(char phase, - const char* category_group, - const void* id, - const char* extra); - static void AddTraceEventEtw(char phase, - const char* category_group, - const void* id, - const std::string& extra); - - void UpdateTraceEventDuration(const unsigned char* category_group_enabled, - const char* name, - TraceEventHandle handle); - - // For every matching event, the callback will be called. - typedef base::Callback<void()> WatchEventCallback; - void SetWatchEvent(const std::string& category_name, - const std::string& event_name, - const WatchEventCallback& callback); - // Cancel the watch event. If tracing is enabled, this may race with the - // watch event notification firing. - void CancelWatchEvent(); - - int process_id() const { return process_id_; } - - // Exposed for unittesting: - - void WaitSamplingEventForTesting(); - - // Allows deleting our singleton instance. - static void DeleteForTesting(); - - // Allow tests to inspect TraceEvents. - TraceEvent* GetEventByHandle(TraceEventHandle handle); - - void SetProcessID(int process_id); - - // Process sort indices, if set, override the order of a process will appear - // relative to other processes in the trace viewer. Processes are sorted first - // on their sort index, ascending, then by their name, and then tid. - void SetProcessSortIndex(int sort_index); - - // Sets the name of the process. - void SetProcessName(const std::string& process_name); - - // Processes can have labels in addition to their names. Use labels, for - // instance, to list out the web page titles that a process is handling. - void UpdateProcessLabel(int label_id, const std::string& current_label); - void RemoveProcessLabel(int label_id); - - // Thread sort indices, if set, override the order of a thread will appear - // within its process in the trace viewer. Threads are sorted first on their - // sort index, ascending, then by their name, and then tid. - void SetThreadSortIndex(PlatformThreadId , int sort_index); - - // Allow setting an offset between the current TimeTicks time and the time - // that should be reported. - void SetTimeOffset(TimeDelta offset); - - size_t GetObserverCountForTest() const; - - // Call this method if the current thread may block the message loop to - // prevent the thread from using the thread-local buffer because the thread - // may not handle the flush request in time causing lost of unflushed events. - void SetCurrentThreadBlocksMessageLoop(); - - private: - typedef unsigned int InternalTraceOptions; - - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferGetReturnChunk); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferHalfIteration); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferRingBufferFullIteration); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceBufferVectorReportFull); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - ConvertTraceOptionsToInternalOptions); - FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, - TraceRecordAsMuchAsPossibleMode); - - // This allows constructor and destructor to be private and usable only - // by the Singleton class. - friend struct DefaultSingletonTraits<TraceLog>; - - // Enable/disable each category group based on the current mode_, - // category_filter_, event_callback_ and event_callback_category_filter_. - // Enable the category group in the enabled mode if category_filter_ matches - // the category group, or event_callback_ is not null and - // event_callback_category_filter_ matches the category group. - void UpdateCategoryGroupEnabledFlags(); - void UpdateCategoryGroupEnabledFlag(size_t category_index); - - // Configure synthetic delays based on the values set in the current - // category filter. - void UpdateSyntheticDelaysFromCategoryFilter(); - - InternalTraceOptions GetInternalOptionsFromTraceOptions( - const TraceOptions& options); - - class ThreadLocalEventBuffer; - class OptionalAutoLock; - - TraceLog(); - ~TraceLog(); - const unsigned char* GetCategoryGroupEnabledInternal(const char* name); - void AddMetadataEventsWhileLocked(); - - InternalTraceOptions trace_options() const { - return static_cast<InternalTraceOptions>( - subtle::NoBarrier_Load(&trace_options_)); - } - - TraceBuffer* trace_buffer() const { return logged_events_.get(); } - TraceBuffer* CreateTraceBuffer(); - TraceBuffer* CreateTraceBufferVectorOfSize(size_t max_chunks); - - std::string EventToConsoleMessage(unsigned char phase, - const TimeTicks& timestamp, - TraceEvent* trace_event); - - TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle, - bool check_buffer_is_full); - void CheckIfBufferIsFullWhileLocked(); - void SetDisabledWhileLocked(); - - TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, - OptionalAutoLock* lock); - - // |generation| is used in the following callbacks to check if the callback - // is called for the flush of the current |logged_events_|. - void FlushCurrentThread(int generation); - void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events, - const TraceLog::OutputCallback& flush_output_callback); - void FinishFlush(int generation); - void OnFlushTimeout(int generation); - - int generation() const { - return static_cast<int>(subtle::NoBarrier_Load(&generation_)); - } - bool CheckGeneration(int generation) const { - return generation == this->generation(); - } - void UseNextTraceBuffer(); - - TimeTicks OffsetNow() const { - return OffsetTimestamp(TimeTicks::NowFromSystemTraceTime()); - } - TimeTicks OffsetTimestamp(const TimeTicks& timestamp) const { - return timestamp - time_offset_; - } - - // Internal representation of trace options since we store the currently used - // trace option as an AtomicWord. - static const InternalTraceOptions kInternalNone; - static const InternalTraceOptions kInternalRecordUntilFull; - static const InternalTraceOptions kInternalRecordContinuously; - static const InternalTraceOptions kInternalEchoToConsole; - static const InternalTraceOptions kInternalEnableSampling; - static const InternalTraceOptions kInternalRecordAsMuchAsPossible; - - // This lock protects TraceLog member accesses (except for members protected - // by thread_info_lock_) from arbitrary threads. - mutable Lock lock_; - // This lock protects accesses to thread_names_, thread_event_start_times_ - // and thread_colors_. - Lock thread_info_lock_; - Mode mode_; - int num_traces_recorded_; - scoped_ptr<TraceBuffer> logged_events_; - subtle::AtomicWord /* EventCallback */ event_callback_; - bool dispatching_to_observer_list_; - std::vector<EnabledStateObserver*> enabled_state_observer_list_; - - std::string process_name_; - base::hash_map<int, std::string> process_labels_; - int process_sort_index_; - base::hash_map<int, int> thread_sort_indices_; - base::hash_map<int, std::string> thread_names_; - - // The following two maps are used only when ECHO_TO_CONSOLE. - base::hash_map<int, std::stack<TimeTicks> > thread_event_start_times_; - base::hash_map<std::string, int> thread_colors_; - - TimeTicks buffer_limit_reached_timestamp_; - - // XORed with TraceID to make it unlikely to collide with other processes. - unsigned long long process_id_hash_; - - int process_id_; - - TimeDelta time_offset_; - - // Allow tests to wake up when certain events occur. - WatchEventCallback watch_event_callback_; - subtle::AtomicWord /* const unsigned char* */ watch_category_; - std::string watch_event_name_; - - subtle::AtomicWord /* Options */ trace_options_; - - // Sampling thread handles. - scoped_ptr<TraceSamplingThread> sampling_thread_; - PlatformThreadHandle sampling_thread_handle_; - - CategoryFilter category_filter_; - CategoryFilter event_callback_category_filter_; - - ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_; - ThreadLocalBoolean thread_blocks_message_loop_; - ThreadLocalBoolean thread_is_in_trace_event_; - - // Contains the message loops of threads that have had at least one event - // added into the local event buffer. Not using MessageLoopProxy because we - // need to know the life time of the message loops. - hash_set<MessageLoop*> thread_message_loops_; - - // For events which can't be added into the thread local buffer, e.g. events - // from threads without a message loop. - scoped_ptr<TraceBufferChunk> thread_shared_chunk_; - size_t thread_shared_chunk_index_; - - // Set when asynchronous Flush is in progress. - OutputCallback flush_output_callback_; - scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_; - subtle::AtomicWord generation_; - - DISALLOW_COPY_AND_ASSIGN(TraceLog); -}; - -} // namespace debug -} // namespace base +#include "base/trace_event/trace_event_impl.h" #endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_ diff --git a/base/debug/trace_event_synthetic_delay.h b/base/debug/trace_event_synthetic_delay.h index 06d6cde..1f1eafb 100644 --- a/base/debug/trace_event_synthetic_delay.h +++ b/base/debug/trace_event_synthetic_delay.h @@ -2,165 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// The synthetic delay framework makes it possible to dynamically inject -// arbitrary delays into into different parts of the codebase. This can be used, -// for instance, for testing various task scheduling algorithms. -// -// The delays are specified in terms of a target duration for a given block of -// code. If the code executes faster than the duration, the thread is made to -// sleep until the deadline is met. -// -// Code can be instrumented for delays with two sets of macros. First, for -// delays that should apply within a scope, use the following macro: -// -// TRACE_EVENT_SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap"); -// -// For delaying operations that span multiple scopes, use: -// -// TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.Scheduler.BeginMainFrame"); -// ... -// TRACE_EVENT_SYNTHETIC_DELAY_END("cc.Scheduler.BeginMainFrame"); -// -// Here BEGIN establishes the start time for the delay and END executes the -// delay based on the remaining time. If BEGIN is called multiple times in a -// row, END should be called a corresponding number of times. Only the last -// call to END will have an effect. -// -// Note that a single delay may begin on one thread and end on another. This -// implies that a single delay cannot not be applied in several threads at once. +// In the process of moving the trace event files. Right now the headers +// are being forwarded. In next CLs the change will get completed +// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032 #ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ #define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ -#include "base/atomicops.h" -#include "base/debug/trace_event.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" +#include "base/trace_event/trace_event_synthetic_delay.h" -// Apply a named delay in the current scope. -#define TRACE_EVENT_SYNTHETIC_DELAY(name) \ - static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \ - trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \ - name, &INTERNAL_TRACE_EVENT_UID(impl_ptr)); - -// Begin a named delay, establishing its timing start point. May be called -// multiple times as long as the calls to TRACE_EVENT_SYNTHETIC_DELAY_END are -// balanced. Only the first call records the timing start point. -#define TRACE_EVENT_SYNTHETIC_DELAY_BEGIN(name) \ - do { \ - static base::subtle::AtomicWord impl_ptr = 0; \ - trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Begin(); \ - } while (false) - -// End a named delay. The delay is applied only if this call matches the -// first corresponding call to TRACE_EVENT_SYNTHETIC_DELAY_BEGIN with the -// same delay. -#define TRACE_EVENT_SYNTHETIC_DELAY_END(name) \ - do { \ - static base::subtle::AtomicWord impl_ptr = 0; \ - trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->End(); \ - } while (false) - -template <typename Type> -struct DefaultSingletonTraits; - -namespace base { -namespace debug { - -// Time source for computing delay durations. Used for testing. -class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock { - public: - TraceEventSyntheticDelayClock(); - virtual ~TraceEventSyntheticDelayClock(); - virtual base::TimeTicks Now() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock); -}; - -// Single delay point instance. -class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelay { - public: - enum Mode { - STATIC, // Apply the configured delay every time. - ONE_SHOT, // Apply the configured delay just once. - ALTERNATING // Apply the configured delay every other time. - }; - - // Returns an existing named delay instance or creates a new one with |name|. - static TraceEventSyntheticDelay* Lookup(const std::string& name); - - void SetTargetDuration(TimeDelta target_duration); - void SetMode(Mode mode); - void SetClock(TraceEventSyntheticDelayClock* clock); - - // Begin the delay, establishing its timing start point. May be called - // multiple times as long as the calls to End() are balanced. Only the first - // call records the timing start point. - void Begin(); - - // End the delay. The delay is applied only if this call matches the first - // corresponding call to Begin() with the same delay. - void End(); - - // Begin a parallel instance of the delay. Several parallel instances may be - // active simultaneously and will complete independently. The computed end - // time for the delay is stored in |out_end_time|, which should later be - // passed to EndParallel(). - void BeginParallel(base::TimeTicks* out_end_time); - - // End a previously started parallel delay. |end_time| is the delay end point - // computed by BeginParallel(). - void EndParallel(base::TimeTicks end_time); - - private: - TraceEventSyntheticDelay(); - ~TraceEventSyntheticDelay(); - friend class TraceEventSyntheticDelayRegistry; - - void Initialize(const std::string& name, - TraceEventSyntheticDelayClock* clock); - base::TimeTicks CalculateEndTimeLocked(base::TimeTicks start_time); - void ApplyDelay(base::TimeTicks end_time); - - Lock lock_; - Mode mode_; - std::string name_; - int begin_count_; - int trigger_count_; - base::TimeTicks end_time_; - base::TimeDelta target_duration_; - TraceEventSyntheticDelayClock* clock_; - - DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay); -}; - -// Set the target durations of all registered synthetic delay points to zero. -TRACE_EVENT_API_CLASS_EXPORT void ResetTraceEventSyntheticDelays(); - -} // namespace debug -} // namespace base - -namespace trace_event_internal { - -// Helper class for scoped delays. Do not use directly. -class TRACE_EVENT_API_CLASS_EXPORT ScopedSyntheticDelay { - public: - explicit ScopedSyntheticDelay(const char* name, - base::subtle::AtomicWord* impl_ptr); - ~ScopedSyntheticDelay(); - - private: - base::debug::TraceEventSyntheticDelay* delay_impl_; - base::TimeTicks end_time_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); -}; - -// Helper for registering delays. Do not use directly. -TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay* - GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr); - -} // namespace trace_event_internal - -#endif /* BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ +#endif // BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_ diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h index c85ca92..473e174 100644 --- a/base/debug/trace_event_win.h +++ b/base/debug/trace_event_win.h @@ -2,124 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file contains the Windows-specific declarations for trace_event.h. +// In the process of moving the trace event files. Right now the headers +// are being forwarded. In next CLs the change will get completed +// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032 + #ifndef BASE_DEBUG_TRACE_EVENT_WIN_H_ #define BASE_DEBUG_TRACE_EVENT_WIN_H_ -#include <string> - -#include "base/base_export.h" -#include "base/debug/trace_event.h" -#include "base/win/event_trace_provider.h" - -// Fwd. -template <typename Type> -struct StaticMemorySingletonTraits; - -namespace base { -namespace debug { - -// This EtwTraceProvider subclass implements ETW logging -// for the macros above on Windows. -class BASE_EXPORT TraceEventETWProvider : public base::win::EtwTraceProvider { - public: - static const size_t kUseStrlen = static_cast<size_t>(-1); - - // Start logging trace events. - // This is a noop in this implementation. - static bool StartTracing(); - - // Trace begin/end/instant events, this is the bottleneck implementation - // all the others defer to. - // Allowing the use of std::string for name or extra is a convenience, - // whereas passing name or extra as a const char* avoids the construction - // of temporary std::string instances. - // If kUseStrlen is passed for name_len or extra_len, the strlen of the string - // will be used for length. - static void Trace(const char* name, - size_t name_len, - char type, - const void* id, - const char* extra, - size_t extra_len); - - // Allows passing extra as a std::string for convenience. - static void Trace(const char* name, - char type, - const void* id, - const std::string& extra) { - return Trace(name, kUseStrlen, type, id, extra.c_str(), extra.length()); - } - - // Allows passing extra as a const char* to avoid constructing temporary - // std::string instances where not needed. - static void Trace(const char* name, - char type, - const void* id, - const char* extra) { - return Trace(name, kUseStrlen, type, id, extra, kUseStrlen); - } - - // Retrieves the singleton. - // Note that this may return NULL post-AtExit processing. - static TraceEventETWProvider* GetInstance(); - - // Returns true iff tracing is turned on. - bool IsTracing() { - return enable_level() >= TRACE_LEVEL_INFORMATION; - } - - // Emit a trace of type |type| containing |name|, |id|, and |extra|. - // Note: |name| and |extra| must be NULL, or a zero-terminated string of - // length |name_len| or |extra_len| respectively. - // Note: if name_len or extra_len are kUseStrlen, the length of the - // corresponding string will be used. - void TraceEvent(const char* name, - size_t name_len, - char type, - const void* id, - const char* extra, - size_t extra_len); - - // Exposed for unittesting only, allows resurrecting our - // singleton instance post-AtExit processing. - static void Resurrect(); - - private: - // Ensure only the provider can construct us. - friend struct StaticMemorySingletonTraits<TraceEventETWProvider>; - TraceEventETWProvider(); - - DISALLOW_COPY_AND_ASSIGN(TraceEventETWProvider); -}; - -// The ETW trace provider GUID. -BASE_EXPORT extern const GUID kChromeTraceProviderName; - -// The ETW event class GUID for 32 bit events. -BASE_EXPORT extern const GUID kTraceEventClass32; - -// The ETW event class GUID for 64 bit events. -BASE_EXPORT extern const GUID kTraceEventClass64; - -// The ETW event types, IDs 0x00-0x09 are reserved, so start at 0x10. -const base::win::EtwEventType kTraceEventTypeBegin = 0x10; -const base::win::EtwEventType kTraceEventTypeEnd = 0x11; -const base::win::EtwEventType kTraceEventTypeInstant = 0x12; - -// If this flag is set in enable flags -enum TraceEventETWFlags { - CAPTURE_STACK_TRACE = 0x0001, -}; - -// The event format consists of: -// The "name" string as a zero-terminated ASCII string. -// The id pointer in the machine bitness. -// The "extra" string as a zero-terminated ASCII string. -// Optionally the stack trace, consisting of a DWORD "depth", followed -// by an array of void* (machine bitness) of length "depth". - -} // namespace debug -} // namespace base +#include "base/trace_event/trace_event_win.h" #endif // BASE_DEBUG_TRACE_EVENT_WIN_H_ diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS new file mode 100644 index 0000000..3932776 --- /dev/null +++ b/base/trace_event/OWNERS @@ -0,0 +1,3 @@ +nduca@chromium.org +dsinclair@chromium.org +per-file trace_event_android.cc=wangxianzhu@chromium.org diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h new file mode 100644 index 0000000..7f73071 --- /dev/null +++ b/base/trace_event/trace_event.h @@ -0,0 +1,1589 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This header file defines the set of trace_event macros without specifying +// how the events actually get collected and stored. If you need to expose trace +// events to some other universe, you can copy-and-paste this file as well as +// trace_event.h, modifying the macros contained there as necessary for the +// target platform. The end result is that multiple libraries can funnel events +// through to a shared trace event collector. + +// Trace events are for tracking application performance and resource usage. +// Macros are provided to track: +// Begin and end of function calls +// Counters +// +// Events are issued against categories. Whereas LOG's +// categories are statically defined, TRACE categories are created +// implicitly with a string. For example: +// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent", +// TRACE_EVENT_SCOPE_THREAD) +// +// It is often the case that one trace may belong in multiple categories at the +// same time. The first argument to the trace can be a comma-separated list of +// categories, forming a category group, like: +// +// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD) +// +// We can enable/disable tracing of OnMouseOver by enabling/disabling either +// category. +// +// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: +// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") +// doSomethingCostly() +// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") +// Note: our tools can't always determine the correct BEGIN/END pairs unless +// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you +// need them to be in separate scopes. +// +// A common use case is to trace entire function scopes. This +// issues a trace BEGIN and END automatically: +// void doSomethingCostly() { +// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); +// ... +// } +// +// Additional parameters can be associated with an event: +// void doSomethingCostly2(int howMuch) { +// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", +// "howMuch", howMuch); +// ... +// } +// +// The trace system will automatically add to this information the +// current process id, thread id, and a timestamp in microseconds. +// +// To trace an asynchronous procedure such as an IPC send/receive, use +// ASYNC_BEGIN and ASYNC_END: +// [single threaded sender code] +// static int send_count = 0; +// ++send_count; +// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// Send(new MyMessage(send_count)); +// [receive code] +// void OnMyMessage(send_count) { +// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// } +// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. +// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. +// Pointers can be used for the ID parameter, and they will be mangled +// internally so that the same pointer on two different processes will not +// match. For example: +// class MyTracedClass { +// public: +// MyTracedClass() { +// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// } +// ~MyTracedClass() { +// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// } +// } +// +// Trace event also supports counters, which is a way to track a quantity +// as it varies over time. Counters are created with the following macro: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); +// +// Counters are process-specific. The macro itself can be issued from any +// thread, however. +// +// Sometimes, you want to track two counters at once. You can do this with two +// counter macros: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); +// Or you can do it with a combined macro: +// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", +// "bytesPinned", g_myCounterValue[0], +// "bytesAllocated", g_myCounterValue[1]); +// This indicates to the tracing UI that these counters should be displayed +// in a single graph, as a summed area chart. +// +// Since counters are in a global namespace, you may want to disambiguate with a +// unique ID, by using the TRACE_COUNTER_ID* variations. +// +// By default, trace collection is compiled in, but turned off at runtime. +// Collecting trace data is the responsibility of the embedding +// application. In Chrome's case, navigating to about:tracing will turn on +// tracing and display data collected across all active processes. +// +// +// Memory scoping note: +// Tracing copies the pointers, not the string content, of the strings passed +// in for category_group, name, and arg_names. Thus, the following code will +// cause problems: +// char* str = strdup("importantName"); +// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! +// free(str); // Trace system now has dangling pointer +// +// To avoid this issue with the |name| and |arg_name| parameters, use the +// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. +// Notes: The category must always be in a long-lived char* (i.e. static const). +// The |arg_values|, when used, are always deep copied with the _COPY +// macros. +// +// When are string argument values copied: +// const char* arg_values are only referenced by default: +// TRACE_EVENT1("category", "name", +// "arg1", "literal string is only referenced"); +// Use TRACE_STR_COPY to force copying of a const char*: +// TRACE_EVENT1("category", "name", +// "arg1", TRACE_STR_COPY("string will be copied")); +// std::string arg_values are always copied: +// TRACE_EVENT1("category", "name", +// "arg1", std::string("string will be copied")); +// +// +// Convertable notes: +// Converting a large data type to a string can be costly. To help with this, +// the trace framework provides an interface ConvertableToTraceFormat. If you +// inherit from it and implement the AppendAsTraceFormat method the trace +// framework will call back to your object to convert a trace output time. This +// means, if the category for the event is disabled, the conversion will not +// happen. +// +// class MyData : public base::debug::ConvertableToTraceFormat { +// public: +// MyData() {} +// virtual void AppendAsTraceFormat(std::string* out) const override { +// out->append("{\"foo\":1}"); +// } +// private: +// virtual ~MyData() {} +// DISALLOW_COPY_AND_ASSIGN(MyData); +// }; +// +// TRACE_EVENT1("foo", "bar", "data", +// scoped_refptr<ConvertableToTraceFormat>(new MyData())); +// +// The trace framework will take ownership if the passed pointer and it will +// be free'd when the trace buffer is flushed. +// +// Note, we only do the conversion when the buffer is flushed, so the provided +// data object should not be modified after it's passed to the trace framework. +// +// +// Thread Safety: +// A thread safe singleton and mutex are used for thread safety. Category +// enabled flags are used to limit the performance impact when the system +// is not enabled. +// +// TRACE_EVENT macros first cache a pointer to a category. The categories are +// statically allocated and safe at all times, even after exit. Fetching a +// category is protected by the TraceLog::lock_. Multiple threads initializing +// the static variable is safe, as they will be serialized by the lock and +// multiple calls will return the same pointer to the category. +// +// Then the category_group_enabled flag is checked. This is a unsigned char, and +// not intended to be multithread safe. It optimizes access to AddTraceEvent +// which is threadsafe internally via TraceLog::lock_. The enabled flag may +// cause some threads to incorrectly call or skip calling AddTraceEvent near +// the time of the system being enabled or disabled. This is acceptable as +// we tolerate some data loss while the system is being enabled/disabled and +// because AddTraceEvent is threadsafe internally and checks the enabled state +// again under lock. +// +// Without the use of these static category pointers and enabled flags all +// trace points would carry a significant performance cost of acquiring a lock +// and resolving the category. + +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_H_ + +#include <string> + +#include "base/atomicops.h" +#include "base/time/time.h" +#include "base/trace_event/trace_event_impl.h" +#include "base/trace_event/trace_event_memory.h" +#include "base/trace_event/trace_event_system_stats_monitor.h" +#include "build/build_config.h" + +// By default, const char* argument values are assumed to have long-lived scope +// and will not be copied. Use this macro to force a const char* to be copied. +#define TRACE_STR_COPY(str) \ + trace_event_internal::TraceStringWithCopy(str) + +// This will mark the trace event as disabled by default. The user will need +// to explicitly enable the event. +#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name + +// By default, uint64 ID argument values are not mangled with the Process ID in +// TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling. +#define TRACE_ID_MANGLE(id) \ + trace_event_internal::TraceID::ForceMangle(id) + +// By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC +// macros. Use this macro to prevent Process ID mangling. +#define TRACE_ID_DONT_MANGLE(id) \ + trace_event_internal::TraceID::DontMangle(id) + +// Records a pair of begin and end events called "name" for the current +// scope, with 0, 1 or 2 associated arguments. If the category is not +// enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT0(category_group, name) \ + INTERNAL_TRACE_MEMORY(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name) +#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_MEMORY(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val) +#define TRACE_EVENT2( \ + category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_MEMORY(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED( \ + category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) + +// Records events like TRACE_EVENT2 but uses |memory_tag| for memory tracing. +// Use this where |name| is too generic to accurately aggregate allocations. +#define TRACE_EVENT_WITH_MEMORY_TAG2( \ + category, name, memory_tag, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_MEMORY(category, memory_tag) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED( \ + category, name, arg1_name, arg1_val, arg2_name, arg2_val) + +// UNSHIPPED_TRACE_EVENT* are like TRACE_EVENT* except that they are not +// included in official builds. + +#if OFFICIAL_BUILD +#undef TRACING_IS_OFFICIAL_BUILD +#define TRACING_IS_OFFICIAL_BUILD 1 +#elif !defined(TRACING_IS_OFFICIAL_BUILD) +#define TRACING_IS_OFFICIAL_BUILD 0 +#endif + +#if TRACING_IS_OFFICIAL_BUILD +#define UNSHIPPED_TRACE_EVENT0(category_group, name) (void)0 +#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ + (void)0 +#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) (void)0 +#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) (void)0 +#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \ + arg1_name, arg1_val) (void)0 +#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \ + arg1_name, arg1_val, \ + arg2_name, arg2_val) (void)0 +#else +#define UNSHIPPED_TRACE_EVENT0(category_group, name) \ + TRACE_EVENT0(category_group, name) +#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ + TRACE_EVENT1(category_group, name, arg1_name, arg1_val) +#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) +#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) \ + TRACE_EVENT_INSTANT0(category_group, name, scope) +#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \ + arg1_name, arg1_val) \ + TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) +#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \ + arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#endif + +// Records a single event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_INSTANT0(category_group, name, scope) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_NONE | scope) +#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_NONE | scope, \ + arg1_name, arg1_val) +#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_NONE | scope, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_COPY | scope) +#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_COPY | scope, arg1_name, \ + arg1_val) +#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, \ + arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category_group, name, TRACE_EVENT_FLAG_COPY | scope, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Sets the current sample state to the given category and name (both must be +// constant strings). These states are intended for a sampling profiler. +// Implementation note: we store category and name together because we don't +// want the inconsistency/expense of storing two pointers. +// |thread_bucket| is [0..2] and is used to statically isolate samples in one +// thread from others. +#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET( \ + bucket_number, category, name) \ + trace_event_internal:: \ + TraceEventSamplingStateScope<bucket_number>::Set(category "\0" name) + +// Returns a current sampling state of the given bucket. +#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ + trace_event_internal::TraceEventSamplingStateScope<bucket_number>::Current() + +// Creates a scope of a sampling state of the given bucket. +// +// { // The sampling state is set within this scope. +// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); +// ...; +// } +#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET( \ + bucket_number, category, name) \ + trace_event_internal::TraceEventSamplingStateScope<bucket_number> \ + traceEventSamplingScope(category "\0" name); + +// Syntactic sugars for the sampling tracing in the main thread. +#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_GET_SAMPLING_STATE() \ + TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) +#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) + + +// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_BEGIN0(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_BEGIN0(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_BEGIN1(category_group, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Similar to TRACE_EVENT_BEGINx but with a custom |at| timestamp provided. +// - |id| is used to match the _BEGIN event with the _END event. +// Events are considered to match if their category_group, name and id values +// all match. |id| must either be a pointer or an integer value up to 64 bits. +// If it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, \ + name, id, thread_id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \ + category_group, name, id, thread_id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( \ + category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) + +// Records a single END event for "name" immediately. If the category +// is not enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_END0(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_END0(category_group, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_END1(category_group, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Similar to TRACE_EVENT_ENDx but with a custom |at| timestamp provided. +// - |id| is used to match the _BEGIN event with the _END event. +// Events are considered to match if their category_group, name and id values +// all match. |id| must either be a pointer or an integer value up to 64 bits. +// If it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, \ + name, id, thread_id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \ + category_group, name, id, thread_id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( \ + category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \ + timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER1(category_group, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast<int>(value)) +#define TRACE_COPY_COUNTER1(category_group, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast<int>(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) +#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID1(category_group, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast<int>(value)) +#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast<int>(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) +#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \ + value1_val, value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) + +// ASYNC_STEP_* APIs should be only used by legacy code. New code should +// consider using NESTABLE_ASYNC_* APIs to describe substeps within an async +// event. +// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC +// events are considered to match if their category_group, name and id values +// all match. |id| must either be a pointer or an integer value up to 64 bits. +// If it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +// +// An asynchronous operation can consist of multiple phases. The first phase is +// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the +// ASYNC_STEP_INTO or ASYNC_STEP_PAST macros. The ASYNC_STEP_INTO macro will +// annotate the block following the call. The ASYNC_STEP_PAST macro will +// annotate the block prior to the call. Note that any particular event must use +// only STEP_INTO or STEP_PAST macros; they can not mix and match. When the +// operation completes, call ASYNC_END. +// +// An ASYNC trace typically occurs on a single thread (if not, they will only be +// drawn on the thread defined in the ASYNC_BEGIN event), but all events in that +// operation must use the same |name| and |id|. Each step can have its own +// args. +#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ + arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \ + arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Similar to TRACE_EVENT_ASYNC_BEGINx but with a custom |at| timestamp +// provided. +#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, \ + name, id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \ + static_cast<int>(base::PlatformThread::CurrentId()), \ + timestamp, TRACE_EVENT_FLAG_NONE) + +// Records a single ASYNC_STEP_INTO event for |step| immediately. If the +// category is not enabled, then this does nothing. The |name| and |id| must +// match the ASYNC_BEGIN event above. The |step| param identifies this step +// within the async event. This should be called at the beginning of the next +// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any +// ASYNC_STEP_PAST events. +#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) + +// Records a single ASYNC_STEP_PAST event for |step| immediately. If the +// category is not enabled, then this does nothing. The |name| and |id| must +// match the ASYNC_BEGIN event above. The |step| param identifies this step +// within the async event. This should be called at the beginning of the next +// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any +// ASYNC_STEP_INTO events. +#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) + +// Records a single ASYNC_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \ + arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Similar to TRACE_EVENT_ASYNC_ENDx but with a custom |at| timestamp provided. +#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, \ + name, id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \ + static_cast<int>(base::PlatformThread::CurrentId()), \ + timestamp, TRACE_EVENT_FLAG_NONE) + +// NESTABLE_ASYNC_* APIs are used to describe an async operation, which can +// be nested within a NESTABLE_ASYNC event and/or have inner NESTABLE_ASYNC +// events. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the NESTABLE_ASYNC_BEGIN event with the +// NESTABLE_ASYNC_END event. Events are considered to match if their +// category_group, name and id values all match. |id| must either be a +// pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on two +// different processes will not collide. +// +// Unmatched NESTABLE_ASYNC_END event will be parsed as an instant event, +// and unmatched NESTABLE_ASYNC_BEGIN event will be parsed as an event that +// ends at the last NESTABLE_ASYNC_END event of that |id|. + +// Records a single NESTABLE_ASYNC_BEGIN event called "name" immediately, with 2 +// associated arguments. If the category is not enabled, then this does nothing. +#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +// Records a single NESTABLE_ASYNC_END event called "name" immediately, with 2 +// associated arguments. If the category is not enabled, then this does nothing. +#define TRACE_EVENT_NESTABLE_ASYNC_END2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +// Records a single NESTABLE_ASYNC_INSTANT event called "name" immediately, +// with 2 associated arguments. If the category is not enabled, then this +// does nothing. +#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(category_group, name, id, \ + arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW +// events are considered to match if their category_group, name and id values +// all match. |id| must either be a pointer or an integer value up to 64 bits. +// If it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +// FLOW events are different from ASYNC events in how they are drawn by the +// tracing UI. A FLOW defines asynchronous data flow, such as posting a task +// (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be +// drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar +// to ASYNC, a FLOW can consist of multiple phases. The first phase is defined +// by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP +// macros. When the operation completes, call FLOW_END. An async operation can +// span threads and processes, but all events in that operation must use the +// same |name| and |id|. Each event can have its own args. +#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \ + arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Records a single FLOW_STEP event for |step| immediately. If the category +// is not enabled, then this does nothing. The |name| and |id| must match the +// FLOW_BEGIN event above. The |step| param identifies this step within the +// async event. This should be called at the beginning of the next phase of an +// asynchronous operation. +#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step) +#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ + arg1_name, arg1_val) + +// Records a single FLOW_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_FLOW_END0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name, \ + arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \ + category_group, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Macros to track the life time and value of arbitrary client objects. +// See also TraceTrackableObject. +#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \ + category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE) + +#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, \ + category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE,\ + "snapshot", snapshot) + +#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \ + category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE) + +#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ + UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ + (base::debug::TraceLog::ENABLED_FOR_RECORDING | \ + base::debug::TraceLog::ENABLED_FOR_EVENT_CALLBACK)) + +// Macro to efficiently determine if a given category group is enabled. +#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + *ret = true; \ + } else { \ + *ret = false; \ + } \ + } while (0) + +// Macro to efficiently determine, through polling, if a new trace has begun. +#define TRACE_EVENT_IS_NEW_TRACE(ret) \ + do { \ + static int INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = 0; \ + int num_traces_recorded = TRACE_EVENT_API_GET_NUM_TRACES_RECORDED(); \ + if (num_traces_recorded != -1 && \ + num_traces_recorded != \ + INTERNAL_TRACE_EVENT_UID(lastRecordingNumber)) { \ + INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = \ + num_traces_recorded; \ + *ret = true; \ + } else { \ + *ret = false; \ + } \ + } while (0) + +//////////////////////////////////////////////////////////////////////////////// +// Implementation specific tracing API definitions. + +// Get a pointer to the enabled state of the given trace category. Only +// long-lived literal strings should be given as the category group. The +// returned pointer can be held permanently in a local static for example. If +// the unsigned char is non-zero, tracing is enabled. If tracing is enabled, +// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled +// between the load of the tracing state and the call to +// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out +// for best performance when tracing is disabled. +// const unsigned char* +// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group) +#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ + base::debug::TraceLog::GetCategoryGroupEnabled + +// Get the number of times traces have been recorded. This is used to implement +// the TRACE_EVENT_IS_NEW_TRACE facility. +// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED() +#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \ + base::debug::TraceLog::GetInstance()->GetNumTracesRecorded + +// Add a trace event to the platform tracing system. +// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT( +// char phase, +// const unsigned char* category_group_enabled, +// const char* name, +// unsigned long long id, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// unsigned char flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT \ + base::debug::TraceLog::GetInstance()->AddTraceEvent + +// Add a trace event to the platform tracing system. +// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( +// char phase, +// const unsigned char* category_group_enabled, +// const char* name, +// unsigned long long id, +// int thread_id, +// const TimeTicks& timestamp, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// unsigned char flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \ + base::debug::TraceLog::GetInstance()->AddTraceEventWithThreadIdAndTimestamp + +// Set the duration field of a COMPLETE trace event. +// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( +// const unsigned char* category_group_enabled, +// const char* name, +// base::debug::TraceEventHandle id) +#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ + base::debug::TraceLog::GetInstance()->UpdateTraceEventDuration + +// Defines atomic operations used internally by the tracing system. +#define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord +#define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var)) +#define TRACE_EVENT_API_ATOMIC_STORE(var, value) \ + base::subtle::NoBarrier_Store(&(var), (value)) + +// Defines visibility for classes in trace_event.h +#define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT + +// The thread buckets for the sampling profiler. +TRACE_EVENT_API_CLASS_EXPORT extern \ + TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3]; + +#define TRACE_EVENT_API_THREAD_BUCKET(thread_bucket) \ + g_trace_state[thread_bucket] + +//////////////////////////////////////////////////////////////////////////////// + +// Implementation detail: trace event macros create temporary variables +// to keep instrumentation overhead low. These macros give each temporary +// variable a unique name based on the line number to prevent name collisions. +#define INTERNAL_TRACE_EVENT_UID3(a,b) \ + trace_event_unique_##a##b +#define INTERNAL_TRACE_EVENT_UID2(a,b) \ + INTERNAL_TRACE_EVENT_UID3(a,b) +#define INTERNAL_TRACE_EVENT_UID(name_prefix) \ + INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) + +// Implementation detail: internal macro to create static category. +// No barriers are needed, because this code is designed to operate safely +// even when the unsigned char* points to garbage data (which may be the case +// on processors without cache coherency). +#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ + category_group, atomic, category_group_enabled) \ + category_group_enabled = \ + reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( \ + atomic)); \ + if (UNLIKELY(!category_group_enabled)) { \ + category_group_enabled = \ + TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \ + TRACE_EVENT_API_ATOMIC_STORE(atomic, \ + reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \ + category_group_enabled)); \ + } + +#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \ + static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \ + const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \ + INTERNAL_TRACE_EVENT_UID(atomic), \ + INTERNAL_TRACE_EVENT_UID(category_group_enabled)); + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + trace_event_internal::AddTraceEvent( \ + phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ + trace_event_internal::kNoEventId, flags, ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add begin +// event if the category is enabled. Also adds the end event when the scope +// ends. +#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + base::debug::TraceEventHandle h = trace_event_internal::AddTraceEvent( \ + TRACE_EVENT_PHASE_COMPLETE, \ + INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ + name, trace_event_internal::kNoEventId, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ + INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ + INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ + } + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \ + flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + trace_event_internal::TraceID trace_event_trace_id( \ + id, &trace_event_flags); \ + trace_event_internal::AddTraceEvent( \ + phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ + name, trace_event_trace_id.data(), trace_event_flags, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(phase, \ + category_group, name, id, thread_id, timestamp, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + trace_event_internal::TraceID trace_event_trace_id( \ + id, &trace_event_flags); \ + trace_event_internal::AddTraceEventWithThreadIdAndTimestamp( \ + phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ + name, trace_event_trace_id.data(), \ + thread_id, base::TimeTicks::FromInternalValue(timestamp), \ + trace_event_flags, ##__VA_ARGS__); \ + } \ + } while (0) + +// Notes regarding the following definitions: +// New values can be added and propagated to third party libraries, but existing +// definitions must never be changed, because third party libraries may use old +// definitions. + +// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. +#define TRACE_EVENT_PHASE_BEGIN ('B') +#define TRACE_EVENT_PHASE_END ('E') +#define TRACE_EVENT_PHASE_COMPLETE ('X') +#define TRACE_EVENT_PHASE_INSTANT ('I') +#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') +#define TRACE_EVENT_PHASE_ASYNC_STEP_INTO ('T') +#define TRACE_EVENT_PHASE_ASYNC_STEP_PAST ('p') +#define TRACE_EVENT_PHASE_ASYNC_END ('F') +#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN ('b') +#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_END ('e') +#define TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT ('n') +#define TRACE_EVENT_PHASE_FLOW_BEGIN ('s') +#define TRACE_EVENT_PHASE_FLOW_STEP ('t') +#define TRACE_EVENT_PHASE_FLOW_END ('f') +#define TRACE_EVENT_PHASE_METADATA ('M') +#define TRACE_EVENT_PHASE_COUNTER ('C') +#define TRACE_EVENT_PHASE_SAMPLE ('P') +#define TRACE_EVENT_PHASE_CREATE_OBJECT ('N') +#define TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ('O') +#define TRACE_EVENT_PHASE_DELETE_OBJECT ('D') + +// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. +#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2)) +#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned char>(1 << 3)) + +#define TRACE_EVENT_FLAG_SCOPE_MASK (static_cast<unsigned char>( \ + TRACE_EVENT_FLAG_SCOPE_OFFSET | (TRACE_EVENT_FLAG_SCOPE_OFFSET << 1))) + +// Type values for identifying types in the TraceValue union. +#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) +#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) +#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) +#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) +#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) +#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) +#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) +#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8)) + +// Enum reflecting the scope of an INSTANT event. Must fit within +// TRACE_EVENT_FLAG_SCOPE_MASK. +#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3)) +#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3)) +#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3)) + +#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g') +#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p') +#define TRACE_EVENT_SCOPE_NAME_THREAD ('t') + +namespace trace_event_internal { + +// Specify these values when the corresponding argument of AddTraceEvent is not +// used. +const int kZeroNumArgs = 0; +const unsigned long long kNoEventId = 0; + +// TraceID encapsulates an ID that can either be an integer or pointer. Pointers +// are by default mangled with the Process ID so that they are unlikely to +// collide when the same pointer is used on different processes. +class TraceID { + public: + class DontMangle { + public: + explicit DontMangle(const void* id) + : data_(static_cast<unsigned long long>( + reinterpret_cast<uintptr_t>(id))) {} + explicit DontMangle(unsigned long long id) : data_(id) {} + explicit DontMangle(unsigned long id) : data_(id) {} + explicit DontMangle(unsigned int id) : data_(id) {} + explicit DontMangle(unsigned short id) : data_(id) {} + explicit DontMangle(unsigned char id) : data_(id) {} + explicit DontMangle(long long id) + : data_(static_cast<unsigned long long>(id)) {} + explicit DontMangle(long id) + : data_(static_cast<unsigned long long>(id)) {} + explicit DontMangle(int id) + : data_(static_cast<unsigned long long>(id)) {} + explicit DontMangle(short id) + : data_(static_cast<unsigned long long>(id)) {} + explicit DontMangle(signed char id) + : data_(static_cast<unsigned long long>(id)) {} + unsigned long long data() const { return data_; } + private: + unsigned long long data_; + }; + + class ForceMangle { + public: + explicit ForceMangle(unsigned long long id) : data_(id) {} + explicit ForceMangle(unsigned long id) : data_(id) {} + explicit ForceMangle(unsigned int id) : data_(id) {} + explicit ForceMangle(unsigned short id) : data_(id) {} + explicit ForceMangle(unsigned char id) : data_(id) {} + explicit ForceMangle(long long id) + : data_(static_cast<unsigned long long>(id)) {} + explicit ForceMangle(long id) + : data_(static_cast<unsigned long long>(id)) {} + explicit ForceMangle(int id) + : data_(static_cast<unsigned long long>(id)) {} + explicit ForceMangle(short id) + : data_(static_cast<unsigned long long>(id)) {} + explicit ForceMangle(signed char id) + : data_(static_cast<unsigned long long>(id)) {} + unsigned long long data() const { return data_; } + private: + unsigned long long data_; + }; + TraceID(const void* id, unsigned char* flags) + : data_(static_cast<unsigned long long>( + reinterpret_cast<uintptr_t>(id))) { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } + TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } + TraceID(DontMangle id, unsigned char* flags) : data_(id.data()) { + } + TraceID(unsigned long long id, unsigned char* flags) + : data_(id) { (void)flags; } + TraceID(unsigned long id, unsigned char* flags) + : data_(id) { (void)flags; } + TraceID(unsigned int id, unsigned char* flags) + : data_(id) { (void)flags; } + TraceID(unsigned short id, unsigned char* flags) + : data_(id) { (void)flags; } + TraceID(unsigned char id, unsigned char* flags) + : data_(id) { (void)flags; } + TraceID(long long id, unsigned char* flags) + : data_(static_cast<unsigned long long>(id)) { (void)flags; } + TraceID(long id, unsigned char* flags) + : data_(static_cast<unsigned long long>(id)) { (void)flags; } + TraceID(int id, unsigned char* flags) + : data_(static_cast<unsigned long long>(id)) { (void)flags; } + TraceID(short id, unsigned char* flags) + : data_(static_cast<unsigned long long>(id)) { (void)flags; } + TraceID(signed char id, unsigned char* flags) + : data_(static_cast<unsigned long long>(id)) { (void)flags; } + + unsigned long long data() const { return data_; } + + private: + unsigned long long data_; +}; + +// Simple union to store various types as unsigned long long. +union TraceValueUnion { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; +}; + +// Simple container for const char* that should be copied instead of retained. +class TraceStringWithCopy { + public: + explicit TraceStringWithCopy(const char* str) : str_(str) {} + const char* str() const { return str_; } + private: + const char* str_; +}; + +// Define SetTraceValue for each allowed type. It stores the type and +// value in the return arguments. This allows this API to avoid declaring any +// structures so that it is portable to third_party libraries. +#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ + arg_expression, \ + union_member, \ + value_type_id) \ + static inline void SetTraceValue( \ + actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + TraceValueUnion type_value; \ + type_value.union_member = arg_expression; \ + *type = value_type_id; \ + *value = type_value.as_uint; \ + } +// Simpler form for int types that can be safely casted. +#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ + value_type_id) \ + static inline void SetTraceValue( \ + actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + *type = value_type_id; \ + *value = static_cast<unsigned long long>(arg); \ + } + +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL) +INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double, + TRACE_VALUE_TYPE_DOUBLE) +INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer, + TRACE_VALUE_TYPE_POINTER) +INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string, + TRACE_VALUE_TYPE_STRING) +INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), + as_string, TRACE_VALUE_TYPE_COPY_STRING) + +#undef INTERNAL_DECLARE_SET_TRACE_VALUE +#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT + +// std::string version of SetTraceValue so that trace arguments can be strings. +static inline void SetTraceValue(const std::string& arg, + unsigned char* type, + unsigned long long* value) { + TraceValueUnion type_value; + type_value.as_string = arg.c_str(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = type_value.as_uint; +} + +// base::Time and base::TimeTicks version of SetTraceValue to make it easier to +// trace these types. +static inline void SetTraceValue(const base::Time arg, + unsigned char* type, + unsigned long long* value) { + *type = TRACE_VALUE_TYPE_INT; + *value = arg.ToInternalValue(); +} + +static inline void SetTraceValue(const base::TimeTicks arg, + unsigned char* type, + unsigned long long* value) { + *type = TRACE_VALUE_TYPE_INT; + *value = arg.ToInternalValue(); +} + +// These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template +// functions are defined here instead of in the macro, because the arg_values +// could be temporary objects, such as std::string. In order to store +// pointers to the internal c_str and pass through to the tracing API, +// the arg_values must live throughout these procedures. + +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val) { + const int num_args = 1; + unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE }; + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, &arg1_name, arg_types, NULL, &arg1_val, flags); +} + +template<class ARG1_TYPE> +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const ARG1_TYPE& arg1_val, + const char* arg2_name, + const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE; + + scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2]; + convertable_values[1] = arg2_val; + + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, arg_names, arg_types, arg_values, convertable_values, flags); +} + +template<class ARG2_TYPE> +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE; + arg_values[0] = 0; + SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); + + scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2]; + convertable_values[0] = arg1_val; + + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, arg_names, arg_types, arg_values, convertable_values, flags); +} + +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val, + const char* arg2_name, + const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + unsigned char arg_types[2] = + { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE }; + scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2] = + { arg1_val, arg2_val }; + + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, arg_names, arg_types, NULL, convertable_values, flags); +} + +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags) { + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + kZeroNumArgs, NULL, NULL, NULL, NULL, flags); +} + +static inline base::debug::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + unsigned char flags) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); + return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, + name, id, thread_id, now, flags); +} + +template<class ARG1_TYPE> +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const ARG1_TYPE& arg1_val) { + const int num_args = 1; + unsigned char arg_types[1]; + unsigned long long arg_values[1]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, &arg1_name, arg_types, arg_values, NULL, flags); +} + +template<class ARG1_TYPE> +static inline base::debug::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1_name, + const ARG1_TYPE& arg1_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); + return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, + name, id, thread_id, now, flags, + arg1_name, arg1_val); +} + +template<class ARG1_TYPE, class ARG2_TYPE> +static inline base::debug::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned char flags, + const char* arg1_name, + const ARG1_TYPE& arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, thread_id, timestamp, + num_args, arg_names, arg_types, arg_values, NULL, flags); +} + +template<class ARG1_TYPE, class ARG2_TYPE> +static inline base::debug::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1_name, + const ARG1_TYPE& arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime(); + return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, + name, id, thread_id, now, flags, + arg1_name, arg1_val, + arg2_name, arg2_val); +} + +// Used by TRACE_EVENTx macros. Do not use directly. +class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { + public: + // Note: members of data_ intentionally left uninitialized. See Initialize. + ScopedTracer() : p_data_(NULL) {} + + ~ScopedTracer() { + if (p_data_ && *data_.category_group_enabled) + TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( + data_.category_group_enabled, data_.name, data_.event_handle); + } + + void Initialize(const unsigned char* category_group_enabled, + const char* name, + base::debug::TraceEventHandle event_handle) { + data_.category_group_enabled = category_group_enabled; + data_.name = name; + data_.event_handle = event_handle; + p_data_ = &data_; + } + + private: + // This Data struct workaround is to avoid initializing all the members + // in Data during construction of this object, since this object is always + // constructed, even when tracing is disabled. If the members of Data were + // members of this class instead, compiler warnings occur about potential + // uninitialized accesses. + struct Data { + const unsigned char* category_group_enabled; + const char* name; + base::debug::TraceEventHandle event_handle; + }; + Data* p_data_; + Data data_; +}; + +// Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly. +class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient { + public: + ScopedTraceBinaryEfficient(const char* category_group, const char* name); + ~ScopedTraceBinaryEfficient(); + + private: + const unsigned char* category_group_enabled_; + const char* name_; + base::debug::TraceEventHandle event_handle_; +}; + +// This macro generates less code then TRACE_EVENT0 but is also +// slower to execute when tracing is off. It should generally only be +// used with code that is seldom executed or conditionally executed +// when debugging. +// For now the category_group must be "gpu". +#define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \ + trace_event_internal::ScopedTraceBinaryEfficient \ + INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name); + +// TraceEventSamplingStateScope records the current sampling state +// and sets a new sampling state. When the scope exists, it restores +// the sampling state having recorded. +template<size_t BucketNumber> +class TraceEventSamplingStateScope { + public: + TraceEventSamplingStateScope(const char* category_and_name) { + previous_state_ = TraceEventSamplingStateScope<BucketNumber>::Current(); + TraceEventSamplingStateScope<BucketNumber>::Set(category_and_name); + } + + ~TraceEventSamplingStateScope() { + TraceEventSamplingStateScope<BucketNumber>::Set(previous_state_); + } + + static inline const char* Current() { + return reinterpret_cast<const char*>(TRACE_EVENT_API_ATOMIC_LOAD( + g_trace_state[BucketNumber])); + } + + static inline void Set(const char* category_and_name) { + TRACE_EVENT_API_ATOMIC_STORE( + g_trace_state[BucketNumber], + reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( + const_cast<char*>(category_and_name))); + } + + private: + const char* previous_state_; +}; + +} // namespace trace_event_internal + +namespace base { +namespace debug { + +template<typename IDType> class TraceScopedTrackableObject { + public: + TraceScopedTrackableObject(const char* category_group, const char* name, + IDType id) + : category_group_(category_group), + name_(name), + id_(id) { + TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group_, name_, id_); + } + + template <typename ArgType> void snapshot(ArgType snapshot) { + TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group_, name_, id_, snapshot); + } + + ~TraceScopedTrackableObject() { + TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group_, name_, id_); + } + + private: + const char* category_group_; + const char* name_; + IDType id_; + + DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject); +}; + +} // namespace debug +} // namespace base + +#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */ diff --git a/base/debug/trace_event_android.cc b/base/trace_event/trace_event_android.cc index f08fffc..31da26d 100644 --- a/base/debug/trace_event_android.cc +++ b/base/trace_event/trace_event_android.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_impl.h" +#include "base/trace_event/trace_event_impl.h" #include <fcntl.h> -#include "base/debug/trace_event.h" #include "base/format_macros.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" +#include "base/trace_event/trace_event.h" namespace { diff --git a/base/debug/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc index 90e924f1..00fcde1 100644 --- a/base/debug/trace_event_argument.cc +++ b/base/trace_event/trace_event_argument.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_argument.h" +#include "base/trace_event/trace_event_argument.h" #include "base/json/json_writer.h" #include "base/values.h" diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h new file mode 100644 index 0000000..08a5b50 --- /dev/null +++ b/base/trace_event/trace_event_argument.h @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/trace_event/trace_event.h" + +namespace base { +class DictionaryValue; +class ListValue; +class Value; + +namespace debug { + +class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { + public: + TracedValue(); + + void EndDictionary(); + void EndArray(); + + void SetInteger(const char* name, int value); + void SetDouble(const char* name, double); + void SetBoolean(const char* name, bool value); + void SetString(const char* name, const std::string& value); + void SetValue(const char* name, Value* value); + void BeginDictionary(const char* name); + void BeginArray(const char* name); + + void AppendInteger(int); + void AppendDouble(double); + void AppendBoolean(bool); + void AppendString(const std::string&); + void BeginArray(); + void BeginDictionary(); + + void AppendAsTraceFormat(std::string* out) const override; + + private: + ~TracedValue() override; + + DictionaryValue* GetCurrentDictionary(); + ListValue* GetCurrentArray(); + + scoped_ptr<base::Value> root_; + std::vector<Value*> stack_; + DISALLOW_COPY_AND_ASSIGN(TracedValue); +}; + +} // namespace debug +} // namespace base + +#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ diff --git a/base/debug/trace_event_argument_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc index 06a7697..39cafef 100644 --- a/base/debug/trace_event_argument_unittest.cc +++ b/base/trace_event/trace_event_argument_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_argument.h" +#include "base/trace_event/trace_event_argument.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { diff --git a/base/debug/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 137cb02..a8a0cc1 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_impl.h" +#include "base/trace_event/trace_event_impl.h" #include <algorithm> @@ -10,8 +10,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/debug/leak_annotations.h" -#include "base/debug/trace_event.h" -#include "base/debug/trace_event_synthetic_delay.h" #include "base/float_util.h" #include "base/format_macros.h" #include "base/json/string_escape.h" @@ -33,9 +31,11 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread_id_name_manager.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_event_synthetic_delay.h" #if defined(OS_WIN) -#include "base/debug/trace_event_win.h" +#include "base/trace_event/trace_event_win.h" #endif class DeleteTraceLogForTesting { diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h new file mode 100644 index 0000000..6d04c76 --- /dev/null +++ b/base/trace_event/trace_event_impl.h @@ -0,0 +1,813 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_ + +#include <stack> +#include <string> +#include <vector> + +#include "base/atomicops.h" +#include "base/base_export.h" +#include "base/callback.h" +#include "base/containers/hash_tables.h" +#include "base/gtest_prod_util.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_vector.h" +#include "base/observer_list.h" +#include "base/strings/string_util.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" +#include "base/threading/thread_local.h" + +// Older style trace macros with explicit id and extra data +// Only these macros result in publishing data to ETW as currently implemented. +#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \ + base::debug::TraceLog::AddTraceEventEtw( \ + TRACE_EVENT_PHASE_BEGIN, \ + name, reinterpret_cast<const void*>(id), extra) + +#define TRACE_EVENT_END_ETW(name, id, extra) \ + base::debug::TraceLog::AddTraceEventEtw( \ + TRACE_EVENT_PHASE_END, \ + name, reinterpret_cast<const void*>(id), extra) + +#define TRACE_EVENT_INSTANT_ETW(name, id, extra) \ + base::debug::TraceLog::AddTraceEventEtw( \ + TRACE_EVENT_PHASE_INSTANT, \ + name, reinterpret_cast<const void*>(id), extra) + +template <typename Type> +struct DefaultSingletonTraits; + +namespace base { + +class WaitableEvent; +class MessageLoop; + +namespace debug { + +// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided +// class must implement this interface. +class BASE_EXPORT ConvertableToTraceFormat + : public RefCounted<ConvertableToTraceFormat> { + public: + // Append the class info to the provided |out| string. The appended + // data must be a valid JSON object. Strings must be properly quoted, and + // escaped. There is no processing applied to the content after it is + // appended. + virtual void AppendAsTraceFormat(std::string* out) const = 0; + + std::string ToString() const { + std::string result; + AppendAsTraceFormat(&result); + return result; + } + + protected: + virtual ~ConvertableToTraceFormat() {} + + private: + friend class RefCounted<ConvertableToTraceFormat>; +}; + +struct TraceEventHandle { + uint32 chunk_seq; + uint16 chunk_index; + uint16 event_index; +}; + +const int kTraceMaxNumArgs = 2; + +class BASE_EXPORT TraceEvent { + public: + union TraceValue { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; + }; + + TraceEvent(); + ~TraceEvent(); + + // We don't need to copy TraceEvent except when TraceEventBuffer is cloned. + // Use explicit copy method to avoid accidentally misuse of copy. + void CopyFrom(const TraceEvent& other); + + void Initialize( + int thread_id, + TimeTicks timestamp, + TimeTicks thread_timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const scoped_refptr<ConvertableToTraceFormat>* convertable_values, + unsigned char flags); + + void Reset(); + + void UpdateDuration(const TimeTicks& now, const TimeTicks& thread_now); + + // Serialize event data to JSON + void AppendAsJSON(std::string* out) const; + void AppendPrettyPrinted(std::ostringstream* out) const; + + static void AppendValueAsJSON(unsigned char type, + TraceValue value, + std::string* out); + + TimeTicks timestamp() const { return timestamp_; } + TimeTicks thread_timestamp() const { return thread_timestamp_; } + char phase() const { return phase_; } + int thread_id() const { return thread_id_; } + TimeDelta duration() const { return duration_; } + TimeDelta thread_duration() const { return thread_duration_; } + unsigned long long id() const { return id_; } + unsigned char flags() const { return flags_; } + + // Exposed for unittesting: + + const base::RefCountedString* parameter_copy_storage() const { + return parameter_copy_storage_.get(); + } + + const unsigned char* category_group_enabled() const { + return category_group_enabled_; + } + + const char* name() const { return name_; } + +#if defined(OS_ANDROID) + void SendToATrace(); +#endif + + private: + // Note: these are ordered by size (largest first) for optimal packing. + TimeTicks timestamp_; + TimeTicks thread_timestamp_; + TimeDelta duration_; + TimeDelta thread_duration_; + // id_ can be used to store phase-specific data. + unsigned long long id_; + TraceValue arg_values_[kTraceMaxNumArgs]; + const char* arg_names_[kTraceMaxNumArgs]; + scoped_refptr<ConvertableToTraceFormat> convertable_values_[kTraceMaxNumArgs]; + const unsigned char* category_group_enabled_; + const char* name_; + scoped_refptr<base::RefCountedString> parameter_copy_storage_; + int thread_id_; + char phase_; + unsigned char flags_; + unsigned char arg_types_[kTraceMaxNumArgs]; + + DISALLOW_COPY_AND_ASSIGN(TraceEvent); +}; + +// TraceBufferChunk is the basic unit of TraceBuffer. +class BASE_EXPORT TraceBufferChunk { + public: + explicit TraceBufferChunk(uint32 seq) + : next_free_(0), + seq_(seq) { + } + + void Reset(uint32 new_seq); + TraceEvent* AddTraceEvent(size_t* event_index); + bool IsFull() const { return next_free_ == kTraceBufferChunkSize; } + + uint32 seq() const { return seq_; } + size_t capacity() const { return kTraceBufferChunkSize; } + size_t size() const { return next_free_; } + + TraceEvent* GetEventAt(size_t index) { + DCHECK(index < size()); + return &chunk_[index]; + } + const TraceEvent* GetEventAt(size_t index) const { + DCHECK(index < size()); + return &chunk_[index]; + } + + scoped_ptr<TraceBufferChunk> Clone() const; + + static const size_t kTraceBufferChunkSize = 64; + + private: + size_t next_free_; + TraceEvent chunk_[kTraceBufferChunkSize]; + uint32 seq_; +}; + +// TraceBuffer holds the events as they are collected. +class BASE_EXPORT TraceBuffer { + public: + virtual ~TraceBuffer() {} + + virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t *index) = 0; + virtual void ReturnChunk(size_t index, + scoped_ptr<TraceBufferChunk> chunk) = 0; + + virtual bool IsFull() const = 0; + virtual size_t Size() const = 0; + virtual size_t Capacity() const = 0; + virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) = 0; + + // For iteration. Each TraceBuffer can only be iterated once. + virtual const TraceBufferChunk* NextChunk() = 0; + + virtual scoped_ptr<TraceBuffer> CloneForIteration() const = 0; +}; + +// TraceResultBuffer collects and converts trace fragments returned by TraceLog +// to JSON output. +class BASE_EXPORT TraceResultBuffer { + public: + typedef base::Callback<void(const std::string&)> OutputCallback; + + // If you don't need to stream JSON chunks out efficiently, and just want to + // get a complete JSON string after calling Finish, use this struct to collect + // JSON trace output. + struct BASE_EXPORT SimpleOutput { + OutputCallback GetCallback(); + void Append(const std::string& json_string); + + // Do what you want with the json_output_ string after calling + // TraceResultBuffer::Finish. + std::string json_output; + }; + + TraceResultBuffer(); + ~TraceResultBuffer(); + + // Set callback. The callback will be called during Start with the initial + // JSON output and during AddFragment and Finish with following JSON output + // chunks. The callback target must live past the last calls to + // TraceResultBuffer::Start/AddFragment/Finish. + void SetOutputCallback(const OutputCallback& json_chunk_callback); + + // Start JSON output. This resets all internal state, so you can reuse + // the TraceResultBuffer by calling Start. + void Start(); + + // Call AddFragment 0 or more times to add trace fragments from TraceLog. + void AddFragment(const std::string& trace_fragment); + + // When all fragments have been added, call Finish to complete the JSON + // formatted output. + void Finish(); + + private: + OutputCallback output_callback_; + bool append_comma_; +}; + +class BASE_EXPORT CategoryFilter { + public: + typedef std::vector<std::string> StringList; + + // The default category filter, used when none is provided. + // Allows all categories through, except if they end in the suffix 'Debug' or + // 'Test'. + static const char kDefaultCategoryFilterString[]; + + // |filter_string| is a comma-delimited list of category wildcards. + // A category can have an optional '-' prefix to make it an excluded category. + // All the same rules apply above, so for example, having both included and + // excluded categories in the same list would not be supported. + // + // Example: CategoryFilter"test_MyTest*"); + // Example: CategoryFilter("test_MyTest*,test_OtherStuff"); + // Example: CategoryFilter("-excluded_category1,-excluded_category2"); + // Example: CategoryFilter("-*,webkit"); would disable everything but webkit. + // Example: CategoryFilter("-webkit"); would enable everything but webkit. + // + // Category filters can also be used to configure synthetic delays. + // + // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16)"); would make swap + // buffers always take at least 16 ms. + // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16;oneshot)"); would + // make swap buffers take at least 16 ms the first time it is + // called. + // Example: CategoryFilter("DELAY(gpu.PresentingFrame;16;alternating)"); + // would make swap buffers take at least 16 ms every other time it + // is called. + explicit CategoryFilter(const std::string& filter_string); + + CategoryFilter(); + + CategoryFilter(const CategoryFilter& cf); + + ~CategoryFilter(); + + CategoryFilter& operator=(const CategoryFilter& rhs); + + // Writes the string representation of the CategoryFilter. This is a comma + // separated string, similar in nature to the one used to determine + // enabled/disabled category patterns, except here there is an arbitrary + // order, included categories go first, then excluded categories. Excluded + // categories are distinguished from included categories by the prefix '-'. + std::string ToString() const; + + // Returns true if at least one category in the list is enabled by this + // category filter. + bool IsCategoryGroupEnabled(const char* category_group) const; + + // Return a list of the synthetic delays specified in this category filter. + const StringList& GetSyntheticDelayValues() const; + + // Merges nested_filter with the current CategoryFilter + void Merge(const CategoryFilter& nested_filter); + + // Clears both included/excluded pattern lists. This would be equivalent to + // creating a CategoryFilter with an empty string, through the constructor. + // i.e: CategoryFilter(). + // + // When using an empty filter, all categories are considered included as we + // are not excluding anything. + void Clear(); + + private: + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, CategoryFilter); + + // Returns true if category is enable according to this filter. + bool IsCategoryEnabled(const char* category_name) const; + + static bool IsEmptyOrContainsLeadingOrTrailingWhitespace( + const std::string& str); + + void Initialize(const std::string& filter_string); + void WriteString(const StringList& values, + std::string* out, + bool included) const; + void WriteString(const StringList& delays, std::string* out) const; + bool HasIncludedPatterns() const; + + StringList included_; + StringList disabled_; + StringList excluded_; + StringList delays_; +}; + +class TraceSamplingThread; + +// Options determines how the trace buffer stores data. +enum TraceRecordMode { + // Record until the trace buffer is full. + RECORD_UNTIL_FULL, + + // Record until the user ends the trace. The trace buffer is a fixed size + // and we use it as a ring buffer during recording. + RECORD_CONTINUOUSLY, + + // Echo to console. Events are discarded. + ECHO_TO_CONSOLE, + + // Record until the trace buffer is full, but with a huge buffer size. + RECORD_AS_MUCH_AS_POSSIBLE +}; + +struct BASE_EXPORT TraceOptions { + TraceOptions() + : record_mode(RECORD_UNTIL_FULL), + enable_sampling(false), + enable_systrace(false) {} + + explicit TraceOptions(TraceRecordMode record_mode) + : record_mode(record_mode), + enable_sampling(false), + enable_systrace(false) {} + + // |options_string| is a comma-delimited list of trace options. + // Possible options are: "record-until-full", "record-continuously", + // "trace-to-console", "enable-sampling" and "enable-systrace". + // The first 3 options are trace recoding modes and hence + // mutually exclusive. If more than one trace recording modes appear in the + // options_string, the last one takes precedence. If none of the trace + // recording mode is specified, recording mode is RECORD_UNTIL_FULL. + // + // The trace option will first be reset to the default option + // (record_mode set to RECORD_UNTIL_FULL, enable_sampling and enable_systrace + // set to false) before options parsed from |options_string| are applied on + // it. + // If |options_string| is invalid, the final state of trace_options is + // undefined. + // + // Example: trace_options.SetFromString("record-until-full") + // Example: trace_options.SetFromString( + // "record-continuously, enable-sampling") + // Example: trace_options.SetFromString("record-until-full, trace-to-console") + // will set ECHO_TO_CONSOLE as the recording mode. + // + // Returns true on success. + bool SetFromString(const std::string& options_string); + + std::string ToString() const; + + TraceRecordMode record_mode; + bool enable_sampling; + bool enable_systrace; +}; + +struct BASE_EXPORT TraceLogStatus { + TraceLogStatus(); + ~TraceLogStatus(); + size_t event_capacity; + size_t event_count; +}; + +class BASE_EXPORT TraceLog { + public: + enum Mode { + DISABLED = 0, + RECORDING_MODE, + MONITORING_MODE, + }; + + // The pointer returned from GetCategoryGroupEnabledInternal() points to a + // value with zero or more of the following bits. Used in this class only. + // The TRACE_EVENT macros should only use the value as a bool. + // These values must be in sync with macro values in TraceEvent.h in Blink. + enum CategoryGroupEnabledFlags { + // Category group enabled for the recording mode. + ENABLED_FOR_RECORDING = 1 << 0, + // Category group enabled for the monitoring mode. + ENABLED_FOR_MONITORING = 1 << 1, + // Category group enabled by SetEventCallbackEnabled(). + ENABLED_FOR_EVENT_CALLBACK = 1 << 2, + }; + + static TraceLog* GetInstance(); + + // Get set of known category groups. This can change as new code paths are + // reached. The known category groups are inserted into |category_groups|. + void GetKnownCategoryGroups(std::vector<std::string>* category_groups); + + // Retrieves a copy (for thread-safety) of the current CategoryFilter. + CategoryFilter GetCurrentCategoryFilter(); + + // Retrieves a copy (for thread-safety) of the current TraceOptions. + TraceOptions GetCurrentTraceOptions() const; + + // Enables normal tracing (recording trace events in the trace buffer). + // See CategoryFilter comments for details on how to control what categories + // will be traced. If tracing has already been enabled, |category_filter| will + // be merged into the current category filter. + void SetEnabled(const CategoryFilter& category_filter, + Mode mode, const TraceOptions& options); + + // Disables normal tracing for all categories. + void SetDisabled(); + + bool IsEnabled() { return mode_ != DISABLED; } + + // The number of times we have begun recording traces. If tracing is off, + // returns -1. If tracing is on, then it returns the number of times we have + // recorded a trace. By watching for this number to increment, you can + // passively discover when a new trace has begun. This is then used to + // implement the TRACE_EVENT_IS_NEW_TRACE() primitive. + int GetNumTracesRecorded(); + +#if defined(OS_ANDROID) + void StartATrace(); + void StopATrace(); + void AddClockSyncMetadataEvent(); +#endif + + // Enabled state listeners give a callback when tracing is enabled or + // disabled. This can be used to tie into other library's tracing systems + // on-demand. + class BASE_EXPORT EnabledStateObserver { + public: + // Called just after the tracing system becomes enabled, outside of the + // |lock_|. TraceLog::IsEnabled() is true at this point. + virtual void OnTraceLogEnabled() = 0; + + // Called just after the tracing system disables, outside of the |lock_|. + // TraceLog::IsEnabled() is false at this point. + virtual void OnTraceLogDisabled() = 0; + }; + void AddEnabledStateObserver(EnabledStateObserver* listener); + void RemoveEnabledStateObserver(EnabledStateObserver* listener); + bool HasEnabledStateObserver(EnabledStateObserver* listener) const; + + TraceLogStatus GetStatus() const; + bool BufferIsFull() const; + + // Not using base::Callback because of its limited by 7 parameters. + // Also, using primitive type allows directly passing callback from WebCore. + // WARNING: It is possible for the previously set callback to be called + // after a call to SetEventCallbackEnabled() that replaces or a call to + // SetEventCallbackDisabled() that disables the callback. + // This callback may be invoked on any thread. + // For TRACE_EVENT_PHASE_COMPLETE events, the client will still receive pairs + // of TRACE_EVENT_PHASE_BEGIN and TRACE_EVENT_PHASE_END events to keep the + // interface simple. + typedef void (*EventCallback)(TimeTicks timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char* const arg_names[], + const unsigned char arg_types[], + const unsigned long long arg_values[], + unsigned char flags); + + // Enable tracing for EventCallback. + void SetEventCallbackEnabled(const CategoryFilter& category_filter, + EventCallback cb); + void SetEventCallbackDisabled(); + + // Flush all collected events to the given output callback. The callback will + // be called one or more times either synchronously or asynchronously from + // the current thread with IPC-bite-size chunks. The string format is + // undefined. Use TraceResultBuffer to convert one or more trace strings to + // JSON. The callback can be null if the caller doesn't want any data. + // Due to the implementation of thread-local buffers, flush can't be + // done when tracing is enabled. If called when tracing is enabled, the + // callback will be called directly with (empty_string, false) to indicate + // the end of this unsuccessful flush. + typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&, + bool has_more_events)> OutputCallback; + void Flush(const OutputCallback& cb); + void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback); + + // Called by TRACE_EVENT* macros, don't call this directly. + // The name parameter is a category group for example: + // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent") + static const unsigned char* GetCategoryGroupEnabled(const char* name); + static const char* GetCategoryGroupName( + const unsigned char* category_group_enabled); + + // Called by TRACE_EVENT* macros, don't call this directly. + // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied + // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. + TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const scoped_refptr<ConvertableToTraceFormat>* convertable_values, + unsigned char flags); + TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int thread_id, + const TimeTicks& timestamp, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const scoped_refptr<ConvertableToTraceFormat>* convertable_values, + unsigned char flags); + static void AddTraceEventEtw(char phase, + const char* category_group, + const void* id, + const char* extra); + static void AddTraceEventEtw(char phase, + const char* category_group, + const void* id, + const std::string& extra); + + void UpdateTraceEventDuration(const unsigned char* category_group_enabled, + const char* name, + TraceEventHandle handle); + + // For every matching event, the callback will be called. + typedef base::Callback<void()> WatchEventCallback; + void SetWatchEvent(const std::string& category_name, + const std::string& event_name, + const WatchEventCallback& callback); + // Cancel the watch event. If tracing is enabled, this may race with the + // watch event notification firing. + void CancelWatchEvent(); + + int process_id() const { return process_id_; } + + // Exposed for unittesting: + + void WaitSamplingEventForTesting(); + + // Allows deleting our singleton instance. + static void DeleteForTesting(); + + // Allow tests to inspect TraceEvents. + TraceEvent* GetEventByHandle(TraceEventHandle handle); + + void SetProcessID(int process_id); + + // Process sort indices, if set, override the order of a process will appear + // relative to other processes in the trace viewer. Processes are sorted first + // on their sort index, ascending, then by their name, and then tid. + void SetProcessSortIndex(int sort_index); + + // Sets the name of the process. + void SetProcessName(const std::string& process_name); + + // Processes can have labels in addition to their names. Use labels, for + // instance, to list out the web page titles that a process is handling. + void UpdateProcessLabel(int label_id, const std::string& current_label); + void RemoveProcessLabel(int label_id); + + // Thread sort indices, if set, override the order of a thread will appear + // within its process in the trace viewer. Threads are sorted first on their + // sort index, ascending, then by their name, and then tid. + void SetThreadSortIndex(PlatformThreadId , int sort_index); + + // Allow setting an offset between the current TimeTicks time and the time + // that should be reported. + void SetTimeOffset(TimeDelta offset); + + size_t GetObserverCountForTest() const; + + // Call this method if the current thread may block the message loop to + // prevent the thread from using the thread-local buffer because the thread + // may not handle the flush request in time causing lost of unflushed events. + void SetCurrentThreadBlocksMessageLoop(); + + private: + typedef unsigned int InternalTraceOptions; + + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + TraceBufferRingBufferGetReturnChunk); + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + TraceBufferRingBufferHalfIteration); + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + TraceBufferRingBufferFullIteration); + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + TraceBufferVectorReportFull); + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + ConvertTraceOptionsToInternalOptions); + FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, + TraceRecordAsMuchAsPossibleMode); + + // This allows constructor and destructor to be private and usable only + // by the Singleton class. + friend struct DefaultSingletonTraits<TraceLog>; + + // Enable/disable each category group based on the current mode_, + // category_filter_, event_callback_ and event_callback_category_filter_. + // Enable the category group in the enabled mode if category_filter_ matches + // the category group, or event_callback_ is not null and + // event_callback_category_filter_ matches the category group. + void UpdateCategoryGroupEnabledFlags(); + void UpdateCategoryGroupEnabledFlag(size_t category_index); + + // Configure synthetic delays based on the values set in the current + // category filter. + void UpdateSyntheticDelaysFromCategoryFilter(); + + InternalTraceOptions GetInternalOptionsFromTraceOptions( + const TraceOptions& options); + + class ThreadLocalEventBuffer; + class OptionalAutoLock; + + TraceLog(); + ~TraceLog(); + const unsigned char* GetCategoryGroupEnabledInternal(const char* name); + void AddMetadataEventsWhileLocked(); + + InternalTraceOptions trace_options() const { + return static_cast<InternalTraceOptions>( + subtle::NoBarrier_Load(&trace_options_)); + } + + TraceBuffer* trace_buffer() const { return logged_events_.get(); } + TraceBuffer* CreateTraceBuffer(); + TraceBuffer* CreateTraceBufferVectorOfSize(size_t max_chunks); + + std::string EventToConsoleMessage(unsigned char phase, + const TimeTicks& timestamp, + TraceEvent* trace_event); + + TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle, + bool check_buffer_is_full); + void CheckIfBufferIsFullWhileLocked(); + void SetDisabledWhileLocked(); + + TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, + OptionalAutoLock* lock); + + // |generation| is used in the following callbacks to check if the callback + // is called for the flush of the current |logged_events_|. + void FlushCurrentThread(int generation); + void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events, + const TraceLog::OutputCallback& flush_output_callback); + void FinishFlush(int generation); + void OnFlushTimeout(int generation); + + int generation() const { + return static_cast<int>(subtle::NoBarrier_Load(&generation_)); + } + bool CheckGeneration(int generation) const { + return generation == this->generation(); + } + void UseNextTraceBuffer(); + + TimeTicks OffsetNow() const { + return OffsetTimestamp(TimeTicks::NowFromSystemTraceTime()); + } + TimeTicks OffsetTimestamp(const TimeTicks& timestamp) const { + return timestamp - time_offset_; + } + + // Internal representation of trace options since we store the currently used + // trace option as an AtomicWord. + static const InternalTraceOptions kInternalNone; + static const InternalTraceOptions kInternalRecordUntilFull; + static const InternalTraceOptions kInternalRecordContinuously; + static const InternalTraceOptions kInternalEchoToConsole; + static const InternalTraceOptions kInternalEnableSampling; + static const InternalTraceOptions kInternalRecordAsMuchAsPossible; + + // This lock protects TraceLog member accesses (except for members protected + // by thread_info_lock_) from arbitrary threads. + mutable Lock lock_; + // This lock protects accesses to thread_names_, thread_event_start_times_ + // and thread_colors_. + Lock thread_info_lock_; + Mode mode_; + int num_traces_recorded_; + scoped_ptr<TraceBuffer> logged_events_; + subtle::AtomicWord /* EventCallback */ event_callback_; + bool dispatching_to_observer_list_; + std::vector<EnabledStateObserver*> enabled_state_observer_list_; + + std::string process_name_; + base::hash_map<int, std::string> process_labels_; + int process_sort_index_; + base::hash_map<int, int> thread_sort_indices_; + base::hash_map<int, std::string> thread_names_; + + // The following two maps are used only when ECHO_TO_CONSOLE. + base::hash_map<int, std::stack<TimeTicks> > thread_event_start_times_; + base::hash_map<std::string, int> thread_colors_; + + TimeTicks buffer_limit_reached_timestamp_; + + // XORed with TraceID to make it unlikely to collide with other processes. + unsigned long long process_id_hash_; + + int process_id_; + + TimeDelta time_offset_; + + // Allow tests to wake up when certain events occur. + WatchEventCallback watch_event_callback_; + subtle::AtomicWord /* const unsigned char* */ watch_category_; + std::string watch_event_name_; + + subtle::AtomicWord /* Options */ trace_options_; + + // Sampling thread handles. + scoped_ptr<TraceSamplingThread> sampling_thread_; + PlatformThreadHandle sampling_thread_handle_; + + CategoryFilter category_filter_; + CategoryFilter event_callback_category_filter_; + + ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_; + ThreadLocalBoolean thread_blocks_message_loop_; + ThreadLocalBoolean thread_is_in_trace_event_; + + // Contains the message loops of threads that have had at least one event + // added into the local event buffer. Not using MessageLoopProxy because we + // need to know the life time of the message loops. + hash_set<MessageLoop*> thread_message_loops_; + + // For events which can't be added into the thread local buffer, e.g. events + // from threads without a message loop. + scoped_ptr<TraceBufferChunk> thread_shared_chunk_; + size_t thread_shared_chunk_index_; + + // Set when asynchronous Flush is in progress. + OutputCallback flush_output_callback_; + scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_; + subtle::AtomicWord generation_; + + DISALLOW_COPY_AND_ASSIGN(TraceLog); +}; + +} // namespace debug +} // namespace base + +#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_ diff --git a/base/debug/trace_event_impl_constants.cc b/base/trace_event/trace_event_impl_constants.cc index 8e01411..c46cf49 100644 --- a/base/debug/trace_event_impl_constants.cc +++ b/base/trace_event/trace_event_impl_constants.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_impl.h" +#include "base/trace_event/trace_event_impl.h" namespace base { namespace debug { diff --git a/base/debug/trace_event_memory.cc b/base/trace_event/trace_event_memory.cc index 2831865..96b28e4 100644 --- a/base/debug/trace_event_memory.cc +++ b/base/trace_event/trace_event_memory.cc @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_memory.h" +#include "base/trace_event/trace_event_memory.h" #include "base/debug/leak_annotations.h" -#include "base/debug/trace_event.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -13,6 +12,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_local_storage.h" +#include "base/trace_event/trace_event.h" namespace base { namespace debug { diff --git a/base/debug/trace_event_memory.h b/base/trace_event/trace_event_memory.h index 94c3f91..f16467f 100644 --- a/base/debug/trace_event_memory.h +++ b/base/trace_event/trace_event_memory.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEBUG_TRACE_EVENT_MEMORY_H_ -#define BASE_DEBUG_TRACE_EVENT_MEMORY_H_ +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_H_ #include "base/base_export.h" -#include "base/debug/trace_event_impl.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event_impl.h" // TODO(jamescook): Windows support for memory tracing. #if !defined(NO_TCMALLOC) && !defined(OS_NACL) && \ @@ -169,4 +169,4 @@ BASE_EXPORT const char* StringFromHexAddress(const std::string& hex_address); // visualizer skips them. Must match the value in heap.js. #define TRACE_MEMORY_IGNORE "trace-memory-ignore" -#endif // BASE_DEBUG_TRACE_EVENT_MEMORY_H_ +#endif // BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_H_ diff --git a/base/debug/trace_event_memory_unittest.cc b/base/trace_event/trace_event_memory_unittest.cc index 12135b8..220c0e6 100644 --- a/base/debug/trace_event_memory_unittest.cc +++ b/base/trace_event/trace_event_memory_unittest.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_memory.h" +#include "base/trace_event/trace_event_memory.h" #include <sstream> #include <string> -#include "base/debug/trace_event_impl.h" #include "base/message_loop/message_loop.h" +#include "base/trace_event/trace_event_impl.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) diff --git a/base/debug/trace_event_synthetic_delay.cc b/base/trace_event/trace_event_synthetic_delay.cc index 260a5d8..3651611 100644 --- a/base/debug/trace_event_synthetic_delay.cc +++ b/base/trace_event/trace_event_synthetic_delay.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_synthetic_delay.h" #include "base/memory/singleton.h" +#include "base/trace_event/trace_event_synthetic_delay.h" namespace { const int kMaxSyntheticDelays = 32; diff --git a/base/trace_event/trace_event_synthetic_delay.h b/base/trace_event/trace_event_synthetic_delay.h new file mode 100644 index 0000000..b52f3b0 --- /dev/null +++ b/base/trace_event/trace_event_synthetic_delay.h @@ -0,0 +1,166 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The synthetic delay framework makes it possible to dynamically inject +// arbitrary delays into into different parts of the codebase. This can be used, +// for instance, for testing various task scheduling algorithms. +// +// The delays are specified in terms of a target duration for a given block of +// code. If the code executes faster than the duration, the thread is made to +// sleep until the deadline is met. +// +// Code can be instrumented for delays with two sets of macros. First, for +// delays that should apply within a scope, use the following macro: +// +// TRACE_EVENT_SYNTHETIC_DELAY("cc.LayerTreeHost.DrawAndSwap"); +// +// For delaying operations that span multiple scopes, use: +// +// TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.Scheduler.BeginMainFrame"); +// ... +// TRACE_EVENT_SYNTHETIC_DELAY_END("cc.Scheduler.BeginMainFrame"); +// +// Here BEGIN establishes the start time for the delay and END executes the +// delay based on the remaining time. If BEGIN is called multiple times in a +// row, END should be called a corresponding number of times. Only the last +// call to END will have an effect. +// +// Note that a single delay may begin on one thread and end on another. This +// implies that a single delay cannot not be applied in several threads at once. + +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_ + +#include "base/atomicops.h" +#include "base/synchronization/lock.h" +#include "base/time/time.h" +#include "base/trace_event/trace_event.h" + +// Apply a named delay in the current scope. +#define TRACE_EVENT_SYNTHETIC_DELAY(name) \ + static base::subtle::AtomicWord INTERNAL_TRACE_EVENT_UID(impl_ptr) = 0; \ + trace_event_internal::ScopedSyntheticDelay INTERNAL_TRACE_EVENT_UID(delay)( \ + name, &INTERNAL_TRACE_EVENT_UID(impl_ptr)); + +// Begin a named delay, establishing its timing start point. May be called +// multiple times as long as the calls to TRACE_EVENT_SYNTHETIC_DELAY_END are +// balanced. Only the first call records the timing start point. +#define TRACE_EVENT_SYNTHETIC_DELAY_BEGIN(name) \ + do { \ + static base::subtle::AtomicWord impl_ptr = 0; \ + trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->Begin(); \ + } while (false) + +// End a named delay. The delay is applied only if this call matches the +// first corresponding call to TRACE_EVENT_SYNTHETIC_DELAY_BEGIN with the +// same delay. +#define TRACE_EVENT_SYNTHETIC_DELAY_END(name) \ + do { \ + static base::subtle::AtomicWord impl_ptr = 0; \ + trace_event_internal::GetOrCreateDelay(name, &impl_ptr)->End(); \ + } while (false) + +template <typename Type> +struct DefaultSingletonTraits; + +namespace base { +namespace debug { + +// Time source for computing delay durations. Used for testing. +class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock { + public: + TraceEventSyntheticDelayClock(); + virtual ~TraceEventSyntheticDelayClock(); + virtual base::TimeTicks Now() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayClock); +}; + +// Single delay point instance. +class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelay { + public: + enum Mode { + STATIC, // Apply the configured delay every time. + ONE_SHOT, // Apply the configured delay just once. + ALTERNATING // Apply the configured delay every other time. + }; + + // Returns an existing named delay instance or creates a new one with |name|. + static TraceEventSyntheticDelay* Lookup(const std::string& name); + + void SetTargetDuration(TimeDelta target_duration); + void SetMode(Mode mode); + void SetClock(TraceEventSyntheticDelayClock* clock); + + // Begin the delay, establishing its timing start point. May be called + // multiple times as long as the calls to End() are balanced. Only the first + // call records the timing start point. + void Begin(); + + // End the delay. The delay is applied only if this call matches the first + // corresponding call to Begin() with the same delay. + void End(); + + // Begin a parallel instance of the delay. Several parallel instances may be + // active simultaneously and will complete independently. The computed end + // time for the delay is stored in |out_end_time|, which should later be + // passed to EndParallel(). + void BeginParallel(base::TimeTicks* out_end_time); + + // End a previously started parallel delay. |end_time| is the delay end point + // computed by BeginParallel(). + void EndParallel(base::TimeTicks end_time); + + private: + TraceEventSyntheticDelay(); + ~TraceEventSyntheticDelay(); + friend class TraceEventSyntheticDelayRegistry; + + void Initialize(const std::string& name, + TraceEventSyntheticDelayClock* clock); + base::TimeTicks CalculateEndTimeLocked(base::TimeTicks start_time); + void ApplyDelay(base::TimeTicks end_time); + + Lock lock_; + Mode mode_; + std::string name_; + int begin_count_; + int trigger_count_; + base::TimeTicks end_time_; + base::TimeDelta target_duration_; + TraceEventSyntheticDelayClock* clock_; + + DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelay); +}; + +// Set the target durations of all registered synthetic delay points to zero. +TRACE_EVENT_API_CLASS_EXPORT void ResetTraceEventSyntheticDelays(); + +} // namespace debug +} // namespace base + +namespace trace_event_internal { + +// Helper class for scoped delays. Do not use directly. +class TRACE_EVENT_API_CLASS_EXPORT ScopedSyntheticDelay { + public: + explicit ScopedSyntheticDelay(const char* name, + base::subtle::AtomicWord* impl_ptr); + ~ScopedSyntheticDelay(); + + private: + base::debug::TraceEventSyntheticDelay* delay_impl_; + base::TimeTicks end_time_; + + DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay); +}; + +// Helper for registering delays. Do not use directly. +TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay* + GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr); + +} // namespace trace_event_internal + +#endif /* BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ diff --git a/base/debug/trace_event_synthetic_delay_unittest.cc b/base/trace_event/trace_event_synthetic_delay_unittest.cc index 00cf4f9..84ac75c 100644 --- a/base/debug/trace_event_synthetic_delay_unittest.cc +++ b/base/trace_event/trace_event_synthetic_delay_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_synthetic_delay.h" +#include "base/trace_event/trace_event_synthetic_delay.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/debug/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc index 9cbefd8..6fa0174 100644 --- a/base/debug/trace_event_system_stats_monitor.cc +++ b/base/trace_event/trace_event_system_stats_monitor.cc @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_system_stats_monitor.h" +#include "base/trace_event/trace_event_system_stats_monitor.h" #include "base/debug/leak_annotations.h" -#include "base/debug/trace_event.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/logging.h" @@ -14,6 +13,7 @@ #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" #include "base/threading/thread_local_storage.h" +#include "base/trace_event/trace_event.h" namespace base { namespace debug { diff --git a/base/debug/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h index 143f187..08fbfea 100644 --- a/base/debug/trace_event_system_stats_monitor.h +++ b/base/trace_event/trace_event_system_stats_monitor.h @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEBUG_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ -#define BASE_DEBUG_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ #include "base/base_export.h" -#include "base/debug/trace_event_impl.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/process/process_metrics.h" #include "base/timer/timer.h" +#include "base/trace_event/trace_event_impl.h" namespace base { @@ -72,4 +72,4 @@ BASE_EXPORT void AppendSystemProfileAsTraceFormat(const SystemMetrics& } // namespace debug } // namespace base -#endif // BASE_DEBUG_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ +#endif // BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_ diff --git a/base/debug/trace_event_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc index 76292d2..143ac4a 100644 --- a/base/debug/trace_event_system_stats_monitor_unittest.cc +++ b/base/trace_event/trace_event_system_stats_monitor_unittest.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_system_stats_monitor.h" +#include "base/trace_event/trace_event_system_stats_monitor.h" #include <sstream> #include <string> -#include "base/debug/trace_event_impl.h" #include "base/message_loop/message_loop.h" +#include "base/trace_event/trace_event_impl.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { diff --git a/base/debug/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 4494c99..47b5ab6 100644 --- a/base/debug/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc @@ -7,8 +7,6 @@ #include "base/bind.h" #include "base/command_line.h" -#include "base/debug/trace_event.h" -#include "base/debug/trace_event_synthetic_delay.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/memory/ref_counted_memory.h" @@ -20,6 +18,8 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_event_synthetic_delay.h" #include "base/values.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/base/debug/trace_event_win.cc b/base/trace_event/trace_event_win.cc index 99dd242..d2c3dc8 100644 --- a/base/debug/trace_event_win.cc +++ b/base/trace_event/trace_event_win.cc @@ -1,7 +1,8 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_win.h" + +#include "base/trace_event/trace_event_win.h" #include "base/logging.h" #include "base/memory/singleton.h" diff --git a/base/trace_event/trace_event_win.h b/base/trace_event/trace_event_win.h new file mode 100644 index 0000000..e447c35 --- /dev/null +++ b/base/trace_event/trace_event_win.h @@ -0,0 +1,125 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains the Windows-specific declarations for trace_event.h. +#ifndef BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_ +#define BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_ + +#include <string> + +#include "base/base_export.h" +#include "base/trace_event/trace_event.h" +#include "base/win/event_trace_provider.h" + +// Fwd. +template <typename Type> +struct StaticMemorySingletonTraits; + +namespace base { +namespace debug { + +// This EtwTraceProvider subclass implements ETW logging +// for the macros above on Windows. +class BASE_EXPORT TraceEventETWProvider : public base::win::EtwTraceProvider { + public: + static const size_t kUseStrlen = static_cast<size_t>(-1); + + // Start logging trace events. + // This is a noop in this implementation. + static bool StartTracing(); + + // Trace begin/end/instant events, this is the bottleneck implementation + // all the others defer to. + // Allowing the use of std::string for name or extra is a convenience, + // whereas passing name or extra as a const char* avoids the construction + // of temporary std::string instances. + // If kUseStrlen is passed for name_len or extra_len, the strlen of the string + // will be used for length. + static void Trace(const char* name, + size_t name_len, + char type, + const void* id, + const char* extra, + size_t extra_len); + + // Allows passing extra as a std::string for convenience. + static void Trace(const char* name, + char type, + const void* id, + const std::string& extra) { + return Trace(name, kUseStrlen, type, id, extra.c_str(), extra.length()); + } + + // Allows passing extra as a const char* to avoid constructing temporary + // std::string instances where not needed. + static void Trace(const char* name, + char type, + const void* id, + const char* extra) { + return Trace(name, kUseStrlen, type, id, extra, kUseStrlen); + } + + // Retrieves the singleton. + // Note that this may return NULL post-AtExit processing. + static TraceEventETWProvider* GetInstance(); + + // Returns true iff tracing is turned on. + bool IsTracing() { + return enable_level() >= TRACE_LEVEL_INFORMATION; + } + + // Emit a trace of type |type| containing |name|, |id|, and |extra|. + // Note: |name| and |extra| must be NULL, or a zero-terminated string of + // length |name_len| or |extra_len| respectively. + // Note: if name_len or extra_len are kUseStrlen, the length of the + // corresponding string will be used. + void TraceEvent(const char* name, + size_t name_len, + char type, + const void* id, + const char* extra, + size_t extra_len); + + // Exposed for unittesting only, allows resurrecting our + // singleton instance post-AtExit processing. + static void Resurrect(); + + private: + // Ensure only the provider can construct us. + friend struct StaticMemorySingletonTraits<TraceEventETWProvider>; + TraceEventETWProvider(); + + DISALLOW_COPY_AND_ASSIGN(TraceEventETWProvider); +}; + +// The ETW trace provider GUID. +BASE_EXPORT extern const GUID kChromeTraceProviderName; + +// The ETW event class GUID for 32 bit events. +BASE_EXPORT extern const GUID kTraceEventClass32; + +// The ETW event class GUID for 64 bit events. +BASE_EXPORT extern const GUID kTraceEventClass64; + +// The ETW event types, IDs 0x00-0x09 are reserved, so start at 0x10. +const base::win::EtwEventType kTraceEventTypeBegin = 0x10; +const base::win::EtwEventType kTraceEventTypeEnd = 0x11; +const base::win::EtwEventType kTraceEventTypeInstant = 0x12; + +// If this flag is set in enable flags +enum TraceEventETWFlags { + CAPTURE_STACK_TRACE = 0x0001, +}; + +// The event format consists of: +// The "name" string as a zero-terminated ASCII string. +// The id pointer in the machine bitness. +// The "extra" string as a zero-terminated ASCII string. +// Optionally the stack trace, consisting of a DWORD "depth", followed +// by an array of void* (machine bitness) of length "depth". + +} // namespace debug +} // namespace base + +#endif // BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_ diff --git a/base/debug/trace_event_win_unittest.cc b/base/trace_event/trace_event_win_unittest.cc index 3782645..a411301 100644 --- a/base/debug/trace_event_win_unittest.cc +++ b/base/trace_event/trace_event_win_unittest.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event.h" +#include "base/trace_event/trace_event.h" #include <strstream> #include "base/at_exit.h" #include "base/basictypes.h" -#include "base/debug/trace_event.h" -#include "base/debug/trace_event_win.h" #include "base/files/file_util.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_event_win.h" #include "base/win/event_trace_consumer.h" #include "base/win/event_trace_controller.h" #include "base/win/event_trace_provider.h" diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py index 0569e23..91cec02 100755 --- a/tools/gn/bootstrap/bootstrap.py +++ b/tools/gn/bootstrap/bootstrap.py @@ -151,10 +151,6 @@ def write_ninja(path, options): 'base/debug/alias.cc', 'base/debug/stack_trace.cc', 'base/debug/task_annotator.cc', - 'base/debug/trace_event_impl.cc', - 'base/debug/trace_event_impl_constants.cc', - 'base/debug/trace_event_memory.cc', - 'base/debug/trace_event_synthetic_delay.cc', 'base/environment.cc', 'base/files/file.cc', 'base/files/file_enumerator.cc', @@ -229,6 +225,10 @@ def write_ninja(path, options): 'base/time/time.cc', 'base/timer/elapsed_timer.cc', 'base/timer/timer.cc', + 'base/trace_event/trace_event_impl.cc', + 'base/trace_event/trace_event_impl_constants.cc', + 'base/trace_event/trace_event_memory.cc', + 'base/trace_event/trace_event_synthetic_delay.cc', 'base/tracked_objects.cc', 'base/tracking_info.cc', 'base/values.cc', |