| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bf631b34bea033cba4c95f76d4f73439ed703d3f
|
| --- /dev/null
|
| +++ b/base/trace_event/memory_dump_manager.cc
|
| @@ -0,0 +1,135 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/trace_event/memory_dump_manager.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/compiler_specific.h"
|
| +#include "base/trace_event/memory_dump_provider.h"
|
| +#include "base/trace_event/process_memory_dump.h"
|
| +
|
| +// TODO(primiano): in a separate CL rename DeleteTraceLogForTesting into
|
| +// something like base::internal::TeardownSingletonForTesting so we don't have
|
| +// to add a new friend to singleton each time.
|
| +class DeleteTraceLogForTesting {
|
| + public:
|
| + static void Delete() {
|
| + Singleton<
|
| + base::trace_event::MemoryDumpManager,
|
| + LeakySingletonTraits<base::trace_event::MemoryDumpManager>>::OnExit(0);
|
| + }
|
| +};
|
| +
|
| +namespace base {
|
| +namespace trace_event {
|
| +
|
| +// TODO(primiano): this should be smarter and should do something similar to
|
| +// trace event synthetic delays.
|
| +const char MemoryDumpManager::kTraceCategory[] =
|
| + TRACE_DISABLED_BY_DEFAULT("memory-dumps");
|
| +
|
| +// static
|
| +MemoryDumpManager* MemoryDumpManager::GetInstance() {
|
| + return Singleton<MemoryDumpManager,
|
| + LeakySingletonTraits<MemoryDumpManager>>::get();
|
| +}
|
| +
|
| +// static
|
| +void MemoryDumpManager::DeleteForTesting() {
|
| + DeleteTraceLogForTesting::Delete();
|
| +}
|
| +
|
| +MemoryDumpManager::MemoryDumpManager() : memory_tracing_enabled_(0) {
|
| +}
|
| +
|
| +MemoryDumpManager::~MemoryDumpManager() {
|
| + base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
|
| +}
|
| +
|
| +void MemoryDumpManager::Initialize() {
|
| + TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
|
| + trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
|
| +}
|
| +
|
| +void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
|
| + AutoLock lock(lock_);
|
| + if (std::find(dump_providers_registered_.begin(),
|
| + dump_providers_registered_.end(),
|
| + mdp) != dump_providers_registered_.end()) {
|
| + return;
|
| + }
|
| + dump_providers_registered_.push_back(mdp);
|
| +}
|
| +
|
| +void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
|
| + AutoLock lock(lock_);
|
| +
|
| + // Remove from the registered providers list.
|
| + auto it = std::find(dump_providers_registered_.begin(),
|
| + dump_providers_registered_.end(), mdp);
|
| + if (it != dump_providers_registered_.end())
|
| + dump_providers_registered_.erase(it);
|
| +
|
| + // Remove from the enabled providers list. This is to deal with the case that
|
| + // UnregisterDumpProvider is called while the trace is enabled.
|
| + it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
|
| + mdp);
|
| + if (it != dump_providers_enabled_.end())
|
| + dump_providers_enabled_.erase(it);
|
| +}
|
| +
|
| +void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
|
| + // TODO(primiano): this will have more logic, IPC broadcast & co.
|
| + // Bail out immediately if tracing is not enabled at all.
|
| + if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
|
| + return;
|
| +
|
| + CreateLocalDumpPoint();
|
| +}
|
| +
|
| +void MemoryDumpManager::BroadcastDumpRequest() {
|
| + NOTREACHED(); // TODO(primiano): implement IPC synchronization.
|
| +}
|
| +
|
| +// Creates a dump point for the current process and appends it to the trace.
|
| +void MemoryDumpManager::CreateLocalDumpPoint() {
|
| + AutoLock lock(lock_);
|
| + // TRACE_EVENT_* macros don't induce scoped_refptr type inference, hence we
|
| + // need the base ConvertableToTraceFormat and the upcast below. The
|
| + // alternative would be unnecessarily expensive (double Acquire/Release).
|
| + scoped_refptr<ConvertableToTraceFormat> pmd(new ProcessMemoryDump());
|
| +
|
| + for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
|
| + dump_provider->DumpInto(static_cast<ProcessMemoryDump*>(pmd.get()));
|
| + }
|
| +
|
| + // TODO(primiano): add the dump point to the trace at this point.
|
| +}
|
| +
|
| +void MemoryDumpManager::OnTraceLogEnabled() {
|
| + // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
|
| + // to figure out (and cache) which dumpers should be enabled or not.
|
| + // For the moment piggy back everything on the generic "memory" category.
|
| + bool enabled;
|
| + TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
|
| +
|
| + AutoLock lock(lock_);
|
| + if (enabled) {
|
| + dump_providers_enabled_.assign(dump_providers_registered_.begin(),
|
| + dump_providers_registered_.end());
|
| + } else {
|
| + dump_providers_enabled_.clear();
|
| + }
|
| + subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
|
| +}
|
| +
|
| +void MemoryDumpManager::OnTraceLogDisabled() {
|
| + AutoLock lock(lock_);
|
| + dump_providers_enabled_.clear();
|
| + subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
|
| +}
|
| +
|
| +} // namespace trace_event
|
| +} // namespace base
|
|
|