OLD | NEW |
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 const int g_category_trace_event_overhead = 3; | 92 const int g_category_trace_event_overhead = 3; |
93 const int g_num_builtin_categories = 4; | 93 const int g_num_builtin_categories = 4; |
94 int g_category_index = g_num_builtin_categories; // Skip default categories. | 94 int g_category_index = g_num_builtin_categories; // Skip default categories. |
95 | 95 |
96 // The name of the current thread. This is used to decide if the current | 96 // The name of the current thread. This is used to decide if the current |
97 // thread name has changed. We combine all the seen thread names into the | 97 // thread name has changed. We combine all the seen thread names into the |
98 // output name for the thread. | 98 // output name for the thread. |
99 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 99 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
100 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 100 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
101 | 101 |
| 102 const char kRecordUntilFull[] = "record-until-full"; |
| 103 const char kRecordContinuously[] = "record-continuously"; |
| 104 const char kEnableSampling[] = "enable-sampling"; |
| 105 const char kMonitorSampling[] = "monitor-sampling"; |
| 106 |
102 TimeTicks ThreadNow() { | 107 TimeTicks ThreadNow() { |
103 return TimeTicks::IsThreadNowSupported() ? | 108 return TimeTicks::IsThreadNowSupported() ? |
104 TimeTicks::ThreadNow() : TimeTicks(); | 109 TimeTicks::ThreadNow() : TimeTicks(); |
105 } | 110 } |
106 | 111 |
107 class TraceBufferRingBuffer : public TraceBuffer { | 112 class TraceBufferRingBuffer : public TraceBuffer { |
108 public: | 113 public: |
109 TraceBufferRingBuffer(size_t max_chunks) | 114 TraceBufferRingBuffer(size_t max_chunks) |
110 : max_chunks_(max_chunks), | 115 : max_chunks_(max_chunks), |
111 recyclable_chunks_queue_(new size_t[queue_capacity()]), | 116 recyclable_chunks_queue_(new size_t[queue_capacity()]), |
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 // TraceLog | 944 // TraceLog |
940 // | 945 // |
941 //////////////////////////////////////////////////////////////////////////////// | 946 //////////////////////////////////////////////////////////////////////////////// |
942 | 947 |
943 class TraceLog::ThreadLocalEventBuffer | 948 class TraceLog::ThreadLocalEventBuffer |
944 : public MessageLoop::DestructionObserver { | 949 : public MessageLoop::DestructionObserver { |
945 public: | 950 public: |
946 ThreadLocalEventBuffer(TraceLog* trace_log); | 951 ThreadLocalEventBuffer(TraceLog* trace_log); |
947 virtual ~ThreadLocalEventBuffer(); | 952 virtual ~ThreadLocalEventBuffer(); |
948 | 953 |
949 TraceEvent* AddTraceEvent(TraceEventHandle* handle); | 954 TraceEvent* AddTraceEvent(NotificationHelper* notifier, |
| 955 TraceEventHandle* handle); |
950 | 956 |
951 void ReportOverhead(const TimeTicks& event_timestamp, | 957 void ReportOverhead(const TimeTicks& event_timestamp, |
952 const TimeTicks& event_thread_timestamp); | 958 const TimeTicks& event_thread_timestamp, |
| 959 NotificationHelper* notifier); |
953 | 960 |
954 TraceEvent* GetEventByHandle(TraceEventHandle handle) { | 961 TraceEvent* GetEventByHandle(TraceEventHandle handle) { |
955 if (!chunk_ || handle.chunk_seq != chunk_->seq() || | 962 if (!chunk_ || handle.chunk_seq != chunk_->seq() || |
956 handle.chunk_index != chunk_index_) | 963 handle.chunk_index != chunk_index_) |
957 return NULL; | 964 return NULL; |
958 | 965 |
959 return chunk_->GetEventAt(handle.event_index); | 966 return chunk_->GetEventAt(handle.event_index); |
960 } | 967 } |
961 | 968 |
962 int generation() const { return generation_; } | 969 int generation() const { return generation_; } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 | 1006 |
1000 TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { | 1007 TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { |
1001 CheckThisIsCurrentBuffer(); | 1008 CheckThisIsCurrentBuffer(); |
1002 MessageLoop::current()->RemoveDestructionObserver(this); | 1009 MessageLoop::current()->RemoveDestructionObserver(this); |
1003 | 1010 |
1004 // Zero event_count_ happens in either of the following cases: | 1011 // Zero event_count_ happens in either of the following cases: |
1005 // - no event generated for the thread; | 1012 // - no event generated for the thread; |
1006 // - the thread has no message loop; | 1013 // - the thread has no message loop; |
1007 // - trace_event_overhead is disabled. | 1014 // - trace_event_overhead is disabled. |
1008 if (event_count_) { | 1015 if (event_count_) { |
1009 InitializeMetadataEvent(AddTraceEvent(NULL), | 1016 NotificationHelper notifier(trace_log_); |
| 1017 InitializeMetadataEvent(AddTraceEvent(¬ifier, NULL), |
1010 static_cast<int>(base::PlatformThread::CurrentId()), | 1018 static_cast<int>(base::PlatformThread::CurrentId()), |
1011 "overhead", "average_overhead", | 1019 "overhead", "average_overhead", |
1012 overhead_.InMillisecondsF() / event_count_); | 1020 overhead_.InMillisecondsF() / event_count_); |
| 1021 notifier.SendNotificationIfAny(); |
1013 } | 1022 } |
1014 | 1023 |
1015 { | 1024 { |
1016 AutoLock lock(trace_log_->lock_); | 1025 AutoLock lock(trace_log_->lock_); |
1017 FlushWhileLocked(); | 1026 FlushWhileLocked(); |
1018 trace_log_->thread_message_loops_.erase(MessageLoop::current()); | 1027 trace_log_->thread_message_loops_.erase(MessageLoop::current()); |
1019 } | 1028 } |
1020 trace_log_->thread_local_event_buffer_.Set(NULL); | 1029 trace_log_->thread_local_event_buffer_.Set(NULL); |
1021 } | 1030 } |
1022 | 1031 |
1023 TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( | 1032 TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( |
| 1033 NotificationHelper* notifier, |
1024 TraceEventHandle* handle) { | 1034 TraceEventHandle* handle) { |
1025 CheckThisIsCurrentBuffer(); | 1035 CheckThisIsCurrentBuffer(); |
1026 | 1036 |
1027 if (chunk_ && chunk_->IsFull()) { | 1037 if (chunk_ && chunk_->IsFull()) { |
1028 AutoLock lock(trace_log_->lock_); | 1038 AutoLock lock(trace_log_->lock_); |
1029 FlushWhileLocked(); | 1039 FlushWhileLocked(); |
1030 chunk_.reset(); | 1040 chunk_.reset(); |
1031 } | 1041 } |
1032 if (!chunk_) { | 1042 if (!chunk_) { |
1033 AutoLock lock(trace_log_->lock_); | 1043 AutoLock lock(trace_log_->lock_); |
1034 chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_); | 1044 chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_); |
1035 trace_log_->CheckIfBufferIsFullWhileLocked(); | 1045 trace_log_->CheckIfBufferIsFullWhileLocked(notifier); |
1036 } | 1046 } |
1037 if (!chunk_) | 1047 if (!chunk_) |
1038 return NULL; | 1048 return NULL; |
1039 | 1049 |
1040 size_t event_index; | 1050 size_t event_index; |
1041 TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index); | 1051 TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index); |
1042 if (trace_event && handle) | 1052 if (trace_event && handle) |
1043 MakeHandle(chunk_->seq(), chunk_index_, event_index, handle); | 1053 MakeHandle(chunk_->seq(), chunk_index_, event_index, handle); |
1044 | 1054 |
1045 return trace_event; | 1055 return trace_event; |
1046 } | 1056 } |
1047 | 1057 |
1048 void TraceLog::ThreadLocalEventBuffer::ReportOverhead( | 1058 void TraceLog::ThreadLocalEventBuffer::ReportOverhead( |
1049 const TimeTicks& event_timestamp, | 1059 const TimeTicks& event_timestamp, |
1050 const TimeTicks& event_thread_timestamp) { | 1060 const TimeTicks& event_thread_timestamp, |
| 1061 NotificationHelper* notifier) { |
1051 if (!g_category_group_enabled[g_category_trace_event_overhead]) | 1062 if (!g_category_group_enabled[g_category_trace_event_overhead]) |
1052 return; | 1063 return; |
1053 | 1064 |
1054 CheckThisIsCurrentBuffer(); | 1065 CheckThisIsCurrentBuffer(); |
1055 | 1066 |
1056 event_count_++; | 1067 event_count_++; |
1057 TimeTicks thread_now = ThreadNow(); | 1068 TimeTicks thread_now = ThreadNow(); |
1058 TimeTicks now = trace_log_->OffsetNow(); | 1069 TimeTicks now = trace_log_->OffsetNow(); |
1059 TimeDelta overhead = now - event_timestamp; | 1070 TimeDelta overhead = now - event_timestamp; |
1060 if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) { | 1071 if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) { |
1061 TraceEvent* trace_event = AddTraceEvent(NULL); | 1072 TraceEvent* trace_event = AddTraceEvent(notifier, NULL); |
1062 if (trace_event) { | 1073 if (trace_event) { |
1063 trace_event->Initialize( | 1074 trace_event->Initialize( |
1064 static_cast<int>(PlatformThread::CurrentId()), | 1075 static_cast<int>(PlatformThread::CurrentId()), |
1065 event_timestamp, event_thread_timestamp, | 1076 event_timestamp, event_thread_timestamp, |
1066 TRACE_EVENT_PHASE_COMPLETE, | 1077 TRACE_EVENT_PHASE_COMPLETE, |
1067 &g_category_group_enabled[g_category_trace_event_overhead], | 1078 &g_category_group_enabled[g_category_trace_event_overhead], |
1068 "overhead", 0, 0, NULL, NULL, NULL, NULL, 0); | 1079 "overhead", 0, 0, NULL, NULL, NULL, NULL, 0); |
1069 trace_event->UpdateDuration(now, thread_now); | 1080 trace_event->UpdateDuration(now, thread_now); |
1070 } | 1081 } |
1071 } | 1082 } |
(...skipping 10 matching lines...) Expand all Loading... |
1082 | 1093 |
1083 trace_log_->lock_.AssertAcquired(); | 1094 trace_log_->lock_.AssertAcquired(); |
1084 if (trace_log_->CheckGeneration(generation_)) { | 1095 if (trace_log_->CheckGeneration(generation_)) { |
1085 // Return the chunk to the buffer only if the generation matches, | 1096 // Return the chunk to the buffer only if the generation matches, |
1086 trace_log_->logged_events_->ReturnChunk(chunk_index_, chunk_.Pass()); | 1097 trace_log_->logged_events_->ReturnChunk(chunk_index_, chunk_.Pass()); |
1087 } | 1098 } |
1088 // Otherwise this method may be called from the destructor, or TraceLog will | 1099 // Otherwise this method may be called from the destructor, or TraceLog will |
1089 // find the generation mismatch and delete this buffer soon. | 1100 // find the generation mismatch and delete this buffer soon. |
1090 } | 1101 } |
1091 | 1102 |
| 1103 TraceLog::NotificationHelper::NotificationHelper(TraceLog* trace_log) |
| 1104 : trace_log_(trace_log), |
| 1105 notification_(0) { |
| 1106 } |
| 1107 |
| 1108 TraceLog::NotificationHelper::~NotificationHelper() { |
| 1109 } |
| 1110 |
| 1111 void TraceLog::NotificationHelper::AddNotificationWhileLocked( |
| 1112 int notification) { |
| 1113 trace_log_->lock_.AssertAcquired(); |
| 1114 if (trace_log_->notification_callback_.is_null()) |
| 1115 return; |
| 1116 if (notification_ == 0) |
| 1117 callback_copy_ = trace_log_->notification_callback_; |
| 1118 notification_ |= notification; |
| 1119 } |
| 1120 |
| 1121 void TraceLog::NotificationHelper::SendNotificationIfAny() { |
| 1122 if (notification_) |
| 1123 callback_copy_.Run(notification_); |
| 1124 } |
| 1125 |
1092 // static | 1126 // static |
1093 TraceLog* TraceLog::GetInstance() { | 1127 TraceLog* TraceLog::GetInstance() { |
1094 return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get(); | 1128 return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get(); |
1095 } | 1129 } |
1096 | 1130 |
| 1131 // static |
| 1132 // Note, if you add more options here you also need to update: |
| 1133 // content/browser/devtools/devtools_tracing_handler:TraceOptionsFromString |
| 1134 TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { |
| 1135 std::vector<std::string> split; |
| 1136 base::SplitString(options, ',', &split); |
| 1137 int ret = 0; |
| 1138 for (std::vector<std::string>::iterator iter = split.begin(); |
| 1139 iter != split.end(); |
| 1140 ++iter) { |
| 1141 if (*iter == kRecordUntilFull) { |
| 1142 ret |= RECORD_UNTIL_FULL; |
| 1143 } else if (*iter == kRecordContinuously) { |
| 1144 ret |= RECORD_CONTINUOUSLY; |
| 1145 } else if (*iter == kEnableSampling) { |
| 1146 ret |= ENABLE_SAMPLING; |
| 1147 } else if (*iter == kMonitorSampling) { |
| 1148 ret |= MONITOR_SAMPLING; |
| 1149 } else { |
| 1150 NOTREACHED(); // Unknown option provided. |
| 1151 } |
| 1152 } |
| 1153 if (!(ret & RECORD_UNTIL_FULL) && !(ret & RECORD_CONTINUOUSLY)) |
| 1154 ret |= RECORD_UNTIL_FULL; // Default when no options are specified. |
| 1155 |
| 1156 return static_cast<Options>(ret); |
| 1157 } |
| 1158 |
1097 TraceLog::TraceLog() | 1159 TraceLog::TraceLog() |
1098 : enabled_(false), | 1160 : enabled_(false), |
1099 num_traces_recorded_(0), | 1161 num_traces_recorded_(0), |
| 1162 buffer_is_full_(0), |
1100 event_callback_(0), | 1163 event_callback_(0), |
1101 dispatching_to_observer_list_(false), | 1164 dispatching_to_observer_list_(false), |
1102 process_sort_index_(0), | 1165 process_sort_index_(0), |
1103 process_id_hash_(0), | 1166 process_id_hash_(0), |
1104 process_id_(0), | 1167 process_id_(0), |
1105 watch_category_(0), | 1168 watch_category_(0), |
1106 trace_options_(RECORD_UNTIL_FULL), | 1169 trace_options_(RECORD_UNTIL_FULL), |
1107 sampling_thread_handle_(0), | 1170 sampling_thread_handle_(0), |
1108 category_filter_(CategoryFilter::kDefaultCategoryFilterString), | 1171 category_filter_(CategoryFilter::kDefaultCategoryFilterString), |
1109 event_callback_category_filter_( | 1172 event_callback_category_filter_( |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 "Cannot manipulate TraceLog::Enabled state from an observer."; | 1329 "Cannot manipulate TraceLog::Enabled state from an observer."; |
1267 return; | 1330 return; |
1268 } | 1331 } |
1269 | 1332 |
1270 enabled_ = true; | 1333 enabled_ = true; |
1271 | 1334 |
1272 if (options != old_options) { | 1335 if (options != old_options) { |
1273 subtle::NoBarrier_Store(&trace_options_, options); | 1336 subtle::NoBarrier_Store(&trace_options_, options); |
1274 logged_events_.reset(CreateTraceBuffer()); | 1337 logged_events_.reset(CreateTraceBuffer()); |
1275 NextGeneration(); | 1338 NextGeneration(); |
| 1339 subtle::NoBarrier_Store(&buffer_is_full_, 0); |
1276 } | 1340 } |
1277 | 1341 |
1278 num_traces_recorded_++; | 1342 num_traces_recorded_++; |
1279 | 1343 |
1280 category_filter_ = CategoryFilter(category_filter); | 1344 category_filter_ = CategoryFilter(category_filter); |
1281 UpdateCategoryGroupEnabledFlags(); | 1345 UpdateCategoryGroupEnabledFlags(); |
1282 | 1346 |
1283 if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { | 1347 if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { |
1284 sampling_thread_.reset(new TraceSamplingThread); | 1348 sampling_thread_.reset(new TraceSamplingThread); |
1285 sampling_thread_->RegisterSampleBucket( | 1349 sampling_thread_->RegisterSampleBucket( |
(...skipping 26 matching lines...) Expand all Loading... |
1312 dispatching_to_observer_list_ = false; | 1376 dispatching_to_observer_list_ = false; |
1313 } | 1377 } |
1314 } | 1378 } |
1315 | 1379 |
1316 CategoryFilter TraceLog::GetCurrentCategoryFilter() { | 1380 CategoryFilter TraceLog::GetCurrentCategoryFilter() { |
1317 AutoLock lock(lock_); | 1381 AutoLock lock(lock_); |
1318 return category_filter_; | 1382 return category_filter_; |
1319 } | 1383 } |
1320 | 1384 |
1321 void TraceLog::SetDisabled() { | 1385 void TraceLog::SetDisabled() { |
1322 AutoLock lock(lock_); | 1386 std::vector<EnabledStateObserver*> observer_list; |
1323 SetDisabledWhileLocked(); | 1387 { |
1324 } | 1388 AutoLock lock(lock_); |
| 1389 if (!enabled_) |
| 1390 return; |
1325 | 1391 |
1326 void TraceLog::SetDisabledWhileLocked() { | 1392 if (dispatching_to_observer_list_) { |
1327 lock_.AssertAcquired(); | 1393 DLOG(ERROR) |
| 1394 << "Cannot manipulate TraceLog::Enabled state from an observer."; |
| 1395 return; |
| 1396 } |
1328 | 1397 |
1329 if (!enabled_) | 1398 enabled_ = false; |
1330 return; | |
1331 | 1399 |
1332 if (dispatching_to_observer_list_) { | 1400 if (sampling_thread_.get()) { |
1333 DLOG(ERROR) | 1401 // Stop the sampling thread. |
1334 << "Cannot manipulate TraceLog::Enabled state from an observer."; | 1402 sampling_thread_->Stop(); |
1335 return; | 1403 lock_.Release(); |
| 1404 PlatformThread::Join(sampling_thread_handle_); |
| 1405 lock_.Acquire(); |
| 1406 sampling_thread_handle_ = PlatformThreadHandle(); |
| 1407 sampling_thread_.reset(); |
| 1408 } |
| 1409 |
| 1410 category_filter_.Clear(); |
| 1411 subtle::NoBarrier_Store(&watch_category_, 0); |
| 1412 watch_event_name_ = ""; |
| 1413 UpdateCategoryGroupEnabledFlags(); |
| 1414 AddMetadataEventsWhileLocked(); |
| 1415 |
| 1416 dispatching_to_observer_list_ = true; |
| 1417 observer_list = enabled_state_observer_list_; |
1336 } | 1418 } |
1337 | 1419 |
1338 enabled_ = false; | 1420 // Dispatch to observers outside the lock in case the observer triggers a |
1339 | 1421 // trace event. |
1340 if (sampling_thread_.get()) { | 1422 for (size_t i = 0; i < observer_list.size(); ++i) |
1341 // Stop the sampling thread. | 1423 observer_list[i]->OnTraceLogDisabled(); |
1342 sampling_thread_->Stop(); | |
1343 lock_.Release(); | |
1344 PlatformThread::Join(sampling_thread_handle_); | |
1345 lock_.Acquire(); | |
1346 sampling_thread_handle_ = PlatformThreadHandle(); | |
1347 sampling_thread_.reset(); | |
1348 } | |
1349 | |
1350 category_filter_.Clear(); | |
1351 subtle::NoBarrier_Store(&watch_category_, 0); | |
1352 watch_event_name_ = ""; | |
1353 UpdateCategoryGroupEnabledFlags(); | |
1354 AddMetadataEventsWhileLocked(); | |
1355 | |
1356 dispatching_to_observer_list_ = true; | |
1357 std::vector<EnabledStateObserver*> observer_list = | |
1358 enabled_state_observer_list_; | |
1359 | 1424 |
1360 { | 1425 { |
1361 // Dispatch to observers outside the lock in case the observer triggers a | 1426 AutoLock lock(lock_); |
1362 // trace event. | 1427 dispatching_to_observer_list_ = false; |
1363 AutoUnlock unlock(lock_); | |
1364 for (size_t i = 0; i < observer_list.size(); ++i) | |
1365 observer_list[i]->OnTraceLogDisabled(); | |
1366 } | 1428 } |
1367 dispatching_to_observer_list_ = false; | |
1368 } | 1429 } |
1369 | 1430 |
1370 int TraceLog::GetNumTracesRecorded() { | 1431 int TraceLog::GetNumTracesRecorded() { |
1371 AutoLock lock(lock_); | 1432 AutoLock lock(lock_); |
1372 if (!enabled_) | 1433 if (!enabled_) |
1373 return -1; | 1434 return -1; |
1374 return num_traces_recorded_; | 1435 return num_traces_recorded_; |
1375 } | 1436 } |
1376 | 1437 |
1377 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { | 1438 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { |
(...skipping 11 matching lines...) Expand all Loading... |
1389 | 1450 |
1390 bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { | 1451 bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { |
1391 std::vector<EnabledStateObserver*>::const_iterator it = | 1452 std::vector<EnabledStateObserver*>::const_iterator it = |
1392 std::find(enabled_state_observer_list_.begin(), | 1453 std::find(enabled_state_observer_list_.begin(), |
1393 enabled_state_observer_list_.end(), | 1454 enabled_state_observer_list_.end(), |
1394 listener); | 1455 listener); |
1395 return it != enabled_state_observer_list_.end(); | 1456 return it != enabled_state_observer_list_.end(); |
1396 } | 1457 } |
1397 | 1458 |
1398 float TraceLog::GetBufferPercentFull() const { | 1459 float TraceLog::GetBufferPercentFull() const { |
1399 AutoLock lock(lock_); | |
1400 return static_cast<float>(static_cast<double>(logged_events_->Size()) / | 1460 return static_cast<float>(static_cast<double>(logged_events_->Size()) / |
1401 logged_events_->Capacity()); | 1461 logged_events_->Capacity()); |
1402 } | 1462 } |
1403 | 1463 |
1404 bool TraceLog::BufferIsFull() const { | 1464 void TraceLog::SetNotificationCallback( |
| 1465 const TraceLog::NotificationCallback& cb) { |
1405 AutoLock lock(lock_); | 1466 AutoLock lock(lock_); |
1406 return logged_events_->IsFull(); | 1467 notification_callback_ = cb; |
1407 } | 1468 } |
1408 | 1469 |
1409 TraceBuffer* TraceLog::CreateTraceBuffer() { | 1470 TraceBuffer* TraceLog::CreateTraceBuffer() { |
1410 Options options = trace_options(); | 1471 Options options = trace_options(); |
1411 if (options & RECORD_CONTINUOUSLY) | 1472 if (options & RECORD_CONTINUOUSLY) |
1412 return new TraceBufferRingBuffer(kTraceEventRingBufferChunks); | 1473 return new TraceBufferRingBuffer(kTraceEventRingBufferChunks); |
1413 else if (options & MONITOR_SAMPLING) | 1474 else if (options & MONITOR_SAMPLING) |
1414 return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks); | 1475 return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks); |
1415 else if (options & ECHO_TO_CONSOLE) | 1476 else if (options & ECHO_TO_CONSOLE) |
1416 return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks); | 1477 return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks); |
1417 return new TraceBufferVector(); | 1478 return new TraceBufferVector(); |
1418 } | 1479 } |
1419 | 1480 |
1420 TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( | 1481 TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( |
1421 TraceEventHandle* handle, bool check_buffer_is_full) { | 1482 NotificationHelper* notifier, TraceEventHandle* handle) { |
1422 lock_.AssertAcquired(); | 1483 lock_.AssertAcquired(); |
1423 | 1484 |
1424 if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) { | 1485 if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) { |
1425 logged_events_->ReturnChunk(thread_shared_chunk_index_, | 1486 logged_events_->ReturnChunk(thread_shared_chunk_index_, |
1426 thread_shared_chunk_.Pass()); | 1487 thread_shared_chunk_.Pass()); |
1427 } | 1488 } |
1428 | 1489 |
1429 if (!thread_shared_chunk_) { | 1490 if (!thread_shared_chunk_) { |
1430 thread_shared_chunk_ = logged_events_->GetChunk( | 1491 thread_shared_chunk_ = logged_events_->GetChunk( |
1431 &thread_shared_chunk_index_); | 1492 &thread_shared_chunk_index_); |
1432 if (check_buffer_is_full) | 1493 if (notifier) |
1433 CheckIfBufferIsFullWhileLocked(); | 1494 CheckIfBufferIsFullWhileLocked(notifier); |
1434 } | 1495 } |
1435 if (!thread_shared_chunk_) | 1496 if (!thread_shared_chunk_) |
1436 return NULL; | 1497 return NULL; |
1437 | 1498 |
1438 size_t event_index; | 1499 size_t event_index; |
1439 TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index); | 1500 TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index); |
1440 if (trace_event && handle) { | 1501 if (trace_event && handle) { |
1441 MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_, | 1502 MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_, |
1442 event_index, handle); | 1503 event_index, handle); |
1443 } | 1504 } |
1444 return trace_event; | 1505 return trace_event; |
1445 } | 1506 } |
1446 | 1507 |
1447 void TraceLog::CheckIfBufferIsFullWhileLocked() { | 1508 void TraceLog::CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier) { |
1448 lock_.AssertAcquired(); | 1509 lock_.AssertAcquired(); |
1449 if (logged_events_->IsFull()) | 1510 if (!subtle::NoBarrier_Load(&buffer_is_full_) && logged_events_->IsFull()) { |
1450 SetDisabledWhileLocked(); | 1511 subtle::NoBarrier_Store(&buffer_is_full_, |
| 1512 static_cast<subtle::AtomicWord>(1)); |
| 1513 notifier->AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
| 1514 } |
1451 } | 1515 } |
1452 | 1516 |
1453 void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter, | 1517 void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter, |
1454 EventCallback cb) { | 1518 EventCallback cb) { |
1455 AutoLock lock(lock_); | 1519 AutoLock lock(lock_); |
1456 subtle::NoBarrier_Store(&event_callback_, | 1520 subtle::NoBarrier_Store(&event_callback_, |
1457 reinterpret_cast<subtle::AtomicWord>(cb)); | 1521 reinterpret_cast<subtle::AtomicWord>(cb)); |
1458 event_callback_category_filter_ = category_filter; | 1522 event_callback_category_filter_ = category_filter; |
1459 UpdateCategoryGroupEnabledFlags(); | 1523 UpdateCategoryGroupEnabledFlags(); |
1460 }; | 1524 }; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 | 1621 |
1558 if (!CheckGeneration(generation)) | 1622 if (!CheckGeneration(generation)) |
1559 return; | 1623 return; |
1560 | 1624 |
1561 { | 1625 { |
1562 AutoLock lock(lock_); | 1626 AutoLock lock(lock_); |
1563 | 1627 |
1564 previous_logged_events.swap(logged_events_); | 1628 previous_logged_events.swap(logged_events_); |
1565 logged_events_.reset(CreateTraceBuffer()); | 1629 logged_events_.reset(CreateTraceBuffer()); |
1566 NextGeneration(); | 1630 NextGeneration(); |
| 1631 subtle::NoBarrier_Store(&buffer_is_full_, 0); |
1567 thread_message_loops_.clear(); | 1632 thread_message_loops_.clear(); |
1568 | 1633 |
1569 flush_message_loop_proxy_ = NULL; | 1634 flush_message_loop_proxy_ = NULL; |
1570 flush_output_callback = flush_output_callback_; | 1635 flush_output_callback = flush_output_callback_; |
1571 flush_output_callback_.Reset(); | 1636 flush_output_callback_.Reset(); |
1572 } | 1637 } |
1573 | 1638 |
1574 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), | 1639 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), |
1575 flush_output_callback); | 1640 flush_output_callback); |
1576 } | 1641 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 return handle; | 1741 return handle; |
1677 | 1742 |
1678 DCHECK(name); | 1743 DCHECK(name); |
1679 | 1744 |
1680 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) | 1745 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) |
1681 id ^= process_id_hash_; | 1746 id ^= process_id_hash_; |
1682 | 1747 |
1683 TimeTicks now = OffsetTimestamp(timestamp); | 1748 TimeTicks now = OffsetTimestamp(timestamp); |
1684 TimeTicks thread_now = ThreadNow(); | 1749 TimeTicks thread_now = ThreadNow(); |
1685 | 1750 |
| 1751 NotificationHelper notifier(this); |
| 1752 |
1686 ThreadLocalEventBuffer* thread_local_event_buffer = NULL; | 1753 ThreadLocalEventBuffer* thread_local_event_buffer = NULL; |
1687 // A ThreadLocalEventBuffer needs the message loop | 1754 // A ThreadLocalEventBuffer needs the message loop |
1688 // - to know when the thread exits; | 1755 // - to know when the thread exits; |
1689 // - to handle the final flush. | 1756 // - to handle the final flush. |
1690 // For a thread without a message loop or the message loop may be blocked, the | 1757 // For a thread without a message loop or the message loop may be blocked, the |
1691 // trace events will be added into the main buffer directly. | 1758 // trace events will be added into the main buffer directly. |
1692 if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) { | 1759 if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) { |
1693 thread_local_event_buffer = thread_local_event_buffer_.Get(); | 1760 thread_local_event_buffer = thread_local_event_buffer_.Get(); |
1694 if (thread_local_event_buffer && | 1761 if (thread_local_event_buffer && |
1695 !CheckGeneration(thread_local_event_buffer->generation())) { | 1762 !CheckGeneration(thread_local_event_buffer->generation())) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 new_name) != existing_names.end(); | 1799 new_name) != existing_names.end(); |
1733 if (!found) { | 1800 if (!found) { |
1734 existing_name->second.push_back(','); | 1801 existing_name->second.push_back(','); |
1735 existing_name->second.append(new_name); | 1802 existing_name->second.append(new_name); |
1736 } | 1803 } |
1737 } | 1804 } |
1738 } | 1805 } |
1739 } | 1806 } |
1740 | 1807 |
1741 TraceEvent* trace_event = NULL; | 1808 TraceEvent* trace_event = NULL; |
1742 if ((*category_group_enabled & ENABLED_FOR_RECORDING)) { | 1809 if ((*category_group_enabled & ENABLED_FOR_RECORDING) && |
| 1810 !subtle::NoBarrier_Load(&buffer_is_full_)) { |
1743 if (thread_local_event_buffer) { | 1811 if (thread_local_event_buffer) { |
1744 lock.EnsureReleased(); | 1812 lock.EnsureReleased(); |
1745 trace_event = thread_local_event_buffer->AddTraceEvent(&handle); | 1813 trace_event = thread_local_event_buffer->AddTraceEvent(¬ifier, |
| 1814 &handle); |
1746 } else { | 1815 } else { |
1747 lock.EnsureAcquired(); | 1816 lock.EnsureAcquired(); |
1748 trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); | 1817 trace_event = AddEventToThreadSharedChunkWhileLocked(¬ifier, &handle); |
1749 } | 1818 } |
1750 | 1819 |
1751 if (trace_event) { | 1820 if (trace_event) { |
1752 trace_event->Initialize(thread_id, now, thread_now, phase, | 1821 trace_event->Initialize(thread_id, now, thread_now, phase, |
1753 category_group_enabled, name, id, | 1822 category_group_enabled, name, id, |
1754 num_args, arg_names, arg_types, arg_values, | 1823 num_args, arg_names, arg_types, arg_values, |
1755 convertable_values, flags); | 1824 convertable_values, flags); |
1756 | 1825 |
1757 #if defined(OS_ANDROID) | 1826 #if defined(OS_ANDROID) |
1758 trace_event->SendToATrace(); | 1827 trace_event->SendToATrace(); |
1759 #endif | 1828 #endif |
1760 } | 1829 } |
| 1830 } |
1761 | 1831 |
1762 if (trace_options() & ECHO_TO_CONSOLE) { | 1832 if (trace_options() & ECHO_TO_CONSOLE) { |
1763 lock.EnsureAcquired(); | 1833 lock.EnsureAcquired(); |
1764 OutputEventToConsoleWhileLocked( | 1834 OutputEventToConsoleWhileLocked( |
1765 phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, | 1835 phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, |
1766 timestamp, trace_event); | 1836 timestamp, trace_event); |
1767 } | |
1768 } | 1837 } |
1769 | 1838 |
1770 if (reinterpret_cast<const unsigned char*>(subtle::NoBarrier_Load( | 1839 if (reinterpret_cast<const unsigned char*>(subtle::NoBarrier_Load( |
1771 &watch_category_)) == category_group_enabled) { | 1840 &watch_category_)) == category_group_enabled) { |
1772 lock.EnsureAcquired(); | 1841 lock.EnsureAcquired(); |
1773 if (watch_event_name_ == name) { | 1842 if (watch_event_name_ == name) |
1774 WatchEventCallback watch_event_callback_copy = watch_event_callback_; | 1843 notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
1775 lock.EnsureReleased(); | |
1776 if (!watch_event_callback_copy.is_null()) | |
1777 watch_event_callback_copy.Run(); | |
1778 } | |
1779 } | 1844 } |
1780 | 1845 |
1781 lock.EnsureReleased(); | 1846 lock.EnsureReleased(); |
1782 if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) { | 1847 if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) { |
1783 EventCallback event_callback = reinterpret_cast<EventCallback>( | 1848 EventCallback event_callback = reinterpret_cast<EventCallback>( |
1784 subtle::NoBarrier_Load(&event_callback_)); | 1849 subtle::NoBarrier_Load(&event_callback_)); |
1785 if (event_callback) { | 1850 if (event_callback) { |
1786 event_callback(now, | 1851 event_callback(now, |
1787 phase == TRACE_EVENT_PHASE_COMPLETE ? | 1852 phase == TRACE_EVENT_PHASE_COMPLETE ? |
1788 TRACE_EVENT_PHASE_BEGIN : phase, | 1853 TRACE_EVENT_PHASE_BEGIN : phase, |
1789 category_group_enabled, name, id, | 1854 category_group_enabled, name, id, |
1790 num_args, arg_names, arg_types, arg_values, | 1855 num_args, arg_names, arg_types, arg_values, |
1791 flags); | 1856 flags); |
1792 } | 1857 } |
1793 } | 1858 } |
1794 | 1859 |
1795 if (thread_local_event_buffer) | 1860 if (thread_local_event_buffer) |
1796 thread_local_event_buffer->ReportOverhead(now, thread_now); | 1861 thread_local_event_buffer->ReportOverhead(now, thread_now, ¬ifier); |
| 1862 |
| 1863 notifier.SendNotificationIfAny(); |
1797 | 1864 |
1798 return handle; | 1865 return handle; |
1799 } | 1866 } |
1800 | 1867 |
1801 // May be called when a COMPELETE event ends and the unfinished event has been | 1868 // May be called when a COMPELETE event ends and the unfinished event has been |
1802 // recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL). | 1869 // recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL). |
1803 void TraceLog::OutputEventToConsoleWhileLocked(unsigned char phase, | 1870 void TraceLog::OutputEventToConsoleWhileLocked(unsigned char phase, |
1804 const TimeTicks& timestamp, | 1871 const TimeTicks& timestamp, |
1805 TraceEvent* trace_event) { | 1872 TraceEvent* trace_event) { |
1806 // The caller should translate TRACE_EVENT_PHASE_COMPLETE to | 1873 // The caller should translate TRACE_EVENT_PHASE_COMPLETE to |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1897 subtle::NoBarrier_Load(&event_callback_)); | 1964 subtle::NoBarrier_Load(&event_callback_)); |
1898 if (event_callback) { | 1965 if (event_callback) { |
1899 event_callback(now, TRACE_EVENT_PHASE_END, category_group_enabled, name, | 1966 event_callback(now, TRACE_EVENT_PHASE_END, category_group_enabled, name, |
1900 trace_event_internal::kNoEventId, 0, NULL, NULL, NULL, | 1967 trace_event_internal::kNoEventId, 0, NULL, NULL, NULL, |
1901 TRACE_EVENT_FLAG_NONE); | 1968 TRACE_EVENT_FLAG_NONE); |
1902 } | 1969 } |
1903 } | 1970 } |
1904 } | 1971 } |
1905 | 1972 |
1906 void TraceLog::SetWatchEvent(const std::string& category_name, | 1973 void TraceLog::SetWatchEvent(const std::string& category_name, |
1907 const std::string& event_name, | 1974 const std::string& event_name) { |
1908 const WatchEventCallback& callback) { | |
1909 const unsigned char* category = GetCategoryGroupEnabled( | 1975 const unsigned char* category = GetCategoryGroupEnabled( |
1910 category_name.c_str()); | 1976 category_name.c_str()); |
1911 AutoLock lock(lock_); | 1977 AutoLock lock(lock_); |
1912 subtle::NoBarrier_Store(&watch_category_, | 1978 subtle::NoBarrier_Store(&watch_category_, |
1913 reinterpret_cast<subtle::AtomicWord>(category)); | 1979 reinterpret_cast<subtle::AtomicWord>(category)); |
1914 watch_event_name_ = event_name; | 1980 watch_event_name_ = event_name; |
1915 watch_event_callback_ = callback; | |
1916 } | 1981 } |
1917 | 1982 |
1918 void TraceLog::CancelWatchEvent() { | 1983 void TraceLog::CancelWatchEvent() { |
1919 AutoLock lock(lock_); | 1984 AutoLock lock(lock_); |
1920 subtle::NoBarrier_Store(&watch_category_, 0); | 1985 subtle::NoBarrier_Store(&watch_category_, 0); |
1921 watch_event_name_ = ""; | 1986 watch_event_name_ = ""; |
1922 watch_event_callback_.Reset(); | |
1923 } | 1987 } |
1924 | 1988 |
1925 void TraceLog::AddMetadataEventsWhileLocked() { | 1989 void TraceLog::AddMetadataEventsWhileLocked() { |
1926 lock_.AssertAcquired(); | 1990 lock_.AssertAcquired(); |
1927 | 1991 |
1928 int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId()); | 1992 int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId()); |
1929 if (process_sort_index_ != 0) { | 1993 if (process_sort_index_ != 0) { |
1930 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), | 1994 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
1931 current_thread_id, | 1995 current_thread_id, |
1932 "process_sort_index", "sort_index", | 1996 "process_sort_index", "sort_index", |
1933 process_sort_index_); | 1997 process_sort_index_); |
1934 } | 1998 } |
1935 | 1999 |
1936 if (process_name_.size()) { | 2000 if (process_name_.size()) { |
1937 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), | 2001 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
1938 current_thread_id, | 2002 current_thread_id, |
1939 "process_name", "name", | 2003 "process_name", "name", |
1940 process_name_); | 2004 process_name_); |
1941 } | 2005 } |
1942 | 2006 |
1943 if (process_labels_.size() > 0) { | 2007 if (process_labels_.size() > 0) { |
1944 std::vector<std::string> labels; | 2008 std::vector<std::string> labels; |
1945 for(base::hash_map<int, std::string>::iterator it = process_labels_.begin(); | 2009 for(base::hash_map<int, std::string>::iterator it = process_labels_.begin(); |
1946 it != process_labels_.end(); | 2010 it != process_labels_.end(); |
1947 it++) { | 2011 it++) { |
1948 labels.push_back(it->second); | 2012 labels.push_back(it->second); |
1949 } | 2013 } |
1950 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), | 2014 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
1951 current_thread_id, | 2015 current_thread_id, |
1952 "process_labels", "labels", | 2016 "process_labels", "labels", |
1953 JoinString(labels, ',')); | 2017 JoinString(labels, ',')); |
1954 } | 2018 } |
1955 | 2019 |
1956 // Thread sort indices. | 2020 // Thread sort indices. |
1957 for(hash_map<int, int>::iterator it = thread_sort_indices_.begin(); | 2021 for(hash_map<int, int>::iterator it = thread_sort_indices_.begin(); |
1958 it != thread_sort_indices_.end(); | 2022 it != thread_sort_indices_.end(); |
1959 it++) { | 2023 it++) { |
1960 if (it->second == 0) | 2024 if (it->second == 0) |
1961 continue; | 2025 continue; |
1962 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), | 2026 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
1963 it->first, | 2027 it->first, |
1964 "thread_sort_index", "sort_index", | 2028 "thread_sort_index", "sort_index", |
1965 it->second); | 2029 it->second); |
1966 } | 2030 } |
1967 | 2031 |
1968 // Thread names. | 2032 // Thread names. |
1969 for(hash_map<int, std::string>::iterator it = thread_names_.begin(); | 2033 for(hash_map<int, std::string>::iterator it = thread_names_.begin(); |
1970 it != thread_names_.end(); | 2034 it != thread_names_.end(); |
1971 it++) { | 2035 it++) { |
1972 if (it->second.empty()) | 2036 if (it->second.empty()) |
1973 continue; | 2037 continue; |
1974 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), | 2038 InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
1975 it->first, | 2039 it->first, |
1976 "thread_name", "name", | 2040 "thread_name", "name", |
1977 it->second); | 2041 it->second); |
1978 } | 2042 } |
1979 } | 2043 } |
1980 | 2044 |
1981 void TraceLog::WaitSamplingEventForTesting() { | 2045 void TraceLog::WaitSamplingEventForTesting() { |
1982 if (!sampling_thread_) | 2046 if (!sampling_thread_) |
1983 return; | 2047 return; |
1984 sampling_thread_->WaitSamplingEventForTesting(); | 2048 sampling_thread_->WaitSamplingEventForTesting(); |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2259 } | 2323 } |
2260 | 2324 |
2261 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2325 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2262 if (*category_group_enabled_) { | 2326 if (*category_group_enabled_) { |
2263 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2327 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2264 name_, event_handle_); | 2328 name_, event_handle_); |
2265 } | 2329 } |
2266 } | 2330 } |
2267 | 2331 |
2268 } // namespace trace_event_internal | 2332 } // namespace trace_event_internal |
OLD | NEW |