Home | History | Annotate | Download | only in trace_event
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_TRACE_EVENT_TRACE_EVENT_H_
      6 #define BASE_TRACE_EVENT_TRACE_EVENT_H_
      7 
      8 // This header file defines implementation details of how the trace macros in
      9 // trace_event_common.h collect and store trace events. Anything not
     10 // implementation-specific should go in trace_macros_common.h instead of here.
     11 
     12 #include <stddef.h>
     13 #include <stdint.h>
     14 
     15 #include <string>
     16 
     17 #include "base/atomicops.h"
     18 #include "base/macros.h"
     19 #include "base/time/time.h"
     20 #include "base/trace_event/common/trace_event_common.h"
     21 #include "base/trace_event/trace_event_system_stats_monitor.h"
     22 #include "base/trace_event/trace_log.h"
     23 #include "build/build_config.h"
     24 
     25 // By default, const char* argument values are assumed to have long-lived scope
     26 // and will not be copied. Use this macro to force a const char* to be copied.
     27 #define TRACE_STR_COPY(str) \
     28     trace_event_internal::TraceStringWithCopy(str)
     29 
     30 // By default, uint64_t ID argument values are not mangled with the Process ID
     31 // in TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling.
     32 #define TRACE_ID_MANGLE(id) \
     33     trace_event_internal::TraceID::ForceMangle(id)
     34 
     35 // By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC
     36 // macros. Use this macro to prevent Process ID mangling.
     37 #define TRACE_ID_DONT_MANGLE(id) \
     38     trace_event_internal::TraceID::DontMangle(id)
     39 
     40 // Sets the current sample state to the given category and name (both must be
     41 // constant strings). These states are intended for a sampling profiler.
     42 // Implementation note: we store category and name together because we don't
     43 // want the inconsistency/expense of storing two pointers.
     44 // |thread_bucket| is [0..2] and is used to statically isolate samples in one
     45 // thread from others.
     46 #define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET( \
     47     bucket_number, category, name)                 \
     48         trace_event_internal::                     \
     49         TraceEventSamplingStateScope<bucket_number>::Set(category "\0" name)
     50 
     51 // Returns a current sampling state of the given bucket.
     52 #define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
     53     trace_event_internal::TraceEventSamplingStateScope<bucket_number>::Current()
     54 
     55 // Creates a scope of a sampling state of the given bucket.
     56 //
     57 // {  // The sampling state is set within this scope.
     58 //    TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
     59 //    ...;
     60 // }
     61 #define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(                   \
     62     bucket_number, category, name)                                      \
     63     trace_event_internal::TraceEventSamplingStateScope<bucket_number>   \
     64         traceEventSamplingScope(category "\0" name);
     65 
     66 #define TRACE_EVENT_API_CURRENT_THREAD_ID \
     67   static_cast<int>(base::PlatformThread::CurrentId())
     68 
     69 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
     70   UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) &           \
     71            (base::trace_event::TraceLog::ENABLED_FOR_RECORDING |         \
     72             base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK |    \
     73             base::trace_event::TraceLog::ENABLED_FOR_ETW_EXPORT))
     74 
     75 ////////////////////////////////////////////////////////////////////////////////
     76 // Implementation specific tracing API definitions.
     77 
     78 // Get a pointer to the enabled state of the given trace category. Only
     79 // long-lived literal strings should be given as the category group. The
     80 // returned pointer can be held permanently in a local static for example. If
     81 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
     82 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
     83 // between the load of the tracing state and the call to
     84 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
     85 // for best performance when tracing is disabled.
     86 // const unsigned char*
     87 //     TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
     88 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
     89     base::trace_event::TraceLog::GetCategoryGroupEnabled
     90 
     91 // Get the number of times traces have been recorded. This is used to implement
     92 // the TRACE_EVENT_IS_NEW_TRACE facility.
     93 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
     94 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
     95     base::trace_event::TraceLog::GetInstance()->GetNumTracesRecorded
     96 
     97 // Add a trace event to the platform tracing system.
     98 // base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
     99 //                    char phase,
    100 //                    const unsigned char* category_group_enabled,
    101 //                    const char* name,
    102 //                    unsigned long long id,
    103 //                    int num_args,
    104 //                    const char** arg_names,
    105 //                    const unsigned char* arg_types,
    106 //                    const unsigned long long* arg_values,
    107 //                    const scoped_refptr<ConvertableToTraceFormat>*
    108 //                    convertable_values,
    109 //                    unsigned int flags)
    110 #define TRACE_EVENT_API_ADD_TRACE_EVENT \
    111     base::trace_event::TraceLog::GetInstance()->AddTraceEvent
    112 
    113 // Add a trace event to the platform tracing system.
    114 // base::trace_event::TraceEventHandle
    115 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
    116 //                    char phase,
    117 //                    const unsigned char* category_group_enabled,
    118 //                    const char* name,
    119 //                    unsigned long long id,
    120 //                    unsigned long long bind_id,
    121 //                    int num_args,
    122 //                    const char** arg_names,
    123 //                    const unsigned char* arg_types,
    124 //                    const unsigned long long* arg_values,
    125 //                    const scoped_refptr<ConvertableToTraceFormat>*
    126 //                    convertable_values,
    127 //                    unsigned int flags)
    128 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID \
    129   base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId
    130 
    131 // Add a trace event to the platform tracing system overriding the pid.
    132 // The resulting event will have tid = pid == (process_id passed here).
    133 // base::trace_event::TraceEventHandle
    134 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
    135 //                    char phase,
    136 //                    const unsigned char* category_group_enabled,
    137 //                    const char* name,
    138 //                    unsigned long long id,
    139 //                    int process_id,
    140 //                    int num_args,
    141 //                    const char** arg_names,
    142 //                    const unsigned char* arg_types,
    143 //                    const unsigned long long* arg_values,
    144 //                    const scoped_refptr<ConvertableToTraceFormat>*
    145 //                    convertable_values,
    146 //                    unsigned int flags)
    147 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \
    148   base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId
    149 
    150 // Add a trace event to the platform tracing system.
    151 // base::trace_event::TraceEventHandle
    152 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
    153 //                    char phase,
    154 //                    const unsigned char* category_group_enabled,
    155 //                    const char* name,
    156 //                    unsigned long long id,
    157 //                    int thread_id,
    158 //                    const TimeTicks& timestamp,
    159 //                    int num_args,
    160 //                    const char** arg_names,
    161 //                    const unsigned char* arg_types,
    162 //                    const unsigned long long* arg_values,
    163 //                    const scoped_refptr<ConvertableToTraceFormat>*
    164 //                    convertable_values,
    165 //                    unsigned int flags)
    166 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
    167     base::trace_event::TraceLog::GetInstance() \
    168       ->AddTraceEventWithThreadIdAndTimestamp
    169 
    170 // Set the duration field of a COMPLETE trace event.
    171 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
    172 //     const unsigned char* category_group_enabled,
    173 //     const char* name,
    174 //     base::trace_event::TraceEventHandle id)
    175 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
    176     base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDuration
    177 
    178 // Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
    179 // on the convertable value will be called at flush time.
    180 // TRACE_EVENT_API_ADD_METADATA_EVENT(
    181 //   const char* event_name,
    182 //   const char* arg_name,
    183 //   scoped_refptr<ConvertableToTraceFormat> arg_value)
    184 #define TRACE_EVENT_API_ADD_METADATA_EVENT \
    185     trace_event_internal::AddMetadataEvent
    186 
    187 // Defines atomic operations used internally by the tracing system.
    188 #define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
    189 #define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var))
    190 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
    191     base::subtle::NoBarrier_Store(&(var), (value))
    192 
    193 // Defines visibility for classes in trace_event.h
    194 #define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT
    195 
    196 // The thread buckets for the sampling profiler.
    197 TRACE_EVENT_API_CLASS_EXPORT extern \
    198     TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3];
    199 
    200 #define TRACE_EVENT_API_THREAD_BUCKET(thread_bucket)                           \
    201     g_trace_state[thread_bucket]
    202 
    203 ////////////////////////////////////////////////////////////////////////////////
    204 
    205 // Implementation detail: trace event macros create temporary variables
    206 // to keep instrumentation overhead low. These macros give each temporary
    207 // variable a unique name based on the line number to prevent name collisions.
    208 #define INTERNAL_TRACE_EVENT_UID3(a,b) \
    209     trace_event_unique_##a##b
    210 #define INTERNAL_TRACE_EVENT_UID2(a,b) \
    211     INTERNAL_TRACE_EVENT_UID3(a,b)
    212 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \
    213     INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
    214 
    215 // Implementation detail: internal macro to create static category.
    216 // No barriers are needed, because this code is designed to operate safely
    217 // even when the unsigned char* points to garbage data (which may be the case
    218 // on processors without cache coherency).
    219 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
    220     category_group, atomic, category_group_enabled) \
    221     category_group_enabled = \
    222         reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( \
    223             atomic)); \
    224     if (UNLIKELY(!category_group_enabled)) { \
    225       category_group_enabled = \
    226           TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
    227       TRACE_EVENT_API_ATOMIC_STORE(atomic, \
    228           reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
    229               category_group_enabled)); \
    230     }
    231 
    232 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
    233     static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
    234     const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
    235     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \
    236         INTERNAL_TRACE_EVENT_UID(atomic), \
    237         INTERNAL_TRACE_EVENT_UID(category_group_enabled));
    238 
    239 // Implementation detail: internal macro to create static category and add
    240 // event if the category is enabled.
    241 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
    242     do { \
    243       INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
    244       if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
    245         trace_event_internal::AddTraceEvent( \
    246             phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
    247             trace_event_internal::kNoId, flags, \
    248             trace_event_internal::kNoId, ##__VA_ARGS__); \
    249       } \
    250     } while (0)
    251 
    252 // Implementation detail: internal macro to create static category and add begin
    253 // event if the category is enabled. Also adds the end event when the scope
    254 // ends.
    255 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
    256     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
    257     trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
    258     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
    259       base::trace_event::TraceEventHandle h = \
    260           trace_event_internal::AddTraceEvent( \
    261               TRACE_EVENT_PHASE_COMPLETE, \
    262               INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
    263               trace_event_internal::kNoId, TRACE_EVENT_FLAG_NONE, \
    264               trace_event_internal::kNoId, ##__VA_ARGS__); \
    265       INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
    266           INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
    267     }
    268 
    269 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW( \
    270     category_group, name, bind_id, flow_flags, ...) \
    271   INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
    272   trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
    273   if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
    274     unsigned int trace_event_flags = flow_flags; \
    275     trace_event_internal::TraceID trace_event_bind_id(bind_id, \
    276                                                       &trace_event_flags); \
    277     base::trace_event::TraceEventHandle h = \
    278         trace_event_internal::AddTraceEvent( \
    279             TRACE_EVENT_PHASE_COMPLETE, \
    280             INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
    281             trace_event_internal::kNoId, trace_event_flags, \
    282             trace_event_bind_id.data(), ##__VA_ARGS__); \
    283     INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
    284         INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
    285   }
    286 
    287 // Implementation detail: internal macro to create static category and add
    288 // event if the category is enabled.
    289 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
    290                                          flags, ...) \
    291     do { \
    292       INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
    293       if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
    294         unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
    295         trace_event_internal::TraceID trace_event_trace_id( \
    296             id, &trace_event_flags); \
    297         trace_event_internal::AddTraceEvent( \
    298             phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
    299             name, trace_event_trace_id.data(), trace_event_flags, \
    300             trace_event_internal::kNoId, ##__VA_ARGS__); \
    301       } \
    302     } while (0)
    303 
    304 // Implementation detail: internal macro to create static category and add
    305 // event if the category is enabled.
    306 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
    307                                                 timestamp, flags, ...)       \
    308   do {                                                                       \
    309     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                  \
    310     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {  \
    311       trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(           \
    312           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,     \
    313           trace_event_internal::kNoId, TRACE_EVENT_API_CURRENT_THREAD_ID,    \
    314           base::TimeTicks::FromInternalValue(timestamp),                     \
    315           flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,                       \
    316           trace_event_internal::kNoId, ##__VA_ARGS__);                       \
    317     }                                                                        \
    318   } while (0)
    319 
    320 // Implementation detail: internal macro to create static category and add
    321 // event if the category is enabled.
    322 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                   \
    323     phase, category_group, name, id, thread_id, timestamp, flags, ...)        \
    324   do {                                                                        \
    325     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                   \
    326     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {   \
    327       unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID;       \
    328       trace_event_internal::TraceID trace_event_trace_id(id,                  \
    329                                                          &trace_event_flags); \
    330       trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(            \
    331           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,      \
    332           trace_event_trace_id.data(), thread_id,                             \
    333           base::TimeTicks::FromInternalValue(timestamp),                      \
    334           trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,            \
    335           trace_event_internal::kNoId, ##__VA_ARGS__);                        \
    336     }                                                                         \
    337   } while (0)
    338 
    339 namespace trace_event_internal {
    340 
    341 // Specify these values when the corresponding argument of AddTraceEvent is not
    342 // used.
    343 const int kZeroNumArgs = 0;
    344 const unsigned long long kNoId = 0;
    345 
    346 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
    347 // are by default mangled with the Process ID so that they are unlikely to
    348 // collide when the same pointer is used on different processes.
    349 class TraceID {
    350  public:
    351   class DontMangle {
    352    public:
    353     explicit DontMangle(const void* id)
    354         : data_(static_cast<unsigned long long>(
    355               reinterpret_cast<uintptr_t>(id))) {}
    356     explicit DontMangle(unsigned long long id) : data_(id) {}
    357     explicit DontMangle(unsigned long id) : data_(id) {}
    358     explicit DontMangle(unsigned int id) : data_(id) {}
    359     explicit DontMangle(unsigned short id) : data_(id) {}
    360     explicit DontMangle(unsigned char id) : data_(id) {}
    361     explicit DontMangle(long long id)
    362         : data_(static_cast<unsigned long long>(id)) {}
    363     explicit DontMangle(long id)
    364         : data_(static_cast<unsigned long long>(id)) {}
    365     explicit DontMangle(int id)
    366         : data_(static_cast<unsigned long long>(id)) {}
    367     explicit DontMangle(short id)
    368         : data_(static_cast<unsigned long long>(id)) {}
    369     explicit DontMangle(signed char id)
    370         : data_(static_cast<unsigned long long>(id)) {}
    371     unsigned long long data() const { return data_; }
    372    private:
    373     unsigned long long data_;
    374   };
    375 
    376   class ForceMangle {
    377    public:
    378     explicit ForceMangle(unsigned long long id) : data_(id) {}
    379     explicit ForceMangle(unsigned long id) : data_(id) {}
    380     explicit ForceMangle(unsigned int id) : data_(id) {}
    381     explicit ForceMangle(unsigned short id) : data_(id) {}
    382     explicit ForceMangle(unsigned char id) : data_(id) {}
    383     explicit ForceMangle(long long id)
    384         : data_(static_cast<unsigned long long>(id)) {}
    385     explicit ForceMangle(long id)
    386         : data_(static_cast<unsigned long long>(id)) {}
    387     explicit ForceMangle(int id)
    388         : data_(static_cast<unsigned long long>(id)) {}
    389     explicit ForceMangle(short id)
    390         : data_(static_cast<unsigned long long>(id)) {}
    391     explicit ForceMangle(signed char id)
    392         : data_(static_cast<unsigned long long>(id)) {}
    393     unsigned long long data() const { return data_; }
    394    private:
    395     unsigned long long data_;
    396   };
    397   TraceID(const void* id, unsigned int* flags)
    398       : data_(static_cast<unsigned long long>(
    399               reinterpret_cast<uintptr_t>(id))) {
    400     *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
    401   }
    402   TraceID(ForceMangle id, unsigned int* flags) : data_(id.data()) {
    403     *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
    404   }
    405   TraceID(DontMangle id, unsigned int* /* flags */) : data_(id.data()) {
    406   }
    407   TraceID(unsigned long long id, unsigned int* flags)
    408       : data_(id) { (void)flags; }
    409   TraceID(unsigned long id, unsigned int* flags)
    410       : data_(id) { (void)flags; }
    411   TraceID(unsigned int id, unsigned int* flags)
    412       : data_(id) { (void)flags; }
    413   TraceID(unsigned short id, unsigned int* flags)
    414       : data_(id) { (void)flags; }
    415   TraceID(unsigned char id, unsigned int* flags)
    416       : data_(id) { (void)flags; }
    417   TraceID(long long id, unsigned int* flags)
    418       : data_(static_cast<unsigned long long>(id)) { (void)flags; }
    419   TraceID(long id, unsigned int* flags)
    420       : data_(static_cast<unsigned long long>(id)) { (void)flags; }
    421   TraceID(int id, unsigned int* flags)
    422       : data_(static_cast<unsigned long long>(id)) { (void)flags; }
    423   TraceID(short id, unsigned int* flags)
    424       : data_(static_cast<unsigned long long>(id)) { (void)flags; }
    425   TraceID(signed char id, unsigned int* flags)
    426       : data_(static_cast<unsigned long long>(id)) { (void)flags; }
    427 
    428   unsigned long long data() const { return data_; }
    429 
    430  private:
    431   unsigned long long data_;
    432 };
    433 
    434 // Simple union to store various types as unsigned long long.
    435 union TraceValueUnion {
    436   bool as_bool;
    437   unsigned long long as_uint;
    438   long long as_int;
    439   double as_double;
    440   const void* as_pointer;
    441   const char* as_string;
    442 };
    443 
    444 // Simple container for const char* that should be copied instead of retained.
    445 class TraceStringWithCopy {
    446  public:
    447   explicit TraceStringWithCopy(const char* str) : str_(str) {}
    448   const char* str() const { return str_; }
    449  private:
    450   const char* str_;
    451 };
    452 
    453 // Define SetTraceValue for each allowed type. It stores the type and
    454 // value in the return arguments. This allows this API to avoid declaring any
    455 // structures so that it is portable to third_party libraries.
    456 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
    457                                          arg_expression, \
    458                                          union_member, \
    459                                          value_type_id) \
    460     static inline void SetTraceValue( \
    461         actual_type arg, \
    462         unsigned char* type, \
    463         unsigned long long* value) { \
    464       TraceValueUnion type_value; \
    465       type_value.union_member = arg_expression; \
    466       *type = value_type_id; \
    467       *value = type_value.as_uint; \
    468     }
    469 // Simpler form for int types that can be safely casted.
    470 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
    471                                              value_type_id) \
    472     static inline void SetTraceValue( \
    473         actual_type arg, \
    474         unsigned char* type, \
    475         unsigned long long* value) { \
    476       *type = value_type_id; \
    477       *value = static_cast<unsigned long long>(arg); \
    478     }
    479 
    480 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
    481 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT)
    482 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
    483 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
    484 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
    485 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
    486 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT)
    487 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
    488 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
    489 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
    490 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL)
    491 INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double,
    492                                  TRACE_VALUE_TYPE_DOUBLE)
    493 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer,
    494                                  TRACE_VALUE_TYPE_POINTER)
    495 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string,
    496                                  TRACE_VALUE_TYPE_STRING)
    497 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(),
    498                                  as_string, TRACE_VALUE_TYPE_COPY_STRING)
    499 
    500 #undef INTERNAL_DECLARE_SET_TRACE_VALUE
    501 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
    502 
    503 // std::string version of SetTraceValue so that trace arguments can be strings.
    504 static inline void SetTraceValue(const std::string& arg,
    505                                  unsigned char* type,
    506                                  unsigned long long* value) {
    507   TraceValueUnion type_value;
    508   type_value.as_string = arg.c_str();
    509   *type = TRACE_VALUE_TYPE_COPY_STRING;
    510   *value = type_value.as_uint;
    511 }
    512 
    513 // base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier
    514 // to trace these types.
    515 static inline void SetTraceValue(const base::Time arg,
    516                                  unsigned char* type,
    517                                  unsigned long long* value) {
    518   *type = TRACE_VALUE_TYPE_INT;
    519   *value = arg.ToInternalValue();
    520 }
    521 
    522 static inline void SetTraceValue(const base::TimeTicks arg,
    523                                  unsigned char* type,
    524                                  unsigned long long* value) {
    525   *type = TRACE_VALUE_TYPE_INT;
    526   *value = arg.ToInternalValue();
    527 }
    528 
    529 static inline void SetTraceValue(const base::ThreadTicks arg,
    530                                  unsigned char* type,
    531                                  unsigned long long* value) {
    532   *type = TRACE_VALUE_TYPE_INT;
    533   *value = arg.ToInternalValue();
    534 }
    535 
    536 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
    537 // functions are defined here instead of in the macro, because the arg_values
    538 // could be temporary objects, such as std::string. In order to store
    539 // pointers to the internal c_str and pass through to the tracing API,
    540 // the arg_values must live throughout these procedures.
    541 
    542 static inline base::trace_event::TraceEventHandle
    543 AddTraceEventWithThreadIdAndTimestamp(
    544     char phase,
    545     const unsigned char* category_group_enabled,
    546     const char* name,
    547     unsigned long long id,
    548     int thread_id,
    549     const base::TimeTicks& timestamp,
    550     unsigned int flags,
    551     unsigned long long bind_id,
    552     const char* arg1_name,
    553     const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
    554         arg1_val) {
    555   const int num_args = 1;
    556   unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE };
    557   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    558       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    559       num_args, &arg1_name, arg_types, NULL, &arg1_val, flags);
    560 }
    561 
    562 template<class ARG1_TYPE>
    563 static inline base::trace_event::TraceEventHandle
    564 AddTraceEventWithThreadIdAndTimestamp(
    565     char phase,
    566     const unsigned char* category_group_enabled,
    567     const char* name,
    568     unsigned long long id,
    569     int thread_id,
    570     const base::TimeTicks& timestamp,
    571     unsigned int flags,
    572     unsigned long long bind_id,
    573     const char* arg1_name,
    574     const ARG1_TYPE& arg1_val,
    575     const char* arg2_name,
    576     const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
    577         arg2_val) {
    578   const int num_args = 2;
    579   const char* arg_names[2] = { arg1_name, arg2_name };
    580 
    581   unsigned char arg_types[2];
    582   unsigned long long arg_values[2];
    583   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    584   arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE;
    585 
    586   scoped_refptr<base::trace_event::ConvertableToTraceFormat>
    587       convertable_values[2];
    588   convertable_values[1] = arg2_val;
    589 
    590   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    591       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    592       num_args, arg_names, arg_types, arg_values, convertable_values, flags);
    593 }
    594 
    595 template<class ARG2_TYPE>
    596 static inline base::trace_event::TraceEventHandle
    597 AddTraceEventWithThreadIdAndTimestamp(
    598     char phase,
    599     const unsigned char* category_group_enabled,
    600     const char* name,
    601     unsigned long long id,
    602     int thread_id,
    603     const base::TimeTicks& timestamp,
    604     unsigned int flags,
    605     unsigned long long bind_id,
    606     const char* arg1_name,
    607     const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
    608     const char* arg2_name,
    609     const ARG2_TYPE& arg2_val) {
    610   const int num_args = 2;
    611   const char* arg_names[2] = { arg1_name, arg2_name };
    612 
    613   unsigned char arg_types[2];
    614   unsigned long long arg_values[2];
    615   arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE;
    616   arg_values[0] = 0;
    617   SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
    618 
    619   scoped_refptr<base::trace_event::ConvertableToTraceFormat>
    620       convertable_values[2];
    621   convertable_values[0] = arg1_val;
    622 
    623   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    624       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    625       num_args, arg_names, arg_types, arg_values, convertable_values, flags);
    626 }
    627 
    628 static inline base::trace_event::TraceEventHandle
    629 AddTraceEventWithThreadIdAndTimestamp(
    630     char phase,
    631     const unsigned char* category_group_enabled,
    632     const char* name,
    633     unsigned long long id,
    634     int thread_id,
    635     const base::TimeTicks& timestamp,
    636     unsigned int flags,
    637     unsigned long long bind_id,
    638     const char* arg1_name,
    639     const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
    640     const char* arg2_name,
    641     const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
    642         arg2_val) {
    643   const int num_args = 2;
    644   const char* arg_names[2] = { arg1_name, arg2_name };
    645   unsigned char arg_types[2] =
    646       { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE };
    647   scoped_refptr<base::trace_event::ConvertableToTraceFormat>
    648       convertable_values[2] = {arg1_val, arg2_val};
    649 
    650   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    651       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    652       num_args, arg_names, arg_types, NULL, convertable_values, flags);
    653 }
    654 
    655 static inline base::trace_event::TraceEventHandle
    656 AddTraceEventWithThreadIdAndTimestamp(
    657     char phase,
    658     const unsigned char* category_group_enabled,
    659     const char* name,
    660     unsigned long long id,
    661     int thread_id,
    662     const base::TimeTicks& timestamp,
    663     unsigned int flags,
    664     unsigned long long bind_id) {
    665   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    666       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    667       kZeroNumArgs, NULL, NULL, NULL, NULL, flags);
    668 }
    669 
    670 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    671     char phase,
    672     const unsigned char* category_group_enabled,
    673     const char* name,
    674     unsigned long long id,
    675     unsigned int flags,
    676     unsigned long long bind_id) {
    677   const int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    678   const base::TimeTicks now = base::TimeTicks::Now();
    679   return AddTraceEventWithThreadIdAndTimestamp(
    680       phase, category_group_enabled, name, id, thread_id, now, flags, bind_id);
    681 }
    682 
    683 template<class ARG1_TYPE>
    684 static inline base::trace_event::TraceEventHandle
    685 AddTraceEventWithThreadIdAndTimestamp(
    686     char phase,
    687     const unsigned char* category_group_enabled,
    688     const char* name,
    689     unsigned long long id,
    690     int thread_id,
    691     const base::TimeTicks& timestamp,
    692     unsigned int flags,
    693     unsigned long long bind_id,
    694     const char* arg1_name,
    695     const ARG1_TYPE& arg1_val) {
    696   const int num_args = 1;
    697   unsigned char arg_types[1];
    698   unsigned long long arg_values[1];
    699   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    700   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    701       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    702       num_args, &arg1_name, arg_types, arg_values, NULL, flags);
    703 }
    704 
    705 template<class ARG1_TYPE>
    706 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    707     char phase,
    708     const unsigned char* category_group_enabled,
    709     const char* name,
    710     unsigned long long id,
    711     unsigned int flags,
    712     unsigned long long bind_id,
    713     const char* arg1_name,
    714     const ARG1_TYPE& arg1_val) {
    715   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    716   base::TimeTicks now = base::TimeTicks::Now();
    717   return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled,
    718                                                name, id, thread_id, now, flags,
    719                                                bind_id, arg1_name, arg1_val);
    720 }
    721 
    722 template<class ARG1_TYPE, class ARG2_TYPE>
    723 static inline base::trace_event::TraceEventHandle
    724 AddTraceEventWithThreadIdAndTimestamp(
    725     char phase,
    726     const unsigned char* category_group_enabled,
    727     const char* name,
    728     unsigned long long id,
    729     int thread_id,
    730     const base::TimeTicks& timestamp,
    731     unsigned int flags,
    732     unsigned long long bind_id,
    733     const char* arg1_name,
    734     const ARG1_TYPE& arg1_val,
    735     const char* arg2_name,
    736     const ARG2_TYPE& arg2_val) {
    737   const int num_args = 2;
    738   const char* arg_names[2] = { arg1_name, arg2_name };
    739   unsigned char arg_types[2];
    740   unsigned long long arg_values[2];
    741   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    742   SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
    743   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    744       phase, category_group_enabled, name, id, bind_id, thread_id, timestamp,
    745       num_args, arg_names, arg_types, arg_values, NULL, flags);
    746 }
    747 
    748 template<class ARG1_TYPE, class ARG2_TYPE>
    749 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    750     char phase,
    751     const unsigned char* category_group_enabled,
    752     const char* name,
    753     unsigned long long id,
    754     unsigned int flags,
    755     unsigned long long bind_id,
    756     const char* arg1_name,
    757     const ARG1_TYPE& arg1_val,
    758     const char* arg2_name,
    759     const ARG2_TYPE& arg2_val) {
    760   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    761   base::TimeTicks now = base::TimeTicks::Now();
    762   return AddTraceEventWithThreadIdAndTimestamp(
    763       phase, category_group_enabled, name, id, thread_id, now, flags, bind_id,
    764       arg1_name, arg1_val, arg2_name, arg2_val);
    765 }
    766 
    767 static inline void AddMetadataEvent(
    768     const char* event_name,
    769     const char* arg_name,
    770     scoped_refptr<base::trace_event::ConvertableToTraceFormat> arg_value) {
    771   const char* arg_names[1] = {arg_name};
    772   scoped_refptr<base::trace_event::ConvertableToTraceFormat>
    773       convertable_values[1] = {arg_value};
    774   unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE};
    775   base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
    776       event_name,
    777       1,  // num_args
    778       arg_names, arg_types,
    779       nullptr,  // arg_values
    780       convertable_values, TRACE_EVENT_FLAG_NONE);
    781 }
    782 
    783 template <class ARG1_TYPE>
    784 static void AddMetadataEvent(const char* event_name,
    785                              const char* arg_name,
    786                              const ARG1_TYPE& arg_val) {
    787   const int num_args = 1;
    788   const char* arg_names[1] = {arg_name};
    789   unsigned char arg_types[1];
    790   unsigned long long arg_values[1];
    791   SetTraceValue(arg_val, &arg_types[0], &arg_values[0]);
    792 
    793   base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
    794       event_name, num_args, arg_names, arg_types, arg_values, nullptr,
    795       TRACE_EVENT_FLAG_NONE);
    796 }
    797 
    798 // Used by TRACE_EVENTx macros. Do not use directly.
    799 class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer {
    800  public:
    801   // Note: members of data_ intentionally left uninitialized. See Initialize.
    802   ScopedTracer() : p_data_(NULL) {}
    803 
    804   ~ScopedTracer() {
    805     if (p_data_ && *data_.category_group_enabled)
    806       TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
    807           data_.category_group_enabled, data_.name, data_.event_handle);
    808   }
    809 
    810   void Initialize(const unsigned char* category_group_enabled,
    811                   const char* name,
    812                   base::trace_event::TraceEventHandle event_handle) {
    813     data_.category_group_enabled = category_group_enabled;
    814     data_.name = name;
    815     data_.event_handle = event_handle;
    816     p_data_ = &data_;
    817   }
    818 
    819  private:
    820   // This Data struct workaround is to avoid initializing all the members
    821   // in Data during construction of this object, since this object is always
    822   // constructed, even when tracing is disabled. If the members of Data were
    823   // members of this class instead, compiler warnings occur about potential
    824   // uninitialized accesses.
    825   struct Data {
    826     const unsigned char* category_group_enabled;
    827     const char* name;
    828     base::trace_event::TraceEventHandle event_handle;
    829   };
    830   Data* p_data_;
    831   Data data_;
    832 };
    833 
    834 // Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly.
    835 class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient {
    836  public:
    837   ScopedTraceBinaryEfficient(const char* category_group, const char* name);
    838   ~ScopedTraceBinaryEfficient();
    839 
    840  private:
    841   const unsigned char* category_group_enabled_;
    842   const char* name_;
    843   base::trace_event::TraceEventHandle event_handle_;
    844 };
    845 
    846 // This macro generates less code then TRACE_EVENT0 but is also
    847 // slower to execute when tracing is off. It should generally only be
    848 // used with code that is seldom executed or conditionally executed
    849 // when debugging.
    850 // For now the category_group must be "gpu".
    851 #define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \
    852     trace_event_internal::ScopedTraceBinaryEfficient \
    853         INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name);
    854 
    855 // TraceEventSamplingStateScope records the current sampling state
    856 // and sets a new sampling state. When the scope exists, it restores
    857 // the sampling state having recorded.
    858 template<size_t BucketNumber>
    859 class TraceEventSamplingStateScope {
    860  public:
    861   TraceEventSamplingStateScope(const char* category_and_name) {
    862     previous_state_ = TraceEventSamplingStateScope<BucketNumber>::Current();
    863     TraceEventSamplingStateScope<BucketNumber>::Set(category_and_name);
    864   }
    865 
    866   ~TraceEventSamplingStateScope() {
    867     TraceEventSamplingStateScope<BucketNumber>::Set(previous_state_);
    868   }
    869 
    870   static inline const char* Current() {
    871     return reinterpret_cast<const char*>(TRACE_EVENT_API_ATOMIC_LOAD(
    872       g_trace_state[BucketNumber]));
    873   }
    874 
    875   static inline void Set(const char* category_and_name) {
    876     TRACE_EVENT_API_ATOMIC_STORE(
    877       g_trace_state[BucketNumber],
    878       reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(
    879         const_cast<char*>(category_and_name)));
    880   }
    881 
    882  private:
    883   const char* previous_state_;
    884 };
    885 
    886 }  // namespace trace_event_internal
    887 
    888 namespace base {
    889 namespace trace_event {
    890 
    891 template<typename IDType> class TraceScopedTrackableObject {
    892  public:
    893   TraceScopedTrackableObject(const char* category_group, const char* name,
    894       IDType id)
    895     : category_group_(category_group),
    896       name_(name),
    897       id_(id) {
    898     TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group_, name_, id_);
    899   }
    900 
    901   template <typename ArgType> void snapshot(ArgType snapshot) {
    902     TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group_, name_, id_, snapshot);
    903   }
    904 
    905   ~TraceScopedTrackableObject() {
    906     TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group_, name_, id_);
    907   }
    908 
    909  private:
    910   const char* category_group_;
    911   const char* name_;
    912   IDType id_;
    913 
    914   DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject);
    915 };
    916 
    917 }  // namespace trace_event
    918 }  // namespace base
    919 
    920 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_H_
    921