summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorprimiano <primiano@chromium.org>2015-06-16 13:56:41 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-16 20:57:08 +0000
commitc525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0 (patch)
treebe4c771f0943c5fce3f9714d754f1bbb65ea590f /base
parent027857bdba4dce9bea91ad4a49c9263e4c37c2f0 (diff)
downloadchromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.zip
chromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.tar.gz
chromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.tar.bz2
[tracing] Warmup the ThreadLocalEventBuffer when MemoryInfra is enabled
When memory tracing is enabled, the initialization of ThreadLocalEventBuffer registers its own MemoryDumpProvider to account for the memory overhead caused by tracing itself. Before this CL, the ThreadLocalEventBuffer is lazily initialized the first time a TRACE_EVENT* is called. Doing that w/ MemoryInfra enabled though could lead to a deadlock if the first TRACE_EVENT happens in the middle of a memory dump, in which case the ThreadLocalEventBuffer would try to register a dump provider while dumping. Races are broken by ensuring that, when a dump provider is being registered, the ThreadLocalEventBuffer for its thread is being initialized. BUG=500569 Review URL: https://codereview.chromium.org/1191473004 Cr-Commit-Position: refs/heads/master@{#334689}
Diffstat (limited to 'base')
-rw-r--r--base/trace_event/memory_dump_manager.cc25
-rw-r--r--base/trace_event/trace_event_impl.cc42
-rw-r--r--base/trace_event/trace_event_impl.h4
3 files changed, 51 insertions, 20 deletions
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index e10a77d..82fe10a 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -8,6 +8,7 @@
#include "base/atomic_sequence_num.h"
#include "base/compiler_specific.h"
+#include "base/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_dump.h"
@@ -142,6 +143,10 @@ void RequestPeriodicGlobalDump() {
MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type);
}
+void InitializeThreadLocalEventBufferIfSupported() {
+ TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
+}
+
} // namespace
// static
@@ -285,6 +290,11 @@ void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
bool did_any_provider_dump = false;
bool did_post_any_async_task = false;
+ // Initalizes the ThreadLocalEventBuffer for the syncrhonous dump providers
+ // that will be invoked in this thread without other posts. The initialization
+ // for the asynchronous providers, instead, is handled in OnTraceLogEnabled().
+ InitializeThreadLocalEventBufferIfSupported();
+
// Iterate over the active dump providers and invoke OnMemoryDump(pmd).
// The MDM guarantees linearity (at most one MDP is active within one
// process) and thread-safety (MDM enforces the right locking when entering /
@@ -396,8 +406,19 @@ void MemoryDumpManager::OnTraceLogEnabled() {
}
session_state_ = new MemoryDumpSessionState();
- for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
- it->second.disabled = false;
+ for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
+ MemoryDumpProviderInfo& mdp_info = it->second;
+ mdp_info.disabled = false;
+ if (mdp_info.task_runner) {
+ // The thread local event buffer must be initialized at this point as it
+ // registers its own dump provider (for tracing overhead acounting).
+ // The registration cannot happen lazily during the first TRACE_EVENT*
+ // as it might end up registering the ThreadLocalEventBuffer while
+ // in onMemoryDump(), which will deadlock.
+ mdp_info.task_runner->PostTask(
+ FROM_HERE, Bind(&InitializeThreadLocalEventBufferIfSupported));
+ }
+ }
subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 5882333..f760b88 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -1312,6 +1312,26 @@ TraceLog::TraceLog()
TraceLog::~TraceLog() {
}
+void TraceLog::InitializeThreadLocalEventBufferIfSupported() {
+ // A ThreadLocalEventBuffer needs the message loop
+ // - to know when the thread exits;
+ // - to handle the final flush.
+ // For a thread without a message loop or the message loop may be blocked, the
+ // trace events will be added into the main buffer directly.
+ if (thread_blocks_message_loop_.Get() || !MessageLoop::current())
+ return;
+ auto thread_local_event_buffer = thread_local_event_buffer_.Get();
+ if (thread_local_event_buffer &&
+ !CheckGeneration(thread_local_event_buffer->generation())) {
+ delete thread_local_event_buffer;
+ thread_local_event_buffer = NULL;
+ }
+ if (!thread_local_event_buffer) {
+ thread_local_event_buffer = new ThreadLocalEventBuffer(this);
+ thread_local_event_buffer_.Set(thread_local_event_buffer);
+ }
+}
+
bool TraceLog::OnMemoryDump(ProcessMemoryDump* pmd) {
TraceEventMemoryOverhead overhead;
overhead.Add("TraceLog", sizeof(*this));
@@ -2003,24 +2023,10 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
OffsetNow() : offset_event_timestamp;
ThreadTicks thread_now = ThreadNow();
- ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
- // A ThreadLocalEventBuffer needs the message loop
- // - to know when the thread exits;
- // - to handle the final flush.
- // For a thread without a message loop or the message loop may be blocked, the
- // trace events will be added into the main buffer directly.
- if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) {
- thread_local_event_buffer = thread_local_event_buffer_.Get();
- if (thread_local_event_buffer &&
- !CheckGeneration(thread_local_event_buffer->generation())) {
- delete thread_local_event_buffer;
- thread_local_event_buffer = NULL;
- }
- if (!thread_local_event_buffer) {
- thread_local_event_buffer = new ThreadLocalEventBuffer(this);
- thread_local_event_buffer_.Set(thread_local_event_buffer);
- }
- }
+ // |thread_local_event_buffer_| can be null if the current thread doesn't have
+ // a message loop or the message loop is blocked.
+ InitializeThreadLocalEventBufferIfSupported();
+ auto thread_local_event_buffer = thread_local_event_buffer_.Get();
// Check and update the current thread name only if the event is for the
// current thread to avoid locks in most cases.
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 503a69d..2922840 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -334,6 +334,10 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider {
// Retrieves a copy (for thread-safety) of the current TraceConfig.
TraceConfig GetCurrentTraceConfig() const;
+ // Initializes the thread-local event buffer, if not already initialized and
+ // if the current thread supports that (has a message loop).
+ void InitializeThreadLocalEventBufferIfSupported();
+
// Enables normal tracing (recording trace events in the trace buffer).
// See TraceConfig comments for details on how to control what categories
// will be traced. If tracing has already been enabled, |category_filter| will