1 // Copyright 2015 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 #include <stddef.h> 6 7 #include "base/trace_event/trace_event_impl.h" 8 #include "base/trace_event/trace_log.h" 9 #include "base/trace_event/trace_sampling_thread.h" 10 11 namespace base { 12 namespace trace_event { 13 14 class TraceBucketData { 15 public: 16 TraceBucketData(base::subtle::AtomicWord* bucket, 17 const char* name, 18 TraceSampleCallback callback); 19 ~TraceBucketData(); 20 21 TRACE_EVENT_API_ATOMIC_WORD* bucket; 22 const char* bucket_name; 23 TraceSampleCallback callback; 24 }; 25 26 TraceSamplingThread::TraceSamplingThread() 27 : thread_running_(false), waitable_event_for_testing_(false, false) {} 28 29 TraceSamplingThread::~TraceSamplingThread() {} 30 31 void TraceSamplingThread::ThreadMain() { 32 PlatformThread::SetName("Sampling Thread"); 33 thread_running_ = true; 34 const int kSamplingFrequencyMicroseconds = 1000; 35 while (!cancellation_flag_.IsSet()) { 36 PlatformThread::Sleep( 37 TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds)); 38 GetSamples(); 39 waitable_event_for_testing_.Signal(); 40 } 41 } 42 43 // static 44 void TraceSamplingThread::DefaultSamplingCallback( 45 TraceBucketData* bucket_data) { 46 TRACE_EVENT_API_ATOMIC_WORD category_and_name = 47 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); 48 if (!category_and_name) 49 return; 50 const char* const combined = 51 reinterpret_cast<const char* const>(category_and_name); 52 const char* category_group; 53 const char* name; 54 ExtractCategoryAndName(combined, &category_group, &name); 55 TRACE_EVENT_API_ADD_TRACE_EVENT( 56 TRACE_EVENT_PHASE_SAMPLE, 57 TraceLog::GetCategoryGroupEnabled(category_group), name, 0, 0, NULL, NULL, 58 NULL, NULL, 0); 59 } 60 61 void TraceSamplingThread::GetSamples() { 62 for (size_t i = 0; i < sample_buckets_.size(); ++i) { 63 TraceBucketData* bucket_data = &sample_buckets_[i]; 64 bucket_data->callback.Run(bucket_data); 65 } 66 } 67 68 void TraceSamplingThread::RegisterSampleBucket( 69 TRACE_EVENT_API_ATOMIC_WORD* bucket, 70 const char* const name, 71 TraceSampleCallback callback) { 72 // Access to sample_buckets_ doesn't cause races with the sampling thread 73 // that uses the sample_buckets_, because it is guaranteed that 74 // RegisterSampleBucket is called before the sampling thread is created. 75 DCHECK(!thread_running_); 76 sample_buckets_.push_back(TraceBucketData(bucket, name, callback)); 77 } 78 79 // static 80 void TraceSamplingThread::ExtractCategoryAndName(const char* combined, 81 const char** category, 82 const char** name) { 83 *category = combined; 84 *name = &combined[strlen(combined) + 1]; 85 } 86 87 void TraceSamplingThread::Stop() { 88 cancellation_flag_.Set(); 89 } 90 91 void TraceSamplingThread::WaitSamplingEventForTesting() { 92 waitable_event_for_testing_.Wait(); 93 } 94 95 TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket, 96 const char* name, 97 TraceSampleCallback callback) 98 : bucket(bucket), bucket_name(name), callback(callback) {} 99 100 TraceBucketData::~TraceBucketData() {} 101 102 } // namespace trace_event 103 } // namespace base 104