diff options
Diffstat (limited to 'base/trace_event/trace_sampling_thread.cc')
-rw-r--r-- | base/trace_event/trace_sampling_thread.cc | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/base/trace_event/trace_sampling_thread.cc b/base/trace_event/trace_sampling_thread.cc new file mode 100644 index 0000000000..5a0d2f8a02 --- /dev/null +++ b/base/trace_event/trace_sampling_thread.cc @@ -0,0 +1,107 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> + +#include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_event_impl.h" +#include "base/trace_event/trace_log.h" +#include "base/trace_event/trace_sampling_thread.h" + +namespace base { +namespace trace_event { + +class TraceBucketData { + public: + TraceBucketData(base::subtle::AtomicWord* bucket, + const char* name, + TraceSampleCallback callback); + ~TraceBucketData(); + + TRACE_EVENT_API_ATOMIC_WORD* bucket; + const char* bucket_name; + TraceSampleCallback callback; +}; + +TraceSamplingThread::TraceSamplingThread() + : thread_running_(false), + waitable_event_for_testing_(WaitableEvent::ResetPolicy::AUTOMATIC, + WaitableEvent::InitialState::NOT_SIGNALED) {} + +TraceSamplingThread::~TraceSamplingThread() {} + +void TraceSamplingThread::ThreadMain() { + PlatformThread::SetName("Sampling Thread"); + thread_running_ = true; + const int kSamplingFrequencyMicroseconds = 1000; + while (!cancellation_flag_.IsSet()) { + PlatformThread::Sleep( + TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds)); + GetSamples(); + waitable_event_for_testing_.Signal(); + } +} + +// static +void TraceSamplingThread::DefaultSamplingCallback( + TraceBucketData* bucket_data) { + TRACE_EVENT_API_ATOMIC_WORD category_and_name = + TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); + if (!category_and_name) + return; + const char* const combined = + reinterpret_cast<const char* const>(category_and_name); + const char* category_group; + const char* name; + ExtractCategoryAndName(combined, &category_group, &name); + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_SAMPLE, + TraceLog::GetCategoryGroupEnabled(category_group), name, + trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0, + NULL, NULL, NULL, NULL, 0); +} + +void TraceSamplingThread::GetSamples() { + for (size_t i = 0; i < sample_buckets_.size(); ++i) { + TraceBucketData* bucket_data = &sample_buckets_[i]; + bucket_data->callback.Run(bucket_data); + } +} + +void TraceSamplingThread::RegisterSampleBucket( + TRACE_EVENT_API_ATOMIC_WORD* bucket, + const char* const name, + TraceSampleCallback callback) { + // Access to sample_buckets_ doesn't cause races with the sampling thread + // that uses the sample_buckets_, because it is guaranteed that + // RegisterSampleBucket is called before the sampling thread is created. + DCHECK(!thread_running_); + sample_buckets_.push_back(TraceBucketData(bucket, name, callback)); +} + +// static +void TraceSamplingThread::ExtractCategoryAndName(const char* combined, + const char** category, + const char** name) { + *category = combined; + *name = &combined[strlen(combined) + 1]; +} + +void TraceSamplingThread::Stop() { + cancellation_flag_.Set(); +} + +void TraceSamplingThread::WaitSamplingEventForTesting() { + waitable_event_for_testing_.Wait(); +} + +TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket, + const char* name, + TraceSampleCallback callback) + : bucket(bucket), bucket_name(name), callback(callback) {} + +TraceBucketData::~TraceBucketData() {} + +} // namespace trace_event +} // namespace base |