Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: base/debug/trace_event_impl.cc

Issue 28593003: Avoid threading races on TraceSamplingThread's members (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed races on WaitableEvent Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event_impl.h" 5 #include "base/debug/trace_event_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base_switches.h" 9 #include "base/base_switches.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 public: 833 public:
834 TraceSamplingThread(); 834 TraceSamplingThread();
835 virtual ~TraceSamplingThread(); 835 virtual ~TraceSamplingThread();
836 836
837 // Implementation of PlatformThread::Delegate: 837 // Implementation of PlatformThread::Delegate:
838 virtual void ThreadMain() OVERRIDE; 838 virtual void ThreadMain() OVERRIDE;
839 839
840 static void DefaultSamplingCallback(TraceBucketData* bucekt_data); 840 static void DefaultSamplingCallback(TraceBucketData* bucekt_data);
841 841
842 void Stop(); 842 void Stop();
843 void InstallWaitableEventForSamplingTesting(WaitableEvent* waitable_event); 843 void WaitSamplingEventForTesting();
844 844
845 private: 845 private:
846 friend class TraceLog; 846 friend class TraceLog;
847 847
848 void GetSamples(); 848 void GetSamples();
849 // Not thread-safe. Once the ThreadMain has been called, this can no longer 849 // Not thread-safe. Once the ThreadMain has been called, this can no longer
850 // be called. 850 // be called.
851 void RegisterSampleBucket(TRACE_EVENT_API_ATOMIC_WORD* bucket, 851 void RegisterSampleBucket(TRACE_EVENT_API_ATOMIC_WORD* bucket,
852 const char* const name, 852 const char* const name,
853 TraceSampleCallback callback); 853 TraceSampleCallback callback);
854 // Splits a combined "category\0name" into the two component parts. 854 // Splits a combined "category\0name" into the two component parts.
855 static void ExtractCategoryAndName(const char* combined, 855 static void ExtractCategoryAndName(const char* combined,
856 const char** category, 856 const char** category,
857 const char** name); 857 const char** name);
858 std::vector<TraceBucketData> sample_buckets_; 858 std::vector<TraceBucketData> sample_buckets_;
859 bool thread_running_; 859 bool thread_running_;
860 scoped_ptr<CancellationFlag> cancellation_flag_; 860 CancellationFlag cancellation_flag_;
861 scoped_ptr<WaitableEvent> waitable_event_for_testing_; 861 WaitableEvent waitable_event_for_testing_;
862 }; 862 };
863 863
864 864
865 TraceSamplingThread::TraceSamplingThread() 865 TraceSamplingThread::TraceSamplingThread()
866 : thread_running_(false) { 866 : thread_running_(false),
867 cancellation_flag_.reset(new CancellationFlag); 867 waitable_event_for_testing_(false, false) {
868 } 868 }
869 869
870 TraceSamplingThread::~TraceSamplingThread() { 870 TraceSamplingThread::~TraceSamplingThread() {
871 } 871 }
872 872
873 void TraceSamplingThread::ThreadMain() { 873 void TraceSamplingThread::ThreadMain() {
874 PlatformThread::SetName("Sampling Thread"); 874 PlatformThread::SetName("Sampling Thread");
875 thread_running_ = true; 875 thread_running_ = true;
876 const int kSamplingFrequencyMicroseconds = 1000; 876 const int kSamplingFrequencyMicroseconds = 1000;
877 while (!cancellation_flag_->IsSet()) { 877 while (!cancellation_flag_.IsSet()) {
878 PlatformThread::Sleep( 878 PlatformThread::Sleep(
879 TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds)); 879 TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds));
880 GetSamples(); 880 GetSamples();
881 if (waitable_event_for_testing_.get()) 881 waitable_event_for_testing_.Signal();
882 waitable_event_for_testing_->Signal();
883 } 882 }
884 } 883 }
885 884
886 // static 885 // static
887 void TraceSamplingThread::DefaultSamplingCallback( 886 void TraceSamplingThread::DefaultSamplingCallback(
888 TraceBucketData* bucket_data) { 887 TraceBucketData* bucket_data) {
889 TRACE_EVENT_API_ATOMIC_WORD category_and_name = 888 TRACE_EVENT_API_ATOMIC_WORD category_and_name =
890 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); 889 TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket);
891 if (!category_and_name) 890 if (!category_and_name)
892 return; 891 return;
(...skipping 11 matching lines...) Expand all
904 for (size_t i = 0; i < sample_buckets_.size(); ++i) { 903 for (size_t i = 0; i < sample_buckets_.size(); ++i) {
905 TraceBucketData* bucket_data = &sample_buckets_[i]; 904 TraceBucketData* bucket_data = &sample_buckets_[i];
906 bucket_data->callback.Run(bucket_data); 905 bucket_data->callback.Run(bucket_data);
907 } 906 }
908 } 907 }
909 908
910 void TraceSamplingThread::RegisterSampleBucket( 909 void TraceSamplingThread::RegisterSampleBucket(
911 TRACE_EVENT_API_ATOMIC_WORD* bucket, 910 TRACE_EVENT_API_ATOMIC_WORD* bucket,
912 const char* const name, 911 const char* const name,
913 TraceSampleCallback callback) { 912 TraceSampleCallback callback) {
913 // Access to sample_buckets_ doesn't cause races with the sampling thread
914 // that uses the sample_buckets_, because it is guaranteed that
915 // RegisterSampleBucket is called before the sampling thread is created.
914 DCHECK(!thread_running_); 916 DCHECK(!thread_running_);
915 sample_buckets_.push_back(TraceBucketData(bucket, name, callback)); 917 sample_buckets_.push_back(TraceBucketData(bucket, name, callback));
916 } 918 }
917 919
918 // static 920 // static
919 void TraceSamplingThread::ExtractCategoryAndName(const char* combined, 921 void TraceSamplingThread::ExtractCategoryAndName(const char* combined,
920 const char** category, 922 const char** category,
921 const char** name) { 923 const char** name) {
922 *category = combined; 924 *category = combined;
923 *name = &combined[strlen(combined) + 1]; 925 *name = &combined[strlen(combined) + 1];
924 } 926 }
925 927
926 void TraceSamplingThread::Stop() { 928 void TraceSamplingThread::Stop() {
927 cancellation_flag_->Set(); 929 cancellation_flag_.Set();
928 } 930 }
929 931
930 void TraceSamplingThread::InstallWaitableEventForSamplingTesting( 932 void TraceSamplingThread::WaitSamplingEventForTesting() {
931 WaitableEvent* waitable_event) { 933 waitable_event_for_testing_.Wait();
932 waitable_event_for_testing_.reset(waitable_event);
933 } 934 }
934 935
935 TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket, 936 TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket,
936 const char* name, 937 const char* name,
937 TraceSampleCallback callback) 938 TraceSampleCallback callback)
938 : bucket(bucket), 939 : bucket(bucket),
939 bucket_name(name), 940 bucket_name(name),
940 callback(callback) { 941 callback(callback) {
941 } 942 }
942 943
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 it++) { 1996 it++) {
1996 if (it->second.empty()) 1997 if (it->second.empty())
1997 continue; 1998 continue;
1998 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), 1999 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
1999 it->first, 2000 it->first,
2000 "thread_name", "name", 2001 "thread_name", "name",
2001 it->second); 2002 it->second);
2002 } 2003 }
2003 } 2004 }
2004 2005
2005 void TraceLog::InstallWaitableEventForSamplingTesting( 2006 void TraceLog::WaitSamplingEventForTesting() {
2006 WaitableEvent* waitable_event) {
2007 if (!sampling_thread_) 2007 if (!sampling_thread_)
2008 return; 2008 return;
2009 sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); 2009 sampling_thread_->WaitSamplingEventForTesting();
2010 } 2010 }
2011 2011
2012 void TraceLog::DeleteForTesting() { 2012 void TraceLog::DeleteForTesting() {
2013 DeleteTraceLogForTesting::Delete(); 2013 DeleteTraceLogForTesting::Delete();
2014 } 2014 }
2015 2015
2016 TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) { 2016 TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) {
2017 return GetEventByHandleInternal(handle, NULL); 2017 return GetEventByHandleInternal(handle, NULL);
2018 } 2018 }
2019 2019
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 0, NULL, NULL, NULL, NULL, TRACE_EVENT_FLAG_NONE); 2281 0, NULL, NULL, NULL, NULL, TRACE_EVENT_FLAG_NONE);
2282 } 2282 }
2283 } 2283 }
2284 2284
2285 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { 2285 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
2286 if (*category_group_enabled_) 2286 if (*category_group_enabled_)
2287 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(event_handle_); 2287 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(event_handle_);
2288 } 2288 }
2289 2289
2290 } // namespace trace_event_internal 2290 } // namespace trace_event_internal
OLDNEW
« no previous file with comments | « base/debug/trace_event_impl.h ('k') | base/debug/trace_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698