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 
TraceSamplingThread()27 TraceSamplingThread::TraceSamplingThread()
28     : thread_running_(false),
29       waitable_event_for_testing_(WaitableEvent::ResetPolicy::AUTOMATIC,
30                                   WaitableEvent::InitialState::NOT_SIGNALED) {}
31 
~TraceSamplingThread()32 TraceSamplingThread::~TraceSamplingThread() {}
33 
ThreadMain()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
DefaultSamplingCallback(TraceBucketData * bucket_data)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 
GetSamples()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 
RegisterSampleBucket(TRACE_EVENT_API_ATOMIC_WORD * bucket,const char * const name,TraceSampleCallback callback)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
ExtractCategoryAndName(const char * combined,const char ** category,const char ** name)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 
Stop()91 void TraceSamplingThread::Stop() {
92   cancellation_flag_.Set();
93 }
94 
WaitSamplingEventForTesting()95 void TraceSamplingThread::WaitSamplingEventForTesting() {
96   waitable_event_for_testing_.Wait();
97 }
98 
TraceBucketData(base::subtle::AtomicWord * bucket,const char * name,TraceSampleCallback callback)99 TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket,
100                                  const char* name,
101                                  TraceSampleCallback callback)
102     : bucket(bucket), bucket_name(name), callback(callback) {}
103 
~TraceBucketData()104 TraceBucketData::~TraceBucketData() {}
105 
106 }  // namespace trace_event
107 }  // namespace base
108