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