Path: blob/main_old/src/third_party/trace_event/trace_event.h
1693 views
// Copyright (c) 2013 The Chromium Authors. All rights reserved.1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34// Trace events are for tracking application performance and resource usage.5// Macros are provided to track:6// Begin and end of function calls7// Counters8//9// Events are issued against categories. Whereas LOG's10// categories are statically defined, TRACE categories are created11// implicitly with a string. For example:12// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")13//14// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:15// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")16// doSomethingCostly()17// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")18// Note: our tools can't always determine the correct BEGIN/END pairs unless19// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them20// to be in separate scopes.21//22// A common use case is to trace entire function scopes. This23// issues a trace BEGIN and END automatically:24// void doSomethingCostly() {25// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");26// ...27// }28//29// Additional parameters can be associated with an event:30// void doSomethingCostly2(int howMuch) {31// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",32// "howMuch", howMuch);33// ...34// }35//36// The trace system will automatically add to this information the37// current process id, thread id, and a timestamp in microseconds.38//39// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and40// ASYNC_END:41// [single threaded sender code]42// static int send_count = 0;43// ++send_count;44// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);45// Send(new MyMessage(send_count));46// [receive code]47// void OnMyMessage(send_count) {48// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);49// }50// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.51// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can52// be used for the ID parameter, and they will be mangled internally so that53// the same pointer on two different processes will not match. For example:54// class MyTracedClass {55// public:56// MyTracedClass() {57// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);58// }59// ~MyTracedClass() {60// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);61// }62// }63//64// Trace event also supports counters, which is a way to track a quantity65// as it varies over time. Counters are created with the following macro:66// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);67//68// Counters are process-specific. The macro itself can be issued from any69// thread, however.70//71// Sometimes, you want to track two counters at once. You can do this with two72// counter macros:73// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);74// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);75// Or you can do it with a combined macro:76// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",77// "bytesPinned", g_myCounterValue[0],78// "bytesAllocated", g_myCounterValue[1]);79// This indicates to the tracing UI that these counters should be displayed80// in a single graph, as a summed area chart.81//82// Since counters are in a global namespace, you may want to disembiguate with a83// unique ID, by using the TRACE_COUNTER_ID* variations.84//85// By default, trace collection is compiled in, but turned off at runtime.86// Collecting trace data is the responsibility of the embedding87// application. In Chrome's case, navigating to about:tracing will turn on88// tracing and display data collected across all active processes.89//90//91// Memory scoping note:92// Tracing copies the pointers, not the string content, of the strings passed93// in for category, name, and arg_names. Thus, the following code will94// cause problems:95// char* str = strdup("impprtantName");96// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!97// free(str); // Trace system now has dangling pointer98//99// To avoid this issue with the |name| and |arg_name| parameters, use the100// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.101// Notes: The category must always be in a long-lived char* (i.e. static const).102// The |arg_values|, when used, are always deep copied with the _COPY103// macros.104//105// When are string argument values copied:106// const char* arg_values are only referenced by default:107// TRACE_EVENT1("category", "name",108// "arg1", "literal string is only referenced");109// Use TRACE_STR_COPY to force copying of a const char*:110// TRACE_EVENT1("category", "name",111// "arg1", TRACE_STR_COPY("string will be copied"));112// std::string arg_values are always copied:113// TRACE_EVENT1("category", "name",114// "arg1", std::string("string will be copied"));115//116//117// Thread Safety:118// A thread safe singleton and mutex are used for thread safety. Category119// enabled flags are used to limit the performance impact when the system120// is not enabled.121//122// TRACE_EVENT macros first cache a pointer to a category. The categories are123// statically allocated and safe at all times, even after exit. Fetching a124// category is protected by the TraceLog::lock_. Multiple threads initializing125// the static variable is safe, as they will be serialized by the lock and126// multiple calls will return the same pointer to the category.127//128// Then the category_enabled flag is checked. This is a unsigned char, and129// not intended to be multithread safe. It optimizes access to addTraceEvent130// which is threadsafe internally via TraceLog::lock_. The enabled flag may131// cause some threads to incorrectly call or skip calling addTraceEvent near132// the time of the system being enabled or disabled. This is acceptable as133// we tolerate some data loss while the system is being enabled/disabled and134// because addTraceEvent is threadsafe internally and checks the enabled state135// again under lock.136//137// Without the use of these static category pointers and enabled flags all138// trace points would carry a significant performance cost of aquiring a lock139// and resolving the category.140141#ifndef COMMON_TRACE_EVENT_H_142#define COMMON_TRACE_EVENT_H_143144#include <string>145146#include "common/event_tracer.h"147148// By default, const char* argument values are assumed to have long-lived scope149// and will not be copied. Use this macro to force a const char* to be copied.150#define TRACE_STR_COPY(str) WebCore::TraceEvent::TraceStringWithCopy(str)151152// Records a pair of begin and end events called "name" for the current153// scope, with 0, 1 or 2 associated arguments. If the category is not154// enabled, then this does nothing.155// - category and name strings must have application lifetime (statics or156// literals). They may not include " chars.157#define TRACE_EVENT0(platform, category, name) \158INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name)159#define TRACE_EVENT1(platform, category, name, arg1_name, arg1_val) \160INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, arg1_name, arg1_val)161#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \162INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, arg1_name, arg1_val, arg2_name, \163arg2_val)164165// Records a single event called "name" immediately, with 0, 1 or 2166// associated arguments. If the category is not enabled, then this167// does nothing.168// - category and name strings must have application lifetime (statics or169// literals). They may not include " chars.170#define TRACE_EVENT_INSTANT0(platform, category, name) \171INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \172TRACE_EVENT_FLAG_NONE)173#define TRACE_EVENT_INSTANT1(platform, category, name, arg1_name, arg1_val) \174INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \175TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)176#define TRACE_EVENT_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \177INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \178TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)179#define TRACE_EVENT_COPY_INSTANT0(platform, category, name) \180INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \181TRACE_EVENT_FLAG_COPY)182#define TRACE_EVENT_COPY_INSTANT1(platform, category, name, arg1_name, arg1_val) \183INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \184TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)185#define TRACE_EVENT_COPY_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, \186arg2_val) \187INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \188TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)189190// Records a single BEGIN event called "name" immediately, with 0, 1 or 2191// associated arguments. If the category is not enabled, then this192// does nothing.193// - category and name strings must have application lifetime (statics or194// literals). They may not include " chars.195#define TRACE_EVENT_BEGIN0(platform, category, name) \196INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \197TRACE_EVENT_FLAG_NONE)198#define TRACE_EVENT_BEGIN1(platform, category, name, arg1_name, arg1_val) \199INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \200TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)201#define TRACE_EVENT_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \202INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \203TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)204#define TRACE_EVENT_COPY_BEGIN0(platform, category, name) \205INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \206TRACE_EVENT_FLAG_COPY)207#define TRACE_EVENT_COPY_BEGIN1(platform, category, name, arg1_name, arg1_val) \208INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \209TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)210#define TRACE_EVENT_COPY_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, \211arg2_val) \212INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \213TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)214215// Records a single END event for "name" immediately. If the category216// is not enabled, then this does nothing.217// - category and name strings must have application lifetime (statics or218// literals). They may not include " chars.219#define TRACE_EVENT_END0(platform, category, name) \220INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, TRACE_EVENT_FLAG_NONE)221#define TRACE_EVENT_END1(platform, category, name, arg1_name, arg1_val) \222INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \223TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)224#define TRACE_EVENT_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \225INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \226TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)227#define TRACE_EVENT_COPY_END0(platform, category, name) \228INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, TRACE_EVENT_FLAG_COPY)229#define TRACE_EVENT_COPY_END1(platform, category, name, arg1_name, arg1_val) \230INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \231TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)232#define TRACE_EVENT_COPY_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \233INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \234TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)235236// Records the value of a counter called "name" immediately. Value237// must be representable as a 32 bit integer.238// - category and name strings must have application lifetime (statics or239// literals). They may not include " chars.240#define TRACE_COUNTER1(platform, category, name, value) \241INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \242TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value))243#define TRACE_COPY_COUNTER1(platform, category, name, value) \244INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \245TRACE_EVENT_FLAG_COPY, "value", static_cast<int>(value))246247// Records the values of a multi-parted counter called "name" immediately.248// The UI will treat value1 and value2 as parts of a whole, displaying their249// values as a stacked-bar chart.250// - category and name strings must have application lifetime (statics or251// literals). They may not include " chars.252#define TRACE_COUNTER2(platform, category, name, value1_name, value1_val, value2_name, value2_val) \253INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \254TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \255value2_name, static_cast<int>(value2_val))256#define TRACE_COPY_COUNTER2(platform, category, name, value1_name, value1_val, value2_name, \257value2_val) \258INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \259TRACE_EVENT_FLAG_COPY, value1_name, static_cast<int>(value1_val), \260value2_name, static_cast<int>(value2_val))261262// Records the value of a counter called "name" immediately. Value263// must be representable as a 32 bit integer.264// - category and name strings must have application lifetime (statics or265// literals). They may not include " chars.266// - |id| is used to disambiguate counters with the same name. It must either267// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits268// will be xored with a hash of the process ID so that the same pointer on269// two different processes will not collide.270#define TRACE_COUNTER_ID1(platform, category, name, id, value) \271INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \272TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value))273#define TRACE_COPY_COUNTER_ID1(platform, category, name, id, value) \274INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \275TRACE_EVENT_FLAG_COPY, "value", static_cast<int>(value))276277// Records the values of a multi-parted counter called "name" immediately.278// The UI will treat value1 and value2 as parts of a whole, displaying their279// values as a stacked-bar chart.280// - category and name strings must have application lifetime (statics or281// literals). They may not include " chars.282// - |id| is used to disambiguate counters with the same name. It must either283// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits284// will be xored with a hash of the process ID so that the same pointer on285// two different processes will not collide.286#define TRACE_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \287value2_val) \288INTERNAL_TRACE_EVENT_ADD_WITH_ID( \289platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_NONE, \290value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))291#define TRACE_COPY_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \292value2_val) \293INTERNAL_TRACE_EVENT_ADD_WITH_ID( \294platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_COPY, \295value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))296297// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2298// associated arguments. If the category is not enabled, then this299// does nothing.300// - category and name strings must have application lifetime (statics or301// literals). They may not include " chars.302// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC303// events are considered to match if their category, name and id values all304// match. |id| must either be a pointer or an integer value up to 64 bits. If305// it's a pointer, the bits will be xored with a hash of the process ID so306// that the same pointer on two different processes will not collide.307// An asynchronous operation can consist of multiple phases. The first phase is308// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the309// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.310// An async operation can span threads and processes, but all events in that311// operation must use the same |name| and |id|. Each event can have its own312// args.313#define TRACE_EVENT_ASYNC_BEGIN0(platform, category, name, id) \314INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \315TRACE_EVENT_FLAG_NONE)316#define TRACE_EVENT_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val) \317INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \318TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)319#define TRACE_EVENT_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \320arg2_val) \321INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \322TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, \323arg2_val)324#define TRACE_EVENT_COPY_ASYNC_BEGIN0(platform, category, name, id) \325INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \326TRACE_EVENT_FLAG_COPY)327#define TRACE_EVENT_COPY_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val) \328INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \329TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)330#define TRACE_EVENT_COPY_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val, \331arg2_name, arg2_val) \332INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \333TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \334arg2_val)335336// Records a single ASYNC_STEP event for |step| immediately. If the category337// is not enabled, then this does nothing. The |name| and |id| must match the338// ASYNC_BEGIN event above. The |step| param identifies this step within the339// async event. This should be called at the beginning of the next phase of an340// asynchronous operation.341#define TRACE_EVENT_ASYNC_STEP0(platform, category, name, id, step) \342INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \343TRACE_EVENT_FLAG_NONE, "step", step)344#define TRACE_EVENT_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val) \345INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \346TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val)347#define TRACE_EVENT_COPY_ASYNC_STEP0(platform, category, name, id, step) \348INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \349TRACE_EVENT_FLAG_COPY, "step", step)350#define TRACE_EVENT_COPY_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val) \351INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \352TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val)353354// Records a single ASYNC_END event for "name" immediately. If the category355// is not enabled, then this does nothing.356#define TRACE_EVENT_ASYNC_END0(platform, category, name, id) \357INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \358TRACE_EVENT_FLAG_NONE)359#define TRACE_EVENT_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val) \360INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \361TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)362#define TRACE_EVENT_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \363arg2_val) \364INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \365TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, \366arg2_val)367#define TRACE_EVENT_COPY_ASYNC_END0(platform, category, name, id) \368INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \369TRACE_EVENT_FLAG_COPY)370#define TRACE_EVENT_COPY_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val) \371INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \372TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)373#define TRACE_EVENT_COPY_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \374arg2_val) \375INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \376TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \377arg2_val)378379// Creates a scope of a sampling state with the given category and name (both must380// be constant strings). These states are intended for a sampling profiler.381// Implementation note: we store category and name together because we don't382// want the inconsistency/expense of storing two pointers.383// |thread_bucket| is [0..2] and is used to statically isolate samples in one384// thread from others.385//386// { // The sampling state is set within this scope.387// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");388// ...;389// }390#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \391TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);392393// Returns a current sampling state of the given bucket.394// The format of the returned string is "category\0name".395#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \396TraceEvent::SamplingStateScope<bucket_number>::current()397398// Sets a current sampling state of the given bucket.399// |category| and |name| have to be constant strings.400#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \401TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)402403// Sets a current sampling state of the given bucket.404// |categoryAndName| doesn't need to be a constant string.405// The format of the string is "category\0name".406#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \407TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)408409// Syntactic sugars for the sampling tracing in the main thread.410#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \411TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)412#define TRACE_EVENT_GET_SAMPLING_STATE() TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)413#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \414TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)415#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \416TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)417418////////////////////////////////////////////////////////////////////////////////419// Implementation specific tracing API definitions.420421// Get a pointer to the enabled state of the given trace category. Only422// long-lived literal strings should be given as the category name. The returned423// pointer can be held permanently in a local static for example. If the424// unsigned char is non-zero, tracing is enabled. If tracing is enabled,425// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled426// between the load of the tracing state and the call to427// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out428// for best performance when tracing is disabled.429// const unsigned char*430// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)431#define TRACE_EVENT_API_GET_CATEGORY_ENABLED angle::GetTraceCategoryEnabledFlag432433// Add a trace event to the platform tracing system.434// void TRACE_EVENT_API_ADD_TRACE_EVENT(435// char phase,436// const unsigned char* category_enabled,437// const char* name,438// unsigned long long id,439// int num_args,440// const char** arg_names,441// const unsigned char* arg_types,442// const unsigned long long* arg_values,443// unsigned char flags)444#define TRACE_EVENT_API_ADD_TRACE_EVENT angle::AddTraceEvent445446////////////////////////////////////////////////////////////////////////////////447448// Implementation detail: trace event macros create temporary variables449// to keep instrumentation overhead low. These macros give each temporary450// variable a unique name based on the line number to prevent name collissions.451#define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b452#define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)453#define INTERNALTRACEEVENTUID(name_prefix) INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)454455// Implementation detail: internal macro to create static category.456#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category) \457static const unsigned char *INTERNALTRACEEVENTUID(catstatic) = \458TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, category);459460// Implementation detail: internal macro to create static category and add461// event if the category is enabled.462#define INTERNAL_TRACE_EVENT_ADD(platform, phase, category, name, flags, ...) \463do \464{ \465INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \466if (*INTERNALTRACEEVENTUID(catstatic)) \467{ \468gl::TraceEvent::addTraceEvent(platform, phase, INTERNALTRACEEVENTUID(catstatic), name, \469gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \470} \471} while (0)472473// Implementation detail: internal macro to create static category and add begin474// event if the category is enabled. Also adds the end event when the scope475// ends.476#define INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, ...) \477INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \478gl::TraceEvent::TraceEndOnScopeClose INTERNALTRACEEVENTUID(profileScope); \479do \480{ \481if (*INTERNALTRACEEVENTUID(catstatic)) \482{ \483gl::TraceEvent::addTraceEvent( \484platform, TRACE_EVENT_PHASE_BEGIN, INTERNALTRACEEVENTUID(catstatic), name, \485gl::TraceEvent::noEventId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \486INTERNALTRACEEVENTUID(profileScope) \487.initialize(platform, INTERNALTRACEEVENTUID(catstatic), name); \488} \489} while (0)490491// Implementation detail: internal macro to create static category and add492// event if the category is enabled.493#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, phase, category, name, id, flags, ...) \494do \495{ \496INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \497if (*INTERNALTRACEEVENTUID(catstatic)) \498{ \499unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \500gl::TraceEvent::TraceID traceEventTraceID(id, &traceEventFlags); \501gl::TraceEvent::addTraceEvent(platform, phase, INTERNALTRACEEVENTUID(catstatic), name, \502traceEventTraceID.data(), traceEventFlags, \503##__VA_ARGS__); \504} \505} while (0)506507// Notes regarding the following definitions:508// New values can be added and propagated to third party libraries, but existing509// definitions must never be changed, because third party libraries may use old510// definitions.511512// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.513#define TRACE_EVENT_PHASE_BEGIN ('B')514#define TRACE_EVENT_PHASE_END ('E')515#define TRACE_EVENT_PHASE_INSTANT ('I')516#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')517#define TRACE_EVENT_PHASE_ASYNC_STEP ('T')518#define TRACE_EVENT_PHASE_ASYNC_END ('F')519#define TRACE_EVENT_PHASE_METADATA ('M')520#define TRACE_EVENT_PHASE_COUNTER ('C')521#define TRACE_EVENT_PHASE_SAMPLE ('P')522523// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.524#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))525#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))526#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))527#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))528529// Type values for identifying types in the TraceValue union.530#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))531#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))532#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))533#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))534#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))535#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))536#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))537538namespace gl539{540541namespace TraceEvent542{543544// Specify these values when the corresponding argument of addTraceEvent is not545// used.546const int zeroNumArgs = 0;547const unsigned long long noEventId = 0;548549// TraceID encapsulates an ID that can either be an integer or pointer. Pointers550// are mangled with the Process ID so that they are unlikely to collide when the551// same pointer is used on different processes.552class TraceID553{554public:555explicit TraceID(const void *id, unsigned char *flags)556: m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id)))557{558*flags |= TRACE_EVENT_FLAG_MANGLE_ID;559}560explicit TraceID(unsigned long long id, unsigned char *flags) : m_data(id) { (void)flags; }561explicit TraceID(unsigned long id, unsigned char *flags) : m_data(id) { (void)flags; }562explicit TraceID(unsigned int id, unsigned char *flags) : m_data(id) { (void)flags; }563explicit TraceID(unsigned short id, unsigned char *flags) : m_data(id) { (void)flags; }564explicit TraceID(unsigned char id, unsigned char *flags) : m_data(id) { (void)flags; }565explicit TraceID(long long id, unsigned char *flags)566: m_data(static_cast<unsigned long long>(id))567{568(void)flags;569}570explicit TraceID(long id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id))571{572(void)flags;573}574explicit TraceID(int id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id))575{576(void)flags;577}578explicit TraceID(short id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id))579{580(void)flags;581}582explicit TraceID(signed char id, unsigned char *flags)583: m_data(static_cast<unsigned long long>(id))584{585(void)flags;586}587588unsigned long long data() const { return m_data; }589590private:591unsigned long long m_data;592};593594// Simple union to store various types as unsigned long long.595union TraceValueUnion596{597bool m_bool;598unsigned long long m_uint;599long long m_int;600double m_double;601const void *m_pointer;602const char *m_string;603};604605// Simple container for const char* that should be copied instead of retained.606class TraceStringWithCopy607{608public:609explicit TraceStringWithCopy(const char *str) : m_str(str) {}610operator const char *() const { return m_str; }611612private:613const char *m_str;614};615616// Define setTraceValue for each allowed type. It stores the type and617// value in the return arguments. This allows this API to avoid declaring any618// structures so that it is portable to third_party libraries.619#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, value_type_id) \620static inline void setTraceValue(actual_type arg, unsigned char *type, \621unsigned long long *value) \622{ \623TraceValueUnion typeValue; \624typeValue.union_member = arg; \625*type = value_type_id; \626*value = typeValue.m_uint; \627}628// Simpler form for int types that can be safely casted.629#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \630static inline void setTraceValue(actual_type arg, unsigned char *type, \631unsigned long long *value) \632{ \633*type = value_type_id; \634*value = static_cast<unsigned long long>(arg); \635}636637INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)638INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)639INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)640INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)641INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)642INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)643INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)644INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)645INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)646INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)647INTERNAL_DECLARE_SET_TRACE_VALUE(const void *, m_pointer, TRACE_VALUE_TYPE_POINTER)648INTERNAL_DECLARE_SET_TRACE_VALUE(const char *, m_string, TRACE_VALUE_TYPE_STRING)649INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy &,650m_string,651TRACE_VALUE_TYPE_COPY_STRING)652653#undef INTERNAL_DECLARE_SET_TRACE_VALUE654#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT655656static inline void setTraceValue(const std::string &arg,657unsigned char *type,658unsigned long long *value)659{660TraceValueUnion typeValue;661typeValue.m_string = arg.data();662*type = TRACE_VALUE_TYPE_COPY_STRING;663*value = typeValue.m_uint;664}665666// These addTraceEvent template functions are defined here instead of in the667// macro, because the arg values could be temporary string objects. In order to668// store pointers to the internal c_str and pass through to the tracing API, the669// arg values must live throughout these procedures.670671static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform,672char phase,673const unsigned char *categoryEnabled,674const char *name,675unsigned long long id,676unsigned char flags)677{678return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, zeroNumArgs,6790, 0, 0, flags);680}681682template <class ARG1_TYPE>683static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform,684char phase,685const unsigned char *categoryEnabled,686const char *name,687unsigned long long id,688unsigned char flags,689const char *arg1Name,690const ARG1_TYPE &arg1Val)691{692const int numArgs = 1;693unsigned char argTypes[1];694unsigned long long argValues[1];695setTraceValue(arg1Val, &argTypes[0], &argValues[0]);696return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, numArgs,697&arg1Name, argTypes, argValues, flags);698}699700template <class ARG1_TYPE, class ARG2_TYPE>701static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform,702char phase,703const unsigned char *categoryEnabled,704const char *name,705unsigned long long id,706unsigned char flags,707const char *arg1Name,708const ARG1_TYPE &arg1Val,709const char *arg2Name,710const ARG2_TYPE &arg2Val)711{712const int numArgs = 2;713const char *argNames[2] = {arg1Name, arg2Name};714unsigned char argTypes[2];715unsigned long long argValues[2];716setTraceValue(arg1Val, &argTypes[0], &argValues[0]);717setTraceValue(arg2Val, &argTypes[1], &argValues[1]);718return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, numArgs,719argNames, argTypes, argValues, flags);720}721722// Used by TRACE_EVENTx macro. Do not use directly.723class TraceEndOnScopeClose724{725public:726// Note: members of m_data intentionally left uninitialized. See initialize.727TraceEndOnScopeClose() : m_pdata(0) {}728~TraceEndOnScopeClose()729{730if (m_pdata)731addEventIfEnabled();732}733734void initialize(angle::PlatformMethods *platform,735const unsigned char *categoryEnabled,736const char *name)737{738m_data.platform = platform;739m_data.categoryEnabled = categoryEnabled;740m_data.name = name;741m_pdata = &m_data;742}743744private:745// Add the end event if the category is still enabled.746void addEventIfEnabled()747{748// Only called when m_pdata is non-null.749if (*m_pdata->categoryEnabled)750{751TRACE_EVENT_API_ADD_TRACE_EVENT(m_pdata->platform, TRACE_EVENT_PHASE_END,752m_pdata->categoryEnabled, m_pdata->name, noEventId,753zeroNumArgs, 0, 0, 0, TRACE_EVENT_FLAG_NONE);754}755}756757// This Data struct workaround is to avoid initializing all the members758// in Data during construction of this object, since this object is always759// constructed, even when tracing is disabled. If the members of Data were760// members of this class instead, compiler warnings occur about potential761// uninitialized accesses.762struct Data763{764angle::PlatformMethods *platform;765const unsigned char *categoryEnabled;766const char *name;767};768Data *m_pdata;769Data m_data;770};771772} // namespace TraceEvent773774} // namespace gl775776#endif777778779