Index: base/trace_event/memory_dump_manager.cc |
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc |
index 5e34147063662d016ddb8ef003eb21928801a03d..096eaf88487828c43ca9748182282eeed73df80a 100644 |
--- a/base/trace_event/memory_dump_manager.cc |
+++ b/base/trace_event/memory_dump_manager.cc |
@@ -284,6 +284,15 @@ void MemoryDumpManager::RegisterDumpProviderInternal( |
// path for RenderThreadImpl::Init(). |
if (already_registered) |
return; |
+ |
+ // The list of polling MDPs is populated OnTraceLogEnabled(). This code |
+ // deals with the case of a MDP capable of fast polling that is registered |
+ // after the OnTraceLogEnabled() |
+ if (options.is_fast_polling_supported && dump_thread_) { |
+ dump_thread_->task_runner()->PostTask( |
+ FROM_HERE, Bind(&MemoryDumpManager::RegisterPollingMDPOnDumpThread, |
+ Unretained(this), mdpinfo)); |
+ } |
} |
if (heap_profiling_enabled_) |
@@ -322,6 +331,7 @@ void MemoryDumpManager::UnregisterDumpProviderInternal( |
// - At the end of this function, if no dump is in progress. |
// - Either in SetupNextMemoryDump() or InvokeOnMemoryDump() when MDPInfo is |
// removed from |pending_dump_providers|. |
+ // - When the provider is removed from |dump_providers_for_polling_|. |
DCHECK(!(*mdp_iter)->owned_dump_provider); |
(*mdp_iter)->owned_dump_provider = std::move(owned_mdp); |
} else if (subtle::NoBarrier_Load(&memory_tracing_enabled_)) { |
@@ -340,6 +350,16 @@ void MemoryDumpManager::UnregisterDumpProviderInternal( |
<< "unregister itself in a racy way. Please file a crbug."; |
} |
+ if ((*mdp_iter)->options.is_fast_polling_supported && dump_thread_) { |
+ DCHECK(take_mdp_ownership_and_delete_async) |
+ << "MemoryDumpProviders capable of fast polling must NOT be thread " |
+ "bound and hence must be destroyed using " |
+ "UnregisterAndDeleteDumpProviderSoon()"; |
+ dump_thread_->task_runner()->PostTask( |
+ FROM_HERE, Bind(&MemoryDumpManager::UnregisterPollingMDPOnDumpThread, |
+ Unretained(this), *mdp_iter)); |
+ } |
+ |
// The MDPInfo instance can still be referenced by the |
// |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason |
// the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump() |
@@ -349,6 +369,21 @@ void MemoryDumpManager::UnregisterDumpProviderInternal( |
dump_providers_.erase(mdp_iter); |
} |
+void MemoryDumpManager::RegisterPollingMDPOnDumpThread( |
+ scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
+ DCHECK(!mdpinfo->task_runner); |
+ AutoLock lock(lock_); |
+ dump_providers_for_polling_.insert(mdpinfo); |
+} |
+ |
+void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( |
+ scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
+ mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
+ |
+ AutoLock lock(lock_); |
+ dump_providers_for_polling_.erase(mdpinfo); |
+} |
+ |
void MemoryDumpManager::RequestGlobalDump( |
MemoryDumpType dump_type, |
MemoryDumpLevelOfDetail level_of_detail, |
@@ -602,6 +637,18 @@ void MemoryDumpManager::InvokeOnMemoryDump( |
SetupNextMemoryDump(std::move(pmd_async_state)); |
} |
+void MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { |
+ *memory_total = 0; |
+ // Note that we call PollFastMemoryTotal() even if the dump provider is |
+ // disabled (unregistered). This is to avoid taking lock while polling. |
+ for (const auto& mdpinfo : dump_providers_for_polling_) { |
+ uint64_t value = 0; |
+ mdpinfo->dump_provider->PollFastMemoryTotal(&value); |
+ *memory_total += value; |
+ } |
+ return; |
+} |
+ |
// static |
void MemoryDumpManager::FinalizeDumpAndAddToTrace( |
std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
@@ -715,6 +762,12 @@ void MemoryDumpManager::OnTraceLogEnabled() { |
DCHECK(!dump_thread_); |
dump_thread_ = std::move(dump_thread); |
+ dump_providers_for_polling_.clear(); |
+ for (const auto& mdpinfo : dump_providers_) { |
+ if (mdpinfo->options.is_fast_polling_supported) |
+ dump_providers_for_polling_.insert(mdpinfo); |
+ } |
+ |
subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
// TODO(primiano): This is a temporary hack to disable periodic memory dumps |
@@ -735,6 +788,8 @@ void MemoryDumpManager::OnTraceLogDisabled() { |
// There might be a memory dump in progress while this happens. Therefore, |
// ensure that the MDM state which depends on the tracing enabled / disabled |
// state is always accessed by the dumping methods holding the |lock_|. |
+ if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
+ return; |
subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
std::unique_ptr<Thread> dump_thread; |
{ |
@@ -748,6 +803,15 @@ void MemoryDumpManager::OnTraceLogDisabled() { |
periodic_dump_timer_.Stop(); |
if (dump_thread) |
dump_thread->Stop(); |
+ |
+ // |dump_providers_for_polling_| must be cleared only after the dump thread is |
+ // stopped (polling tasks are done). |
+ { |
+ AutoLock lock(lock_); |
+ for (const auto& mdpinfo : dump_providers_for_polling_) |
+ mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
+ dump_providers_for_polling_.clear(); |
+ } |
} |
bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { |