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

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

Issue 16829002: Notify TraceLog observers outside of the lock (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months 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/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/leak_annotations.h" 10 #include "base/debug/leak_annotations.h"
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 903
904 void TraceLog::GetKnownCategoryGroups( 904 void TraceLog::GetKnownCategoryGroups(
905 std::vector<std::string>* category_groups) { 905 std::vector<std::string>* category_groups) {
906 AutoLock lock(lock_); 906 AutoLock lock(lock_);
907 for (int i = g_num_builtin_categories; i < g_category_index; i++) 907 for (int i = g_num_builtin_categories; i < g_category_index; i++)
908 category_groups->push_back(g_category_groups[i]); 908 category_groups->push_back(g_category_groups[i]);
909 } 909 }
910 910
911 void TraceLog::SetEnabled(const CategoryFilter& category_filter, 911 void TraceLog::SetEnabled(const CategoryFilter& category_filter,
912 Options options) { 912 Options options) {
913 AutoLock lock(lock_); 913 std::vector<EnabledStateObserver*> observer_list;
914 {
915 AutoLock lock(lock_);
914 916
915 if (enable_count_++ > 0) { 917 if (enable_count_++ > 0) {
916 if (options != trace_options_) { 918 if (options != trace_options_) {
917 DLOG(ERROR) << "Attemting to re-enable tracing with a different " 919 DLOG(ERROR) << "Attemting to re-enable tracing with a different "
918 << "set of options."; 920 << "set of options.";
921 }
922
923 category_filter_.Merge(category_filter);
924 EnableIncludedCategoryGroups();
925 return;
919 } 926 }
920 927
921 category_filter_.Merge(category_filter); 928 if (options != trace_options_) {
929 trace_options_ = options;
930 logged_events_.reset(GetTraceBuffer());
931 }
932
933 if (dispatching_to_observer_list_) {
934 DLOG(ERROR) <<
935 "Cannot manipulate TraceLog::Enabled state from an observer.";
936 return;
937 }
938
939 num_traces_recorded_++;
940
941 category_filter_ = CategoryFilter(category_filter);
922 EnableIncludedCategoryGroups(); 942 EnableIncludedCategoryGroups();
923 return; 943
944 // Not supported in split-dll build. http://crbug.com/237249
945 #if !defined(CHROME_SPLIT_DLL)
946 if (options & ENABLE_SAMPLING) {
947 sampling_thread_.reset(new TraceSamplingThread);
948 sampling_thread_->RegisterSampleBucket(
949 &g_trace_state0,
950 "bucket0",
951 Bind(&TraceSamplingThread::DefaultSampleCallback));
952 sampling_thread_->RegisterSampleBucket(
953 &g_trace_state1,
954 "bucket1",
955 Bind(&TraceSamplingThread::DefaultSampleCallback));
956 sampling_thread_->RegisterSampleBucket(
957 &g_trace_state2,
958 "bucket2",
959 Bind(&TraceSamplingThread::DefaultSampleCallback));
960 if (!PlatformThread::Create(
961 0, sampling_thread_.get(), &sampling_thread_handle_)) {
962 DCHECK(false) << "failed to create thread";
963 }
964 }
965 #endif
966
967 dispatching_to_observer_list_ = true;
968 observer_list = enabled_state_observer_list_;
924 } 969 }
970 // Notify observers outside the lock in case they trigger trace events.
971 for (size_t i = 0; i < observer_list.size(); ++i)
972 observer_list[i]->OnTraceLogEnabled();
925 973
926 if (options != trace_options_) { 974 {
927 trace_options_ = options; 975 AutoLock lock(lock_);
928 logged_events_.reset(GetTraceBuffer()); 976 dispatching_to_observer_list_ = false;
929 } 977 }
930
931 if (dispatching_to_observer_list_) {
932 DLOG(ERROR) <<
933 "Cannot manipulate TraceLog::Enabled state from an observer.";
934 return;
935 }
936
937 num_traces_recorded_++;
938
939 dispatching_to_observer_list_ = true;
940 FOR_EACH_OBSERVER(EnabledStateChangedObserver, enabled_state_observer_list_,
941 OnTraceLogWillEnable());
942 dispatching_to_observer_list_ = false;
943
944 category_filter_ = CategoryFilter(category_filter);
945 EnableIncludedCategoryGroups();
946
947 // Not supported in split-dll build. http://crbug.com/237249
948 #if !defined(CHROME_SPLIT_DLL)
949 if (options & ENABLE_SAMPLING) {
950 sampling_thread_.reset(new TraceSamplingThread);
951 sampling_thread_->RegisterSampleBucket(
952 &g_trace_state0,
953 "bucket0",
954 Bind(&TraceSamplingThread::DefaultSampleCallback));
955 sampling_thread_->RegisterSampleBucket(
956 &g_trace_state1,
957 "bucket1",
958 Bind(&TraceSamplingThread::DefaultSampleCallback));
959 sampling_thread_->RegisterSampleBucket(
960 &g_trace_state2,
961 "bucket2",
962 Bind(&TraceSamplingThread::DefaultSampleCallback));
963 if (!PlatformThread::Create(
964 0, sampling_thread_.get(), &sampling_thread_handle_)) {
965 DCHECK(false) << "failed to create thread";
966 }
967 }
968 #endif
969 } 978 }
970 979
971 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { 980 const CategoryFilter& TraceLog::GetCurrentCategoryFilter() {
972 AutoLock lock(lock_); 981 AutoLock lock(lock_);
973 DCHECK(enable_count_ > 0); 982 DCHECK(enable_count_ > 0);
974 return category_filter_; 983 return category_filter_;
975 } 984 }
976 985
977 void TraceLog::SetDisabled() { 986 void TraceLog::SetDisabled() {
978 AutoLock lock(lock_); 987 std::vector<EnabledStateObserver*> observer_list;
979 DCHECK(enable_count_ > 0); 988 {
980 if (--enable_count_ != 0) 989 AutoLock lock(lock_);
981 return; 990 DCHECK(enable_count_ > 0);
991 if (--enable_count_ != 0)
992 return;
982 993
983 if (dispatching_to_observer_list_) { 994 if (dispatching_to_observer_list_) {
984 DLOG(ERROR) 995 DLOG(ERROR)
985 << "Cannot manipulate TraceLog::Enabled state from an observer."; 996 << "Cannot manipulate TraceLog::Enabled state from an observer.";
986 return; 997 return;
998 }
999
1000 if (sampling_thread_.get()) {
1001 // Stop the sampling thread.
1002 sampling_thread_->Stop();
1003 lock_.Release();
1004 PlatformThread::Join(sampling_thread_handle_);
1005 lock_.Acquire();
1006 sampling_thread_handle_ = PlatformThreadHandle();
1007 sampling_thread_.reset();
1008 }
1009
1010 category_filter_.Clear();
1011 watch_category_ = NULL;
1012 watch_event_name_ = "";
1013 for (int i = 0; i < g_category_index; i++)
1014 SetCategoryGroupEnabled(i, false);
1015 AddThreadNameMetadataEvents();
1016
1017 dispatching_to_observer_list_ = true;
1018 observer_list = enabled_state_observer_list_;
987 } 1019 }
988 1020
989 if (sampling_thread_.get()) { 1021 // Dispatch to observers outside the lock in case the observer triggers a
990 // Stop the sampling thread. 1022 // trace event.
991 sampling_thread_->Stop(); 1023 for (size_t i = 0; i < observer_list.size(); ++i)
992 lock_.Release(); 1024 observer_list[i]->OnTraceLogDisabled();
993 PlatformThread::Join(sampling_thread_handle_); 1025
994 lock_.Acquire(); 1026 {
995 sampling_thread_handle_ = PlatformThreadHandle(); 1027 AutoLock lock(lock_);
996 sampling_thread_.reset(); 1028 dispatching_to_observer_list_ = false;
997 } 1029 }
998
999 dispatching_to_observer_list_ = true;
1000 FOR_EACH_OBSERVER(EnabledStateChangedObserver,
1001 enabled_state_observer_list_,
1002 OnTraceLogWillDisable());
1003 dispatching_to_observer_list_ = false;
1004
1005 category_filter_.Clear();
1006 watch_category_ = NULL;
1007 watch_event_name_ = "";
1008 for (int i = 0; i < g_category_index; i++)
1009 SetCategoryGroupEnabled(i, false);
1010 AddThreadNameMetadataEvents();
1011 } 1030 }
1012 1031
1013 int TraceLog::GetNumTracesRecorded() { 1032 int TraceLog::GetNumTracesRecorded() {
1014 AutoLock lock(lock_); 1033 AutoLock lock(lock_);
1015 if (enable_count_ == 0) 1034 if (enable_count_ == 0)
1016 return -1; 1035 return -1;
1017 return num_traces_recorded_; 1036 return num_traces_recorded_;
1018 } 1037 }
1019 1038
1020 void TraceLog::AddEnabledStateObserver(EnabledStateChangedObserver* listener) { 1039 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {
1021 enabled_state_observer_list_.AddObserver(listener); 1040 enabled_state_observer_list_.push_back(listener);
1022 } 1041 }
1023 1042
1024 void TraceLog::RemoveEnabledStateObserver( 1043 void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
1025 EnabledStateChangedObserver* listener) { 1044 std::vector<EnabledStateObserver*>::iterator it =
1026 enabled_state_observer_list_.RemoveObserver(listener); 1045 std::find(enabled_state_observer_list_.begin(),
1046 enabled_state_observer_list_.end(),
1047 listener);
1048 if (it != enabled_state_observer_list_.end())
1049 enabled_state_observer_list_.erase(it);
1027 } 1050 }
1028 1051
1029 float TraceLog::GetBufferPercentFull() const { 1052 float TraceLog::GetBufferPercentFull() const {
1030 return (float)((double)logged_events_->Size()/(double)kTraceEventBufferSize); 1053 return (float)((double)logged_events_->Size()/(double)kTraceEventBufferSize);
1031 } 1054 }
1032 1055
1033 void TraceLog::SetNotificationCallback( 1056 void TraceLog::SetNotificationCallback(
1034 const TraceLog::NotificationCallback& cb) { 1057 const TraceLog::NotificationCallback& cb) {
1035 AutoLock lock(lock_); 1058 AutoLock lock(lock_);
1036 notification_callback_ = cb; 1059 notification_callback_ = cb;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 unsigned long long offset_basis = 14695981039346656037ull; 1336 unsigned long long offset_basis = 14695981039346656037ull;
1314 unsigned long long fnv_prime = 1099511628211ull; 1337 unsigned long long fnv_prime = 1099511628211ull;
1315 unsigned long long pid = static_cast<unsigned long long>(process_id_); 1338 unsigned long long pid = static_cast<unsigned long long>(process_id_);
1316 process_id_hash_ = (offset_basis ^ pid) * fnv_prime; 1339 process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
1317 } 1340 }
1318 1341
1319 void TraceLog::SetTimeOffset(TimeDelta offset) { 1342 void TraceLog::SetTimeOffset(TimeDelta offset) {
1320 time_offset_ = offset; 1343 time_offset_ = offset;
1321 } 1344 }
1322 1345
1346 size_t TraceLog::GetObserverCountForTest() const {
1347 return enabled_state_observer_list_.size();
1348 }
1349
1323 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( 1350 bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
1324 const std::string& str) { 1351 const std::string& str) {
1325 return str.empty() || 1352 return str.empty() ||
1326 str.at(0) == ' ' || 1353 str.at(0) == ' ' ||
1327 str.at(str.length() - 1) == ' '; 1354 str.at(str.length() - 1) == ' ';
1328 } 1355 }
1329 1356
1330 bool CategoryFilter::DoesCategoryGroupContainCategory( 1357 bool CategoryFilter::DoesCategoryGroupContainCategory(
1331 const char* category_group, 1358 const char* category_group,
1332 const char* category) const { 1359 const char* category) const {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 0, // num_args 1547 0, // num_args
1521 NULL, // arg_names 1548 NULL, // arg_names
1522 NULL, // arg_types 1549 NULL, // arg_types
1523 NULL, // arg_values 1550 NULL, // arg_values
1524 NULL, // convertable values 1551 NULL, // convertable values
1525 TRACE_EVENT_FLAG_NONE); // flags 1552 TRACE_EVENT_FLAG_NONE); // flags
1526 } 1553 }
1527 } 1554 }
1528 1555
1529 } // namespace trace_event_internal 1556 } // 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