Index: base/debug/trace_event_impl.cc |
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc |
index 8f08a1c7b7f285ad514eb0424a68323b5a29e3ce..e4d20a5bb2d024640e3d46d8c7c1d242f78605f9 100644 |
--- a/base/debug/trace_event_impl.cc |
+++ b/base/debug/trace_event_impl.cc |
@@ -99,11 +99,6 @@ int g_category_index = g_num_builtin_categories; // Skip default categories. |
LazyInstance<ThreadLocalPointer<const char> >::Leaky |
g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
-const char kRecordUntilFull[] = "record-until-full"; |
-const char kRecordContinuously[] = "record-continuously"; |
-const char kEnableSampling[] = "enable-sampling"; |
-const char kMonitorSampling[] = "monitor-sampling"; |
- |
TimeTicks ThreadNow() { |
return TimeTicks::IsThreadNowSupported() ? |
TimeTicks::ThreadNow() : TimeTicks(); |
@@ -944,12 +939,10 @@ class TraceLog::ThreadLocalEventBuffer |
ThreadLocalEventBuffer(TraceLog* trace_log); |
virtual ~ThreadLocalEventBuffer(); |
- TraceEvent* AddTraceEvent(NotificationHelper* notifier, |
- TraceEventHandle* handle); |
+ TraceEvent* AddTraceEvent(TraceEventHandle* handle); |
void ReportOverhead(const TimeTicks& event_timestamp, |
- const TimeTicks& event_thread_timestamp, |
- NotificationHelper* notifier); |
+ const TimeTicks& event_thread_timestamp); |
TraceEvent* GetEventByHandle(TraceEventHandle handle) { |
if (!chunk_ || handle.chunk_seq != chunk_->seq() || |
@@ -1006,12 +999,10 @@ TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { |
// - the thread has no message loop; |
// - trace_event_overhead is disabled. |
if (event_count_) { |
- NotificationHelper notifier(trace_log_); |
- InitializeMetadataEvent(AddTraceEvent(¬ifier, NULL), |
+ InitializeMetadataEvent(AddTraceEvent(NULL), |
static_cast<int>(base::PlatformThread::CurrentId()), |
"overhead", "average_overhead", |
overhead_.InMillisecondsF() / event_count_); |
- notifier.SendNotificationIfAny(); |
} |
{ |
@@ -1023,7 +1014,6 @@ TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { |
} |
TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( |
- NotificationHelper* notifier, |
TraceEventHandle* handle) { |
CheckThisIsCurrentBuffer(); |
@@ -1035,7 +1025,7 @@ TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( |
if (!chunk_) { |
AutoLock lock(trace_log_->lock_); |
chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_); |
- trace_log_->CheckIfBufferIsFullWhileLocked(notifier); |
+ trace_log_->CheckIfBufferIsFullWhileLocked(); |
} |
if (!chunk_) |
return NULL; |
@@ -1050,8 +1040,7 @@ TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( |
void TraceLog::ThreadLocalEventBuffer::ReportOverhead( |
const TimeTicks& event_timestamp, |
- const TimeTicks& event_thread_timestamp, |
- NotificationHelper* notifier) { |
+ const TimeTicks& event_thread_timestamp) { |
if (!g_category_group_enabled[g_category_trace_event_overhead]) |
return; |
@@ -1061,7 +1050,7 @@ void TraceLog::ThreadLocalEventBuffer::ReportOverhead( |
TimeTicks now = trace_log_->OffsetNow(); |
TimeDelta overhead = now - event_timestamp; |
if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) { |
- TraceEvent* trace_event = AddTraceEvent(notifier, NULL); |
+ TraceEvent* trace_event = AddTraceEvent(NULL); |
if (trace_event) { |
trace_event->Initialize( |
static_cast<int>(PlatformThread::CurrentId()), |
@@ -1092,66 +1081,14 @@ void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() { |
// find the generation mismatch and delete this buffer soon. |
} |
-TraceLog::NotificationHelper::NotificationHelper(TraceLog* trace_log) |
- : trace_log_(trace_log), |
- notification_(0) { |
-} |
- |
-TraceLog::NotificationHelper::~NotificationHelper() { |
-} |
- |
-void TraceLog::NotificationHelper::AddNotificationWhileLocked( |
- int notification) { |
- trace_log_->lock_.AssertAcquired(); |
- if (trace_log_->notification_callback_.is_null()) |
- return; |
- if (notification_ == 0) |
- callback_copy_ = trace_log_->notification_callback_; |
- notification_ |= notification; |
-} |
- |
-void TraceLog::NotificationHelper::SendNotificationIfAny() { |
- if (notification_) |
- callback_copy_.Run(notification_); |
-} |
- |
// static |
TraceLog* TraceLog::GetInstance() { |
return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get(); |
} |
-// static |
-// Note, if you add more options here you also need to update: |
-// content/browser/devtools/devtools_tracing_handler:TraceOptionsFromString |
-TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { |
- std::vector<std::string> split; |
- base::SplitString(options, ',', &split); |
- int ret = 0; |
- for (std::vector<std::string>::iterator iter = split.begin(); |
- iter != split.end(); |
- ++iter) { |
- if (*iter == kRecordUntilFull) { |
- ret |= RECORD_UNTIL_FULL; |
- } else if (*iter == kRecordContinuously) { |
- ret |= RECORD_CONTINUOUSLY; |
- } else if (*iter == kEnableSampling) { |
- ret |= ENABLE_SAMPLING; |
- } else if (*iter == kMonitorSampling) { |
- ret |= MONITOR_SAMPLING; |
- } else { |
- NOTREACHED(); // Unknown option provided. |
- } |
- } |
- if (!(ret & RECORD_UNTIL_FULL) && !(ret & RECORD_CONTINUOUSLY)) |
- ret |= RECORD_UNTIL_FULL; // Default when no options are specified. |
- |
- return static_cast<Options>(ret); |
-} |
- |
TraceLog::TraceLog() |
: enabled_(false), |
num_traces_recorded_(0), |
- buffer_is_full_(0), |
event_callback_(0), |
dispatching_to_observer_list_(false), |
process_sort_index_(0), |
@@ -1328,7 +1265,6 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
subtle::NoBarrier_Store(&trace_options_, options); |
logged_events_.reset(CreateTraceBuffer()); |
NextGeneration(); |
- subtle::NoBarrier_Store(&buffer_is_full_, 0); |
} |
num_traces_recorded_++; |
@@ -1375,49 +1311,52 @@ CategoryFilter TraceLog::GetCurrentCategoryFilter() { |
} |
void TraceLog::SetDisabled() { |
- std::vector<EnabledStateObserver*> observer_list; |
- { |
- AutoLock lock(lock_); |
- if (!enabled_) |
- return; |
+ AutoLock lock(lock_); |
+ SetDisabledWhileLocked(); |
+} |
- if (dispatching_to_observer_list_) { |
- DLOG(ERROR) |
- << "Cannot manipulate TraceLog::Enabled state from an observer."; |
- return; |
- } |
+void TraceLog::SetDisabledWhileLocked() { |
+ lock_.AssertAcquired(); |
- enabled_ = false; |
+ if (!enabled_) |
+ return; |
- if (sampling_thread_.get()) { |
- // Stop the sampling thread. |
- sampling_thread_->Stop(); |
- lock_.Release(); |
- PlatformThread::Join(sampling_thread_handle_); |
- lock_.Acquire(); |
- sampling_thread_handle_ = PlatformThreadHandle(); |
- sampling_thread_.reset(); |
- } |
+ if (dispatching_to_observer_list_) { |
+ DLOG(ERROR) |
+ << "Cannot manipulate TraceLog::Enabled state from an observer."; |
+ return; |
+ } |
- category_filter_.Clear(); |
- subtle::NoBarrier_Store(&watch_category_, 0); |
- watch_event_name_ = ""; |
- UpdateCategoryGroupEnabledFlags(); |
- AddMetadataEventsWhileLocked(); |
+ enabled_ = false; |
- dispatching_to_observer_list_ = true; |
- observer_list = enabled_state_observer_list_; |
+ if (sampling_thread_.get()) { |
+ // Stop the sampling thread. |
+ sampling_thread_->Stop(); |
+ lock_.Release(); |
+ PlatformThread::Join(sampling_thread_handle_); |
+ lock_.Acquire(); |
+ sampling_thread_handle_ = PlatformThreadHandle(); |
+ sampling_thread_.reset(); |
} |
- // Dispatch to observers outside the lock in case the observer triggers a |
- // trace event. |
- for (size_t i = 0; i < observer_list.size(); ++i) |
- observer_list[i]->OnTraceLogDisabled(); |
+ category_filter_.Clear(); |
+ subtle::NoBarrier_Store(&watch_category_, 0); |
+ watch_event_name_ = ""; |
+ UpdateCategoryGroupEnabledFlags(); |
+ AddMetadataEventsWhileLocked(); |
+ |
+ dispatching_to_observer_list_ = true; |
+ std::vector<EnabledStateObserver*> observer_list = |
+ enabled_state_observer_list_; |
{ |
- AutoLock lock(lock_); |
- dispatching_to_observer_list_ = false; |
+ // Dispatch to observers outside the lock in case the observer triggers a |
+ // trace event. |
+ AutoUnlock unlock(lock_); |
+ for (size_t i = 0; i < observer_list.size(); ++i) |
+ observer_list[i]->OnTraceLogDisabled(); |
} |
+ dispatching_to_observer_list_ = false; |
} |
int TraceLog::GetNumTracesRecorded() { |
@@ -1449,14 +1388,14 @@ bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { |
} |
float TraceLog::GetBufferPercentFull() const { |
+ AutoLock lock(lock_); |
return static_cast<float>(static_cast<double>(logged_events_->Size()) / |
logged_events_->Capacity()); |
} |
-void TraceLog::SetNotificationCallback( |
- const TraceLog::NotificationCallback& cb) { |
+bool TraceLog::BufferIsFull() const { |
AutoLock lock(lock_); |
- notification_callback_ = cb; |
+ return logged_events_->IsFull(); |
} |
TraceBuffer* TraceLog::CreateTraceBuffer() { |
@@ -1471,7 +1410,7 @@ TraceBuffer* TraceLog::CreateTraceBuffer() { |
} |
TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( |
- NotificationHelper* notifier, TraceEventHandle* handle) { |
+ TraceEventHandle* handle, bool check_buffer_is_full) { |
lock_.AssertAcquired(); |
if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) { |
@@ -1482,8 +1421,8 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( |
if (!thread_shared_chunk_) { |
thread_shared_chunk_ = logged_events_->GetChunk( |
&thread_shared_chunk_index_); |
- if (notifier) |
- CheckIfBufferIsFullWhileLocked(notifier); |
+ if (check_buffer_is_full) |
+ CheckIfBufferIsFullWhileLocked(); |
} |
if (!thread_shared_chunk_) |
return NULL; |
@@ -1497,13 +1436,10 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( |
return trace_event; |
} |
-void TraceLog::CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier) { |
+void TraceLog::CheckIfBufferIsFullWhileLocked() { |
lock_.AssertAcquired(); |
- if (!subtle::NoBarrier_Load(&buffer_is_full_) && logged_events_->IsFull()) { |
- subtle::NoBarrier_Store(&buffer_is_full_, |
- static_cast<subtle::AtomicWord>(1)); |
- notifier->AddNotificationWhileLocked(TRACE_BUFFER_FULL); |
- } |
+ if (logged_events_->IsFull()) |
+ SetDisabledWhileLocked(); |
} |
void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter, |
@@ -1620,7 +1556,6 @@ void TraceLog::FinishFlush(int generation) { |
previous_logged_events.swap(logged_events_); |
logged_events_.reset(CreateTraceBuffer()); |
NextGeneration(); |
- subtle::NoBarrier_Store(&buffer_is_full_, 0); |
thread_message_loops_.clear(); |
flush_message_loop_proxy_ = NULL; |
@@ -1740,8 +1675,6 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
TimeTicks now = OffsetTimestamp(timestamp); |
TimeTicks thread_now = ThreadNow(); |
- NotificationHelper notifier(this); |
- |
ThreadLocalEventBuffer* thread_local_event_buffer = NULL; |
// A ThreadLocalEventBuffer needs the message loop |
// - to know when the thread exits; |
@@ -1798,15 +1731,13 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
} |
TraceEvent* trace_event = NULL; |
- if ((*category_group_enabled & ENABLED_FOR_RECORDING) && |
- !subtle::NoBarrier_Load(&buffer_is_full_)) { |
+ if ((*category_group_enabled & ENABLED_FOR_RECORDING)) { |
if (thread_local_event_buffer) { |
lock.EnsureReleased(); |
- trace_event = thread_local_event_buffer->AddTraceEvent(¬ifier, |
- &handle); |
+ trace_event = thread_local_event_buffer->AddTraceEvent(&handle); |
} else { |
lock.EnsureAcquired(); |
- trace_event = AddEventToThreadSharedChunkWhileLocked(¬ifier, &handle); |
+ trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true); |
} |
if (trace_event) { |
@@ -1819,20 +1750,24 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
trace_event->SendToATrace(); |
#endif |
} |
- } |
- if (trace_options() & ECHO_TO_CONSOLE) { |
- lock.EnsureAcquired(); |
- OutputEventToConsoleWhileLocked( |
- phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, |
- timestamp, trace_event); |
+ if (trace_options() & ECHO_TO_CONSOLE) { |
+ lock.EnsureAcquired(); |
+ OutputEventToConsoleWhileLocked( |
+ phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, |
+ timestamp, trace_event); |
+ } |
} |
if (reinterpret_cast<const unsigned char*>(subtle::NoBarrier_Load( |
&watch_category_)) == category_group_enabled) { |
lock.EnsureAcquired(); |
- if (watch_event_name_ == name) |
- notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION); |
+ if (watch_event_name_ == name) { |
+ WatchEventCallback watch_event_callback_copy = watch_event_callback_; |
+ lock.EnsureReleased(); |
+ if (!watch_event_callback_copy.is_null()) |
+ watch_event_callback_copy.Run(); |
+ } |
} |
lock.EnsureReleased(); |
@@ -1850,9 +1785,7 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
} |
if (thread_local_event_buffer) |
- thread_local_event_buffer->ReportOverhead(now, thread_now, ¬ifier); |
- |
- notifier.SendNotificationIfAny(); |
+ thread_local_event_buffer->ReportOverhead(now, thread_now); |
return handle; |
} |
@@ -1962,19 +1895,22 @@ void TraceLog::UpdateTraceEventDuration( |
} |
void TraceLog::SetWatchEvent(const std::string& category_name, |
- const std::string& event_name) { |
+ const std::string& event_name, |
+ const WatchEventCallback& callback) { |
const unsigned char* category = GetCategoryGroupEnabled( |
category_name.c_str()); |
AutoLock lock(lock_); |
subtle::NoBarrier_Store(&watch_category_, |
reinterpret_cast<subtle::AtomicWord>(category)); |
watch_event_name_ = event_name; |
+ watch_event_callback_ = callback; |
} |
void TraceLog::CancelWatchEvent() { |
AutoLock lock(lock_); |
subtle::NoBarrier_Store(&watch_category_, 0); |
watch_event_name_ = ""; |
+ watch_event_callback_.Reset(); |
} |
void TraceLog::AddMetadataEventsWhileLocked() { |
@@ -1982,14 +1918,14 @@ void TraceLog::AddMetadataEventsWhileLocked() { |
int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId()); |
if (process_sort_index_ != 0) { |
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), |
current_thread_id, |
"process_sort_index", "sort_index", |
process_sort_index_); |
} |
if (process_name_.size()) { |
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), |
current_thread_id, |
"process_name", "name", |
process_name_); |
@@ -2002,7 +1938,7 @@ void TraceLog::AddMetadataEventsWhileLocked() { |
it++) { |
labels.push_back(it->second); |
} |
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), |
current_thread_id, |
"process_labels", "labels", |
JoinString(labels, ',')); |
@@ -2014,7 +1950,7 @@ void TraceLog::AddMetadataEventsWhileLocked() { |
it++) { |
if (it->second == 0) |
continue; |
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), |
it->first, |
"thread_sort_index", "sort_index", |
it->second); |
@@ -2026,7 +1962,7 @@ void TraceLog::AddMetadataEventsWhileLocked() { |
it++) { |
if (it->second.empty()) |
continue; |
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL), |
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false), |
it->first, |
"thread_name", "name", |
it->second); |