Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: base/trace_event/memory_dump_manager.cc

Issue 1647803004: Move base to DEPS (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | base/trace_event/memory_dump_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
deleted file mode 100644
index e2ca702cb14adfb6e4ab027dc904cc2c704caa00..0000000000000000000000000000000000000000
--- a/base/trace_event/memory_dump_manager.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// 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/atomic_sequence_num.h"
-#include "base/compiler_specific.h"
-#include "base/hash.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"
-#include "base/trace_event/trace_event_argument.h"
-#include "build/build_config.h"
-
-#if !defined(OS_NACL)
-#include "base/trace_event/process_memory_totals_dump_provider.h"
-#endif
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#include "base/trace_event/malloc_dump_provider.h"
-#include "base/trace_event/process_memory_maps_dump_provider.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "base/trace_event/java_heap_dump_provider_android.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/trace_event/winheap_dump_provider_win.h"
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// TODO(primiano): this should be smarter and should do something similar to
-// trace event synthetic delays.
-const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra");
-
-// Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps.
-const int kHeavyMmapsDumpsRate = 8; // 250 ms * 8 = 2000 ms.
-const int kDumpIntervalMs = 250;
-const int kTraceEventNumArgs = 1;
-const char* kTraceEventArgNames[] = {"dumps"};
-const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
-
-StaticAtomicSequenceNumber g_next_guid;
-uint32 g_periodic_dumps_count = 0;
-MemoryDumpManager* g_instance_for_testing = nullptr;
-MemoryDumpProvider* g_mmaps_dump_provider = nullptr;
-
-void RequestPeriodicGlobalDump() {
- MemoryDumpType dump_type = g_periodic_dumps_count == 0
- ? MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS
- : MemoryDumpType::PERIODIC_INTERVAL;
- if (++g_periodic_dumps_count == kHeavyMmapsDumpsRate)
- g_periodic_dumps_count = 0;
-
- MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type);
-}
-
-} // namespace
-
-// static
-const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory;
-
-// static
-const uint64 MemoryDumpManager::kInvalidTracingProcessId = 0;
-
-// static
-const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3;
-
-// static
-MemoryDumpManager* MemoryDumpManager::GetInstance() {
- if (g_instance_for_testing)
- return g_instance_for_testing;
-
- return Singleton<MemoryDumpManager,
- LeakySingletonTraits<MemoryDumpManager>>::get();
-}
-
-// static
-void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
- if (instance)
- instance->skip_core_dumpers_auto_registration_for_testing_ = true;
- g_instance_for_testing = instance;
-}
-
-MemoryDumpManager::MemoryDumpManager()
- : did_unregister_dump_provider_(false),
- delegate_(nullptr),
- memory_tracing_enabled_(0),
- tracing_process_id_(kInvalidTracingProcessId),
- skip_core_dumpers_auto_registration_for_testing_(false) {
- g_next_guid.GetNext(); // Make sure that first guid is not zero.
-}
-
-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);
-
- if (skip_core_dumpers_auto_registration_for_testing_)
- return;
-
- // Enable the core dump providers.
-#if !defined(OS_NACL)
- RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
-#endif
-
-#if (defined(OS_LINUX) && !defined(FNL_MUSL)) || defined(OS_ANDROID)
- g_mmaps_dump_provider = ProcessMemoryMapsDumpProvider::GetInstance();
- RegisterDumpProvider(g_mmaps_dump_provider);
- RegisterDumpProvider(MallocDumpProvider::GetInstance());
-#endif
-
-#if defined(OS_ANDROID)
- RegisterDumpProvider(JavaHeapDumpProvider::GetInstance());
-#endif
-
-#if defined(OS_WIN)
- RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
-#endif
-}
-
-void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
- AutoLock lock(lock_);
- DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
- delegate_ = delegate;
-}
-
-void MemoryDumpManager::RegisterDumpProvider(
- MemoryDumpProvider* mdp,
- const scoped_refptr<SingleThreadTaskRunner>& task_runner) {
- MemoryDumpProviderInfo mdp_info(mdp, task_runner);
- AutoLock lock(lock_);
- dump_providers_.insert(mdp_info);
-}
-
-void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
- RegisterDumpProvider(mdp, nullptr);
-}
-
-void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
- AutoLock lock(lock_);
-
- auto mdp_iter = dump_providers_.begin();
- for (; mdp_iter != dump_providers_.end(); ++mdp_iter) {
- if (mdp_iter->dump_provider == mdp)
- break;
- }
-
- if (mdp_iter == dump_providers_.end())
- return;
-
- // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
- // only if the MDP has specified a thread affinity (via task_runner()) AND
- // the unregistration happens on the same thread (so the MDP cannot unregister
- // and OnMemoryDump() at the same time).
- // Otherwise, it is not possible to guarantee that its unregistration is
- // race-free. If you hit this DCHECK, your MDP has a bug.
- DCHECK_IMPLIES(
- subtle::NoBarrier_Load(&memory_tracing_enabled_),
- mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread())
- << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
- << "Please file a crbug.";
-
- dump_providers_.erase(mdp_iter);
- did_unregister_dump_provider_ = true;
-}
-
-void MemoryDumpManager::RequestGlobalDump(
- MemoryDumpType dump_type,
- const MemoryDumpCallback& callback) {
- // Bail out immediately if tracing is not enabled at all.
- if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
- return;
-
- const uint64 guid =
- TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
-
- // The delegate_ is supposed to be thread safe, immutable and long lived.
- // No need to keep the lock after we ensure that a delegate has been set.
- MemoryDumpManagerDelegate* delegate;
- {
- AutoLock lock(lock_);
- delegate = delegate_;
- }
-
- if (delegate) {
- // The delegate is in charge to coordinate the request among all the
- // processes and call the CreateLocalDumpPoint on the local process.
- MemoryDumpRequestArgs args = {guid, dump_type};
- delegate->RequestGlobalMemoryDump(args, callback);
- } else if (!callback.is_null()) {
- callback.Run(guid, false /* success */);
- }
-}
-
-void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) {
- RequestGlobalDump(dump_type, MemoryDumpCallback());
-}
-
-void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
- const MemoryDumpCallback& callback) {
- scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
- {
- AutoLock lock(lock_);
- did_unregister_dump_provider_ = false;
- pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
- args, dump_providers_.begin(), session_state_, callback));
- }
-
- // Start the thread hop. |dump_providers_| are kept sorted by thread, so
- // ContinueAsyncProcessDump will hop at most once per thread (w.r.t. thread
- // affinity specified by the MemoryDumpProvider(s) in RegisterDumpProvider()).
- ContinueAsyncProcessDump(pmd_async_state.Pass());
-}
-
-// At most one ContinueAsyncProcessDump() can be active at any time for a given
-// PMD, regardless of status of the |lock_|. |lock_| is used here purely to
-// ensure consistency w.r.t. (un)registrations of |dump_providers_|.
-// The linearization of dump providers' OnMemoryDump invocations is achieved by
-// means of subsequent PostTask(s).
-//
-// 1) Prologue:
-// - Check if the dump provider is disabled, if so skip the dump.
-// - Check if we are on the right thread. If not hop and continue there.
-// 2) Invoke the dump provider's OnMemoryDump() (unless skipped).
-// 3) Epilogue:
-// - Unregister the dump provider if it failed too many times consecutively.
-// - Advance the |next_dump_provider| iterator to the next dump provider.
-// - If this was the last hop, create a trace event, add it to the trace
-// and finalize (invoke callback).
-
-void MemoryDumpManager::ContinueAsyncProcessDump(
- scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
- // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs
- // in the PostTask below don't end up registering their own dump providers
- // (for discounting trace memory overhead) while holding the |lock_|.
- TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
-
- // DO NOT put any LOG() statement in the locked sections, as in some contexts
- // (GPU process) LOG() ends up performing PostTask/IPCs.
- MemoryDumpProvider* mdp;
- bool skip_dump = false;
- {
- AutoLock lock(lock_);
- // In the unlikely event that a dump provider was unregistered while
- // dumping, abort the dump, as that would make |next_dump_provider| invalid.
- // Registration, on the other hand, is safe as per std::set<> contract.
- if (did_unregister_dump_provider_) {
- return AbortDumpLocked(pmd_async_state->callback,
- pmd_async_state->task_runner,
- pmd_async_state->req_args.dump_guid);
- }
-
- auto* mdp_info = &*pmd_async_state->next_dump_provider;
- mdp = mdp_info->dump_provider;
- if (mdp_info->disabled) {
- skip_dump = true;
- } else if (mdp == g_mmaps_dump_provider &&
- pmd_async_state->req_args.dump_type !=
- MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS) {
- // Mmaps dumping is very heavyweight and cannot be performed at the same
- // rate of other dumps. TODO(primiano): this is a hack and should be
- // cleaned up as part of crbug.com/499731.
- skip_dump = true;
- } else if (mdp_info->task_runner &&
- !mdp_info->task_runner->BelongsToCurrentThread()) {
- // It's time to hop onto another thread.
-
- // Copy the callback + arguments just for the unlikley case in which
- // PostTask fails. In such case the Bind helper will destroy the
- // pmd_async_state and we must keep a copy of the fields to notify the
- // abort.
- MemoryDumpCallback callback = pmd_async_state->callback;
- scoped_refptr<SingleThreadTaskRunner> callback_task_runner =
- pmd_async_state->task_runner;
- const uint64 dump_guid = pmd_async_state->req_args.dump_guid;
-
- const bool did_post_task = mdp_info->task_runner->PostTask(
- FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
- Unretained(this), Passed(pmd_async_state.Pass())));
- if (did_post_task)
- return;
-
- // The thread is gone. At this point the best thing we can do is to
- // disable the dump provider and abort this dump.
- mdp_info->disabled = true;
- return AbortDumpLocked(callback, callback_task_runner, dump_guid);
- }
- } // AutoLock(lock_)
-
- // Invoke the dump provider without holding the |lock_|.
- bool finalize = false;
- bool dump_successful = false;
- if (!skip_dump)
- dump_successful = mdp->OnMemoryDump(&pmd_async_state->process_memory_dump);
-
- {
- AutoLock lock(lock_);
- if (did_unregister_dump_provider_) {
- return AbortDumpLocked(pmd_async_state->callback,
- pmd_async_state->task_runner,
- pmd_async_state->req_args.dump_guid);
- }
- auto* mdp_info = &*pmd_async_state->next_dump_provider;
- if (dump_successful) {
- mdp_info->consecutive_failures = 0;
- } else if (!skip_dump) {
- ++mdp_info->consecutive_failures;
- if (mdp_info->consecutive_failures >= kMaxConsecutiveFailuresCount) {
- mdp_info->disabled = true;
- }
- }
- ++pmd_async_state->next_dump_provider;
- finalize = pmd_async_state->next_dump_provider == dump_providers_.end();
- }
-
- if (!skip_dump && !dump_successful) {
- LOG(ERROR) << "A memory dumper failed, possibly due to sandboxing "
- "(crbug.com/461788). Disabling dumper for current process. "
- "Try restarting chrome with the --no-sandbox switch.";
- }
-
- if (finalize)
- return FinalizeDumpAndAddToTrace(pmd_async_state.Pass());
-
- ContinueAsyncProcessDump(pmd_async_state.Pass());
-}
-
-// static
-void MemoryDumpManager::FinalizeDumpAndAddToTrace(
- scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
- if (!pmd_async_state->task_runner->BelongsToCurrentThread()) {
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- pmd_async_state->task_runner;
- task_runner->PostTask(FROM_HERE,
- Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace,
- Passed(pmd_async_state.Pass())));
- return;
- }
-
- scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
- pmd_async_state->process_memory_dump.AsValueInto(
- static_cast<TracedValue*>(event_value.get()));
- const char* const event_name =
- MemoryDumpTypeToString(pmd_async_state->req_args.dump_type);
-
- TRACE_EVENT_API_ADD_TRACE_EVENT(
- TRACE_EVENT_PHASE_MEMORY_DUMP,
- TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
- pmd_async_state->req_args.dump_guid, kTraceEventNumArgs,
- kTraceEventArgNames, kTraceEventArgTypes, nullptr /* arg_values */,
- &event_value, TRACE_EVENT_FLAG_HAS_ID);
-
- if (!pmd_async_state->callback.is_null()) {
- pmd_async_state->callback.Run(pmd_async_state->req_args.dump_guid,
- true /* success */);
- pmd_async_state->callback.Reset();
- }
-}
-
-// static
-void MemoryDumpManager::AbortDumpLocked(
- MemoryDumpCallback callback,
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- uint64 dump_guid) {
- if (callback.is_null())
- return; // There is nothing to NACK.
-
- // Post the callback even if we are already on the right thread to avoid
- // invoking the callback while holding the lock_.
- task_runner->PostTask(FROM_HERE,
- Bind(callback, dump_guid, false /* success */));
-}
-
-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);
-
- // Initialize the TraceLog for the current thread. This is to avoid that the
- // TraceLog memory dump provider is registered lazily in the PostTask() below
- // while the |lock_| is taken;
- TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
-
- AutoLock lock(lock_);
-
- // There is no point starting the tracing without a delegate.
- if (!enabled || !delegate_) {
- // Disable all the providers.
- for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
- it->disabled = true;
- return;
- }
-
- session_state_ = new MemoryDumpSessionState();
- for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
- it->disabled = false;
- it->consecutive_failures = 0;
- }
-
- subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
-
- if (delegate_->IsCoordinatorProcess()) {
- g_periodic_dumps_count = 0;
- periodic_dump_timer_.Start(FROM_HERE,
- TimeDelta::FromMilliseconds(kDumpIntervalMs),
- base::Bind(&RequestPeriodicGlobalDump));
- }
-}
-
-void MemoryDumpManager::OnTraceLogDisabled() {
- AutoLock lock(lock_);
- periodic_dump_timer_.Stop();
- subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
- session_state_ = nullptr;
-}
-
-// static
-uint64 MemoryDumpManager::ChildProcessIdToTracingProcessId(
- int child_process_id) {
- return static_cast<uint64>(
- Hash(reinterpret_cast<const char*>(&child_process_id),
- sizeof(child_process_id))) +
- 1;
-}
-
-MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
- MemoryDumpProvider* dump_provider,
- const scoped_refptr<SingleThreadTaskRunner>& task_runner)
- : dump_provider(dump_provider),
- task_runner(task_runner),
- consecutive_failures(0),
- disabled(false) {}
-
-MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {
-}
-
-bool MemoryDumpManager::MemoryDumpProviderInfo::operator<(
- const MemoryDumpProviderInfo& other) const {
- if (task_runner == other.task_runner)
- return dump_provider < other.dump_provider;
- return task_runner < other.task_runner;
-}
-
-MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
- MemoryDumpRequestArgs req_args,
- MemoryDumpProviderInfoSet::iterator next_dump_provider,
- const scoped_refptr<MemoryDumpSessionState>& session_state,
- MemoryDumpCallback callback)
- : process_memory_dump(session_state),
- req_args(req_args),
- next_dump_provider(next_dump_provider),
- callback(callback),
- task_runner(MessageLoop::current()->task_runner()) {}
-
-MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() {
-}
-
-} // namespace trace_event
-} // namespace base
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | base/trace_event/memory_dump_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698