Index: base/debug/trace_event_impl.cc |
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc |
index 9a75ad3db26d39032b6f1147b4877c9406a257d0..d2f05fc1db77ec9680078de0db802d28d6c5aab1 100644 |
--- a/base/debug/trace_event_impl.cc |
+++ b/base/debug/trace_event_impl.cc |
@@ -1149,7 +1149,7 @@ TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { |
} |
TraceLog::TraceLog() |
- : enable_count_(0), |
+ : enabled_(false), |
num_traces_recorded_(0), |
buffer_is_full_(0), |
event_callback_(0), |
@@ -1161,6 +1161,8 @@ TraceLog::TraceLog() |
trace_options_(RECORD_UNTIL_FULL), |
sampling_thread_handle_(0), |
category_filter_(CategoryFilter::kDefaultCategoryFilterString), |
+ event_callback_category_filter_( |
+ CategoryFilter::kDefaultCategoryFilterString), |
thread_shared_chunk_index_(0), |
generation_(0) { |
// Trace is enabled or disabled on one thread while other threads are |
@@ -1227,10 +1229,14 @@ const char* TraceLog::GetCategoryGroupName( |
} |
void TraceLog::UpdateCategoryGroupEnabledFlag(int category_index) { |
- g_category_group_enabled[category_index] = |
- enable_count_ && |
- category_filter_.IsCategoryGroupEnabled( |
- g_category_groups[category_index]); |
+ unsigned char enabled_flag = 0; |
+ const char* category_group = g_category_groups[category_index]; |
+ if (enabled_ && category_filter_.IsCategoryGroupEnabled(category_group)) |
+ enabled_flag |= ENABLED_FOR_RECORDING; |
+ if (event_callback_ && |
+ event_callback_category_filter_.IsCategoryGroupEnabled(category_group)) |
+ enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; |
+ g_category_group_enabled[category_index] = enabled_flag; |
} |
void TraceLog::UpdateCategoryGroupEnabledFlags() { |
@@ -1299,7 +1305,7 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
Options old_options = trace_options(); |
- if (enable_count_++ > 0) { |
+ if (enabled_) { |
if (options != old_options) { |
DLOG(ERROR) << "Attemting to re-enable tracing with a different " |
<< "set of options."; |
@@ -1310,6 +1316,14 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
return; |
} |
+ if (dispatching_to_observer_list_) { |
+ DLOG(ERROR) << |
+ "Cannot manipulate TraceLog::Enabled state from an observer."; |
+ return; |
+ } |
+ |
+ enabled_ = true; |
+ |
if (options != old_options) { |
subtle::NoBarrier_Store(&trace_options_, options); |
logged_events_.reset(CreateTraceBuffer()); |
@@ -1317,12 +1331,6 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
subtle::NoBarrier_Store(&buffer_is_full_, 0); |
} |
- if (dispatching_to_observer_list_) { |
- DLOG(ERROR) << |
- "Cannot manipulate TraceLog::Enabled state from an observer."; |
- return; |
- } |
- |
num_traces_recorded_++; |
category_filter_ = CategoryFilter(category_filter); |
@@ -1361,9 +1369,8 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, |
} |
} |
-const CategoryFilter& TraceLog::GetCurrentCategoryFilter() { |
+CategoryFilter TraceLog::GetCurrentCategoryFilter() { |
AutoLock lock(lock_); |
- DCHECK(enable_count_ > 0); |
return category_filter_; |
} |
@@ -1371,9 +1378,7 @@ void TraceLog::SetDisabled() { |
std::vector<EnabledStateObserver*> observer_list; |
{ |
AutoLock lock(lock_); |
- DCHECK(enable_count_ > 0); |
- |
- if (--enable_count_ != 0) |
+ if (!enabled_) |
return; |
if (dispatching_to_observer_list_) { |
@@ -1382,6 +1387,8 @@ void TraceLog::SetDisabled() { |
return; |
} |
+ enabled_ = false; |
+ |
if (sampling_thread_.get()) { |
// Stop the sampling thread. |
sampling_thread_->Stop(); |
@@ -1415,7 +1422,7 @@ void TraceLog::SetDisabled() { |
int TraceLog::GetNumTracesRecorded() { |
AutoLock lock(lock_); |
- if (enable_count_ == 0) |
+ if (!enabled_) |
return -1; |
return num_traces_recorded_; |
} |
@@ -1499,11 +1506,21 @@ void TraceLog::CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier) { |
} |
} |
-void TraceLog::SetEventCallback(EventCallback cb) { |
+void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter, |
+ EventCallback cb) { |
+ AutoLock lock(lock_); |
subtle::NoBarrier_Store(&event_callback_, |
reinterpret_cast<subtle::AtomicWord>(cb)); |
+ event_callback_category_filter_ = category_filter; |
+ UpdateCategoryGroupEnabledFlags(); |
}; |
+void TraceLog::SetEventCallbackDisabled() { |
+ AutoLock lock(lock_); |
+ subtle::NoBarrier_Store(&event_callback_, 0); |
+ UpdateCategoryGroupEnabledFlags(); |
+} |
+ |
// Flush() works as the following: |
// 1. Flush() is called in threadA whose message loop is saved in |
// flush_message_loop_proxy_; |
@@ -1784,7 +1801,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
} |
TraceEvent* trace_event = NULL; |
- if (!subtle::NoBarrier_Load(&buffer_is_full_)) { |
+ if ((*category_group_enabled & ENABLED_FOR_RECORDING) && |
+ !subtle::NoBarrier_Load(&buffer_is_full_)) { |
if (thread_local_event_buffer) { |
lock.EnsureReleased(); |
trace_event = thread_local_event_buffer->AddTraceEvent(¬ifier, |
@@ -1821,17 +1839,17 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( |
} |
lock.EnsureReleased(); |
- EventCallback event_callback = reinterpret_cast<EventCallback>( |
- subtle::NoBarrier_Load(&event_callback_)); |
- if (event_callback) { |
- // TODO(wangxianzhu): Should send TRACE_EVENT_PHASE_COMPLETE directly to |
- // clients if it is beneficial and feasible. |
- event_callback(now, |
- phase == TRACE_EVENT_PHASE_COMPLETE ? |
- TRACE_EVENT_PHASE_BEGIN : phase, |
- category_group_enabled, name, id, |
- num_args, arg_names, arg_types, arg_values, |
- flags); |
+ if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) { |
+ EventCallback event_callback = reinterpret_cast<EventCallback>( |
+ subtle::NoBarrier_Load(&event_callback_)); |
+ if (event_callback) { |
+ event_callback(now, |
+ phase == TRACE_EVENT_PHASE_COMPLETE ? |
+ TRACE_EVENT_PHASE_BEGIN : phase, |
+ category_group_enabled, name, id, |
+ num_args, arg_names, arg_types, arg_values, |
+ flags); |
+ } |
} |
if (thread_local_event_buffer) |
@@ -1911,38 +1929,49 @@ void TraceLog::AddTraceEventEtw(char phase, |
TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra); |
} |
-void TraceLog::UpdateTraceEventDuration(TraceEventHandle handle) { |
+void TraceLog::UpdateTraceEventDuration( |
+ const unsigned char* category_group_enabled, |
+ const char* name, |
+ TraceEventHandle handle) { |
OptionalAutoLock lock(lock_); |
TimeTicks now = OffsetNow(); |
- TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock); |
- if (trace_event) { |
- DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE); |
- trace_event->UpdateDuration(now); |
+ TraceEvent* trace_event = NULL; |
+ // TODO(wangxianzhu): Remove the !category_group_enabled condition after |
+ // all clients migrate to the new UpdateTraceEventDuration API. |
+ if (!category_group_enabled || |
+ (*category_group_enabled & ENABLED_FOR_RECORDING)) { |
+ trace_event = GetEventByHandleInternal(handle, &lock); |
+ if (trace_event) { |
+ DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE); |
+ trace_event->UpdateDuration(now); |
#if defined(OS_ANDROID) |
- trace_event->SendToATrace(); |
+ trace_event->SendToATrace(); |
#endif |
+ } |
+ |
+ if (trace_options() & ECHO_TO_CONSOLE) { |
+ lock.EnsureAcquired(); |
+ OutputEventToConsoleWhileLocked(TRACE_EVENT_PHASE_END, now, trace_event); |
+ } |
} |
- if (trace_options() & ECHO_TO_CONSOLE) { |
- lock.EnsureAcquired(); |
- OutputEventToConsoleWhileLocked(TRACE_EVENT_PHASE_END, now, trace_event); |
+ // TODO(wangxianzhu): Remove this block after all clients migrate to the |
+ // new UpdateTraceEventDuration API. |
+ if (!category_group_enabled || !name) { |
+ if (!trace_event) |
+ return; |
+ category_group_enabled = trace_event->category_group_enabled(); |
+ name = trace_event->name(); |
} |
- EventCallback event_callback = reinterpret_cast<EventCallback>( |
- subtle::NoBarrier_Load(&event_callback_)); |
- if (event_callback && trace_event) { |
- // The copy is needed when trace_event is from the main buffer in which case |
- // the lock has been locked. |
- TraceEvent event_copy; |
- event_copy.CopyFrom(*trace_event); |
- lock.EnsureReleased(); |
- // TODO(wangxianzhu): Should send TRACE_EVENT_PHASE_COMPLETE directly to |
- // clients if it is beneficial and feasible. |
- event_callback(now, TRACE_EVENT_PHASE_END, |
- event_copy.category_group_enabled(), |
- event_copy.name(), event_copy.id(), |
- 0, NULL, NULL, NULL, event_copy.flags()); |
+ lock.EnsureReleased(); |
+ if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) { |
+ EventCallback event_callback = reinterpret_cast<EventCallback>( |
+ subtle::NoBarrier_Load(&event_callback_)); |
+ event_callback(now, TRACE_EVENT_PHASE_END, category_group_enabled, name, |
+ trace_event_internal::kNoEventId, 0, NULL, NULL, NULL, |
+ TRACE_EVENT_FLAG_NONE); |
} |
} |
@@ -2286,6 +2315,7 @@ ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( |
static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; |
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( |
category_group, atomic, category_group_enabled_); |
+ name_ = name; |
if (*category_group_enabled_) { |
event_handle_ = |
TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( |
@@ -2298,8 +2328,10 @@ ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( |
} |
ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
- if (*category_group_enabled_) |
- TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(event_handle_); |
+ if (*category_group_enabled_) { |
+ TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
+ name_, event_handle_); |
+ } |
} |
} // namespace trace_event_internal |