1 // Copyright (c) 2014 Google Inc. 2 // 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 6 // This header file defines implementation details of how the trace macros in 7 // SkTraceEventCommon.h collect and store trace events. Anything not 8 // implementation-specific should go in SkTraceEventCommon.h instead of here. 9 10 #ifndef SkTraceEvent_DEFINED 11 #define SkTraceEvent_DEFINED 12 13 #include "SkAtomics.h" 14 #include "SkEventTracer.h" 15 #include "SkTraceEventCommon.h" 16 17 //////////////////////////////////////////////////////////////////////////////// 18 // Implementation specific tracing API definitions. 19 20 // By default, const char* argument values are assumed to have long-lived scope 21 // and will not be copied. Use this macro to force a const char* to be copied. 22 #define TRACE_STR_COPY(str) \ 23 skia::tracing_internals::TraceStringWithCopy(str) 24 25 // By default, uint64 ID argument values are not mangled with the Process ID in 26 // TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling. 27 #define TRACE_ID_MANGLE(id) \ 28 skia::tracing_internals::TraceID::ForceMangle(id) 29 30 // By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC 31 // macros. Use this macro to prevent Process ID mangling. 32 #define TRACE_ID_DONT_MANGLE(id) \ 33 skia::tracing_internals::TraceID::DontMangle(id) 34 35 // Sets the current sample state to the given category and name (both must be 36 // constant strings). These states are intended for a sampling profiler. 37 // Implementation note: we store category and name together because we don't 38 // want the inconsistency/expense of storing two pointers. 39 // |thread_bucket| is [0..2] and is used to statically isolate samples in one 40 // thread from others. 41 #define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET( \ 42 bucket_number, category, name) \ 43 skia::tracing_internals:: \ 44 TraceEventSamplingStateScope<bucket_number>::Set(category "\0" name) 45 46 // Returns a current sampling state of the given bucket. 47 #define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ 48 skia::tracing_internals::TraceEventSamplingStateScope<bucket_number>::Current() 49 50 // Creates a scope of a sampling state of the given bucket. 51 // 52 // { // The sampling state is set within this scope. 53 // TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); 54 // ...; 55 // } 56 #define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET( \ 57 bucket_number, category, name) \ 58 skia::tracing_internals::TraceEventSamplingStateScope<bucket_number> \ 59 traceEventSamplingScope(category "\0" name); 60 61 62 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ 63 *INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ 64 (SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags | \ 65 SkEventTracer::kEnabledForEventCallback_CategoryGroupEnabledFlags) 66 67 // Get a pointer to the enabled state of the given trace category. Only 68 // long-lived literal strings should be given as the category group. The 69 // returned pointer can be held permanently in a local static for example. If 70 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled, 71 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled 72 // between the load of the tracing state and the call to 73 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out 74 // for best performance when tracing is disabled. 75 // const uint8_t* 76 // TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group) 77 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ 78 SkEventTracer::GetInstance()->getCategoryGroupEnabled 79 80 // Get the number of times traces have been recorded. This is used to implement 81 // the TRACE_EVENT_IS_NEW_TRACE facility. 82 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED() 83 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \ 84 SkEventTracer::GetInstance()->getNumTracesRecorded 85 86 // Add a trace event to the platform tracing system. 87 // SkEventTracer::Handle TRACE_EVENT_API_ADD_TRACE_EVENT( 88 // char phase, 89 // const uint8_t* category_group_enabled, 90 // const char* name, 91 // uint64_t id, 92 // int num_args, 93 // const char** arg_names, 94 // const uint8_t* arg_types, 95 // const uint64_t* arg_values, 96 // unsigned char flags) 97 #define TRACE_EVENT_API_ADD_TRACE_EVENT \ 98 SkEventTracer::GetInstance()->addTraceEvent 99 100 // Set the duration field of a COMPLETE trace event. 101 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( 102 // const uint8_t* category_group_enabled, 103 // const char* name, 104 // SkEventTracer::Handle id) 105 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ 106 SkEventTracer::GetInstance()->updateTraceEventDuration 107 108 #define TRACE_EVENT_API_ATOMIC_WORD intptr_t 109 #define TRACE_EVENT_API_ATOMIC_LOAD(var) sk_atomic_load(&var, sk_memory_order_relaxed) 110 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \ 111 sk_atomic_store(&var, value, sk_memory_order_relaxed) 112 113 // Defines visibility for classes in trace_event.h 114 #define TRACE_EVENT_API_CLASS_EXPORT SK_API 115 116 // The thread buckets for the sampling profiler. 117 TRACE_EVENT_API_CLASS_EXPORT extern \ 118 TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3]; 119 120 #define TRACE_EVENT_API_THREAD_BUCKET(thread_bucket) \ 121 g_trace_state[thread_bucket] 122 123 //////////////////////////////////////////////////////////////////////////////// 124 125 // Implementation detail: trace event macros create temporary variables 126 // to keep instrumentation overhead low. These macros give each temporary 127 // variable a unique name based on the line number to prevent name collisions. 128 #define INTERNAL_TRACE_EVENT_UID3(a,b) \ 129 trace_event_unique_##a##b 130 #define INTERNAL_TRACE_EVENT_UID2(a,b) \ 131 INTERNAL_TRACE_EVENT_UID3(a,b) 132 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \ 133 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) 134 135 // Implementation detail: internal macro to create static category. 136 // No barriers are needed, because this code is designed to operate safely 137 // even when the unsigned char* points to garbage data (which may be the case 138 // on processors without cache coherency). 139 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ 140 category_group, atomic, category_group_enabled) \ 141 category_group_enabled = \ 142 reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD( \ 143 atomic)); \ 144 if (!category_group_enabled) { \ 145 category_group_enabled = \ 146 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \ 147 TRACE_EVENT_API_ATOMIC_STORE(atomic, \ 148 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \ 149 category_group_enabled)); \ 150 } 151 152 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \ 153 static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \ 154 const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ 155 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \ 156 INTERNAL_TRACE_EVENT_UID(atomic), \ 157 INTERNAL_TRACE_EVENT_UID(category_group_enabled)); 158 159 // Implementation detail: internal macro to create static category and add 160 // event if the category is enabled. 161 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \ 162 do { \ 163 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 164 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 165 skia::tracing_internals::AddTraceEvent( \ 166 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 167 skia::tracing_internals::kNoEventId, flags, ##__VA_ARGS__); \ 168 } \ 169 } while (0) 170 171 // Implementation detail: internal macro to create static category and add begin 172 // event if the category is enabled. Also adds the end event when the scope 173 // ends. 174 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ 175 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 176 skia::tracing_internals::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ 177 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 178 SkEventTracer::Handle h = skia::tracing_internals::AddTraceEvent( \ 179 TRACE_EVENT_PHASE_COMPLETE, \ 180 INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ 181 name, skia::tracing_internals::kNoEventId, \ 182 TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ 183 INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ 184 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ 185 } 186 187 // Implementation detail: internal macro to create static category and add 188 // event if the category is enabled. 189 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \ 190 flags, ...) \ 191 do { \ 192 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 193 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 194 unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ 195 skia::tracing_internals::TraceID trace_event_trace_id( \ 196 id, &trace_event_flags); \ 197 skia::tracing_internals::AddTraceEvent( \ 198 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ 199 name, trace_event_trace_id.data(), trace_event_flags, \ 200 ##__VA_ARGS__); \ 201 } \ 202 } while (0) 203 204 // Implementation detail: internal macro to create static category and add 205 // event if the category is enabled. 206 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(phase, \ 207 category_group, name, id, thread_id, flags, ...) \ 208 do { \ 209 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 210 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 211 unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ 212 skia::tracing_internals::TraceID trace_event_trace_id( \ 213 id, &trace_event_flags); \ 214 skia::tracing_internals::AddTraceEventWithThreadIdAndTimestamp( \ 215 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ 216 name, trace_event_trace_id.data(), \ 217 thread_id, base::TimeTicks::FromInternalValue(timestamp), \ 218 trace_event_flags, ##__VA_ARGS__); \ 219 } \ 220 } while (0) 221 222 #define INTERNAL_TRACE_MEMORY(category, name) 223 224 namespace skia { 225 namespace tracing_internals { 226 227 // Specify these values when the corresponding argument of AddTraceEvent is not 228 // used. 229 const int kZeroNumArgs = 0; 230 const uint64_t kNoEventId = 0; 231 232 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers 233 // are by default mangled with the Process ID so that they are unlikely to 234 // collide when the same pointer is used on different processes. 235 class TraceID { 236 public: 237 class DontMangle { 238 public: 239 explicit DontMangle(const void* id) 240 : data_(static_cast<uint64_t>( 241 reinterpret_cast<uintptr_t>(id))) {} 242 explicit DontMangle(uint64_t id) : data_(id) {} 243 explicit DontMangle(unsigned int id) : data_(id) {} 244 explicit DontMangle(unsigned short id) : data_(id) {} 245 explicit DontMangle(unsigned char id) : data_(id) {} 246 explicit DontMangle(long long id) 247 : data_(static_cast<uint64_t>(id)) {} 248 explicit DontMangle(long id) 249 : data_(static_cast<uint64_t>(id)) {} 250 explicit DontMangle(int id) 251 : data_(static_cast<uint64_t>(id)) {} 252 explicit DontMangle(short id) 253 : data_(static_cast<uint64_t>(id)) {} 254 explicit DontMangle(signed char id) 255 : data_(static_cast<uint64_t>(id)) {} 256 uint64_t data() const { return data_; } 257 private: 258 uint64_t data_; 259 }; 260 261 class ForceMangle { 262 public: 263 explicit ForceMangle(uint64_t id) : data_(id) {} 264 explicit ForceMangle(unsigned int id) : data_(id) {} 265 explicit ForceMangle(unsigned short id) : data_(id) {} 266 explicit ForceMangle(unsigned char id) : data_(id) {} 267 explicit ForceMangle(long long id) 268 : data_(static_cast<uint64_t>(id)) {} 269 explicit ForceMangle(long id) 270 : data_(static_cast<uint64_t>(id)) {} 271 explicit ForceMangle(int id) 272 : data_(static_cast<uint64_t>(id)) {} 273 explicit ForceMangle(short id) 274 : data_(static_cast<uint64_t>(id)) {} 275 explicit ForceMangle(signed char id) 276 : data_(static_cast<uint64_t>(id)) {} 277 uint64_t data() const { return data_; } 278 private: 279 uint64_t data_; 280 }; 281 282 TraceID(const void* id, unsigned char* flags) 283 : data_(static_cast<uint64_t>( 284 reinterpret_cast<uintptr_t>(id))) { 285 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; 286 } 287 TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) { 288 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; 289 } 290 TraceID(DontMangle id, unsigned char* flags) : data_(id.data()) { 291 } 292 TraceID(uint64_t id, unsigned char* flags) 293 : data_(id) { (void)flags; } 294 TraceID(unsigned int id, unsigned char* flags) 295 : data_(id) { (void)flags; } 296 TraceID(unsigned short id, unsigned char* flags) 297 : data_(id) { (void)flags; } 298 TraceID(unsigned char id, unsigned char* flags) 299 : data_(id) { (void)flags; } 300 TraceID(long long id, unsigned char* flags) 301 : data_(static_cast<uint64_t>(id)) { (void)flags; } 302 TraceID(long id, unsigned char* flags) 303 : data_(static_cast<uint64_t>(id)) { (void)flags; } 304 TraceID(int id, unsigned char* flags) 305 : data_(static_cast<uint64_t>(id)) { (void)flags; } 306 TraceID(short id, unsigned char* flags) 307 : data_(static_cast<uint64_t>(id)) { (void)flags; } 308 TraceID(signed char id, unsigned char* flags) 309 : data_(static_cast<uint64_t>(id)) { (void)flags; } 310 311 uint64_t data() const { return data_; } 312 313 private: 314 uint64_t data_; 315 }; 316 317 // Simple union to store various types as uint64_t. 318 union TraceValueUnion { 319 bool as_bool; 320 uint64_t as_uint; 321 long long as_int; 322 double as_double; 323 const void* as_pointer; 324 const char* as_string; 325 }; 326 327 // Simple container for const char* that should be copied instead of retained. 328 class TraceStringWithCopy { 329 public: 330 explicit TraceStringWithCopy(const char* str) : str_(str) {} 331 operator const char* () const { return str_; } 332 private: 333 const char* str_; 334 }; 335 336 // Define SetTraceValue for each allowed type. It stores the type and 337 // value in the return arguments. This allows this API to avoid declaring any 338 // structures so that it is portable to third_party libraries. 339 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ 340 union_member, \ 341 value_type_id) \ 342 static inline void SetTraceValue( \ 343 actual_type arg, \ 344 unsigned char* type, \ 345 uint64_t* value) { \ 346 TraceValueUnion type_value; \ 347 type_value.union_member = arg; \ 348 *type = value_type_id; \ 349 *value = type_value.as_uint; \ 350 } 351 // Simpler form for int types that can be safely casted. 352 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ 353 value_type_id) \ 354 static inline void SetTraceValue( \ 355 actual_type arg, \ 356 unsigned char* type, \ 357 uint64_t* value) { \ 358 *type = value_type_id; \ 359 *value = static_cast<uint64_t>(arg); \ 360 } 361 362 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT) 363 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) 364 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) 365 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) 366 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) 367 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) 368 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) 369 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) 370 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) 371 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL) 372 INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE) 373 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer, 374 TRACE_VALUE_TYPE_POINTER) 375 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string, 376 TRACE_VALUE_TYPE_STRING) 377 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string, 378 TRACE_VALUE_TYPE_COPY_STRING) 379 380 #undef INTERNAL_DECLARE_SET_TRACE_VALUE 381 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT 382 383 // These AddTraceEvent and AddTraceEvent template 384 // functions are defined here instead of in the macro, because the arg_values 385 // could be temporary objects, such as std::string. In order to store 386 // pointers to the internal c_str and pass through to the tracing API, 387 // the arg_values must live throughout these procedures. 388 389 static inline SkEventTracer::Handle 390 AddTraceEvent( 391 char phase, 392 const uint8_t* category_group_enabled, 393 const char* name, 394 uint64_t id, 395 unsigned char flags) { 396 return TRACE_EVENT_API_ADD_TRACE_EVENT( 397 phase, category_group_enabled, name, id, 398 kZeroNumArgs, nullptr, nullptr, nullptr, flags); 399 } 400 401 template<class ARG1_TYPE> 402 static inline SkEventTracer::Handle 403 AddTraceEvent( 404 char phase, 405 const uint8_t* category_group_enabled, 406 const char* name, 407 uint64_t id, 408 unsigned char flags, 409 const char* arg1_name, 410 const ARG1_TYPE& arg1_val) { 411 const int num_args = 1; 412 uint8_t arg_types[1]; 413 uint64_t arg_values[1]; 414 SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); 415 return TRACE_EVENT_API_ADD_TRACE_EVENT( 416 phase, category_group_enabled, name, id, 417 num_args, &arg1_name, arg_types, arg_values, flags); 418 } 419 420 template<class ARG1_TYPE, class ARG2_TYPE> 421 static inline SkEventTracer::Handle 422 AddTraceEvent( 423 char phase, 424 const uint8_t* category_group_enabled, 425 const char* name, 426 uint64_t id, 427 unsigned char flags, 428 const char* arg1_name, 429 const ARG1_TYPE& arg1_val, 430 const char* arg2_name, 431 const ARG2_TYPE& arg2_val) { 432 const int num_args = 2; 433 const char* arg_names[2] = { arg1_name, arg2_name }; 434 unsigned char arg_types[2]; 435 uint64_t arg_values[2]; 436 SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); 437 SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); 438 return TRACE_EVENT_API_ADD_TRACE_EVENT( 439 phase, category_group_enabled, name, id, 440 num_args, arg_names, arg_types, arg_values, flags); 441 } 442 443 // Used by TRACE_EVENTx macros. Do not use directly. 444 class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { 445 public: 446 // Note: members of data_ intentionally left uninitialized. See Initialize. 447 ScopedTracer() : p_data_(nullptr) {} 448 449 ~ScopedTracer() { 450 if (p_data_ && *data_.category_group_enabled) 451 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( 452 data_.category_group_enabled, data_.name, data_.event_handle); 453 } 454 455 void Initialize(const uint8_t* category_group_enabled, 456 const char* name, 457 SkEventTracer::Handle event_handle) { 458 data_.category_group_enabled = category_group_enabled; 459 data_.name = name; 460 data_.event_handle = event_handle; 461 p_data_ = &data_; 462 } 463 464 private: 465 // This Data struct workaround is to avoid initializing all the members 466 // in Data during construction of this object, since this object is always 467 // constructed, even when tracing is disabled. If the members of Data were 468 // members of this class instead, compiler warnings occur about potential 469 // uninitialized accesses. 470 struct Data { 471 const uint8_t* category_group_enabled; 472 const char* name; 473 SkEventTracer::Handle event_handle; 474 }; 475 Data* p_data_; 476 Data data_; 477 }; 478 479 // Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly. 480 class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient { 481 public: 482 ScopedTraceBinaryEfficient(const char* category_group, const char* name); 483 ~ScopedTraceBinaryEfficient(); 484 485 private: 486 const uint8_t* category_group_enabled_; 487 const char* name_; 488 SkEventTracer::Handle event_handle_; 489 }; 490 491 // This macro generates less code then TRACE_EVENT0 but is also 492 // slower to execute when tracing is off. It should generally only be 493 // used with code that is seldom executed or conditionally executed 494 // when debugging. 495 // For now the category_group must be "gpu". 496 #define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \ 497 skia::tracing_internals::ScopedTraceBinaryEfficient \ 498 INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name); 499 500 // TraceEventSamplingStateScope records the current sampling state 501 // and sets a new sampling state. When the scope exists, it restores 502 // the sampling state having recorded. 503 template<size_t BucketNumber> 504 class TraceEventSamplingStateScope { 505 public: 506 TraceEventSamplingStateScope(const char* category_and_name) { 507 previous_state_ = TraceEventSamplingStateScope<BucketNumber>::Current(); 508 TraceEventSamplingStateScope<BucketNumber>::Set(category_and_name); 509 } 510 511 ~TraceEventSamplingStateScope() { 512 TraceEventSamplingStateScope<BucketNumber>::Set(previous_state_); 513 } 514 515 static inline const char* Current() { 516 return reinterpret_cast<const char*>(TRACE_EVENT_API_ATOMIC_LOAD( 517 g_trace_state[BucketNumber])); 518 } 519 520 static inline void Set(const char* category_and_name) { 521 TRACE_EVENT_API_ATOMIC_STORE( 522 g_trace_state[BucketNumber], 523 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( 524 const_cast<char*>(category_and_name))); 525 } 526 527 private: 528 const char* previous_state_; 529 }; 530 531 } // namespace tracing_internals 532 } // namespace skia 533 534 #endif 535