mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 06:16:30 +03:00
328 lines
14 KiB
C
328 lines
14 KiB
C
|
// 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.
|
||
|
|
||
|
#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
|
||
|
#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
|
||
|
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include <map>
|
||
|
#include <memory>
|
||
|
#include <unordered_set>
|
||
|
#include <vector>
|
||
|
|
||
|
#include "base/atomicops.h"
|
||
|
#include "base/containers/hash_tables.h"
|
||
|
#include "base/macros.h"
|
||
|
#include "base/memory/ref_counted.h"
|
||
|
#include "base/memory/singleton.h"
|
||
|
#include "base/synchronization/lock.h"
|
||
|
#include "base/trace_event/memory_allocator_dump.h"
|
||
|
#include "base/trace_event/memory_dump_provider_info.h"
|
||
|
#include "base/trace_event/memory_dump_request_args.h"
|
||
|
#include "base/trace_event/process_memory_dump.h"
|
||
|
#include "base/trace_event/trace_event.h"
|
||
|
|
||
|
namespace base {
|
||
|
|
||
|
class SequencedTaskRunner;
|
||
|
class SingleThreadTaskRunner;
|
||
|
class Thread;
|
||
|
|
||
|
namespace trace_event {
|
||
|
|
||
|
class MemoryDumpProvider;
|
||
|
class HeapProfilerSerializationState;
|
||
|
|
||
|
enum HeapProfilingMode {
|
||
|
kHeapProfilingModeDisabled,
|
||
|
kHeapProfilingModeTaskProfiler, // Per task counters for allocs and frees.
|
||
|
kHeapProfilingModeBackground, // Pseudo stacks without default filtering.
|
||
|
kHeapProfilingModePseudo, // Pseudo stacks with default filtering categories.
|
||
|
kHeapProfilingModeNative, // Native stacks
|
||
|
kHeapProfilingModeInvalid // Disabled permanently or unsupported.
|
||
|
};
|
||
|
|
||
|
// This is the interface exposed to the rest of the codebase to deal with
|
||
|
// memory tracing. The main entry point for clients is represented by
|
||
|
// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
|
||
|
class BASE_EXPORT MemoryDumpManager {
|
||
|
public:
|
||
|
using RequestGlobalDumpFunction =
|
||
|
RepeatingCallback<void(const GlobalMemoryDumpRequestArgs& args)>;
|
||
|
|
||
|
static const char* const kTraceCategory;
|
||
|
|
||
|
// This value is returned as the tracing id of the child processes by
|
||
|
// GetTracingProcessId() when tracing is not enabled.
|
||
|
static const uint64_t kInvalidTracingProcessId;
|
||
|
|
||
|
static MemoryDumpManager* GetInstance();
|
||
|
static std::unique_ptr<MemoryDumpManager> CreateInstanceForTesting();
|
||
|
|
||
|
// Invoked once per process to listen to trace begin / end events.
|
||
|
// Initialization can happen after (Un)RegisterMemoryDumpProvider() calls
|
||
|
// and the MemoryDumpManager guarantees to support this.
|
||
|
// On the other side, the MemoryDumpManager will not be fully operational
|
||
|
// (any CreateProcessDump() will return a failure) until initialized.
|
||
|
// Arguments:
|
||
|
// is_coordinator: True when current process coordinates the periodic dump
|
||
|
// triggering.
|
||
|
// request_dump_function: Function to invoke a global dump. Global dump
|
||
|
// involves embedder-specific behaviors like multiprocess handshaking.
|
||
|
// TODO(primiano): this is only required to trigger global dumps from
|
||
|
// the scheduler and the peak detector. Should be removed once they are
|
||
|
// both moved out of base.
|
||
|
void Initialize(RequestGlobalDumpFunction request_dump_function,
|
||
|
bool is_coordinator);
|
||
|
|
||
|
// (Un)Registers a MemoryDumpProvider instance.
|
||
|
// Args:
|
||
|
// - mdp: the MemoryDumpProvider instance to be registered. MemoryDumpManager
|
||
|
// does NOT take memory ownership of |mdp|, which is expected to either
|
||
|
// be a singleton or unregister itself.
|
||
|
// - name: a friendly name (duplicates allowed). Used for debugging and
|
||
|
// run-time profiling of memory-infra internals. Must be a long-lived
|
||
|
// C string.
|
||
|
// - task_runner: either a SingleThreadTaskRunner or SequencedTaskRunner. All
|
||
|
// the calls to |mdp| will be run on the given |task_runner|. If passed
|
||
|
// null |mdp| should be able to handle calls on arbitrary threads.
|
||
|
// - options: extra optional arguments. See memory_dump_provider.h.
|
||
|
void RegisterDumpProvider(MemoryDumpProvider* mdp,
|
||
|
const char* name,
|
||
|
scoped_refptr<SingleThreadTaskRunner> task_runner);
|
||
|
void RegisterDumpProvider(MemoryDumpProvider* mdp,
|
||
|
const char* name,
|
||
|
scoped_refptr<SingleThreadTaskRunner> task_runner,
|
||
|
MemoryDumpProvider::Options options);
|
||
|
void RegisterDumpProviderWithSequencedTaskRunner(
|
||
|
MemoryDumpProvider* mdp,
|
||
|
const char* name,
|
||
|
scoped_refptr<SequencedTaskRunner> task_runner,
|
||
|
MemoryDumpProvider::Options options);
|
||
|
void UnregisterDumpProvider(MemoryDumpProvider* mdp);
|
||
|
|
||
|
// Unregisters an unbound dump provider and takes care about its deletion
|
||
|
// asynchronously. Can be used only for for dump providers with no
|
||
|
// task-runner affinity.
|
||
|
// This method takes ownership of the dump provider and guarantees that:
|
||
|
// - The |mdp| will be deleted at some point in the near future.
|
||
|
// - Its deletion will not happen concurrently with the OnMemoryDump() call.
|
||
|
// Note that OnMemoryDump() and PollFastMemoryTotal() calls can still happen
|
||
|
// after this method returns.
|
||
|
void UnregisterAndDeleteDumpProviderSoon(
|
||
|
std::unique_ptr<MemoryDumpProvider> mdp);
|
||
|
|
||
|
// Prepare MemoryDumpManager for CreateProcessDump() calls for tracing-related
|
||
|
// modes (i.e. |level_of_detail| != SUMMARY_ONLY).
|
||
|
// Also initializes the peak detector, scheduler and heap profiler with the
|
||
|
// given config.
|
||
|
void SetupForTracing(const TraceConfig::MemoryDumpConfig&);
|
||
|
|
||
|
// Tear-down tracing related state.
|
||
|
// Non-tracing modes (e.g. SUMMARY_ONLY) will continue to work.
|
||
|
void TeardownForTracing();
|
||
|
|
||
|
// Creates a memory dump for the current process and appends it to the trace.
|
||
|
// |callback| will be invoked asynchronously upon completion on the same
|
||
|
// thread on which CreateProcessDump() was called. This method should only be
|
||
|
// used by the memory-infra service while creating a global memory dump.
|
||
|
void CreateProcessDump(const MemoryDumpRequestArgs& args,
|
||
|
const ProcessMemoryDumpCallback& callback);
|
||
|
|
||
|
// Returns the heap profiling mode configured on the command-line, if any.
|
||
|
// If heap profiling is configured but not supported by this binary, or if an
|
||
|
// invalid mode is specified, then kHeapProfilingInvalid is returned.
|
||
|
static HeapProfilingMode GetHeapProfilingModeFromCommandLine();
|
||
|
|
||
|
// Enable heap profiling if supported, and kEnableHeapProfiling command line
|
||
|
// is specified.
|
||
|
void EnableHeapProfilingIfNeeded();
|
||
|
|
||
|
// Enable heap profiling with specified |profiling_mode|.
|
||
|
// Use kHeapProfilingModeDisabled to disable, but it can't be re-enabled then.
|
||
|
// Returns true if mode has been *changed* to the desired |profiling_mode|.
|
||
|
bool EnableHeapProfiling(HeapProfilingMode profiling_mode);
|
||
|
HeapProfilingMode GetHeapProfilingMode();
|
||
|
|
||
|
// Lets tests see if a dump provider is registered.
|
||
|
bool IsDumpProviderRegisteredForTesting(MemoryDumpProvider*);
|
||
|
|
||
|
const scoped_refptr<HeapProfilerSerializationState>&
|
||
|
heap_profiler_serialization_state_for_testing() const {
|
||
|
return heap_profiler_serialization_state_;
|
||
|
}
|
||
|
|
||
|
// Returns a unique id for identifying the processes. The id can be
|
||
|
// retrieved by child processes only when tracing is enabled. This is
|
||
|
// intended to express cross-process sharing of memory dumps on the
|
||
|
// child-process side, without having to know its own child process id.
|
||
|
uint64_t GetTracingProcessId() const { return tracing_process_id_; }
|
||
|
void set_tracing_process_id(uint64_t tracing_process_id) {
|
||
|
tracing_process_id_ = tracing_process_id;
|
||
|
}
|
||
|
|
||
|
// Returns the name for a the allocated_objects dump. Use this to declare
|
||
|
// suballocator dumps from other dump providers.
|
||
|
// It will return nullptr if there is no dump provider for the system
|
||
|
// allocator registered (which is currently the case for Mac OS).
|
||
|
const char* system_allocator_pool_name() const {
|
||
|
return kSystemAllocatorPoolName;
|
||
|
};
|
||
|
|
||
|
// When set to true, calling |RegisterMemoryDumpProvider| is a no-op.
|
||
|
void set_dumper_registrations_ignored_for_testing(bool ignored) {
|
||
|
dumper_registrations_ignored_for_testing_ = ignored;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
friend std::default_delete<MemoryDumpManager>; // For the testing instance.
|
||
|
friend struct DefaultSingletonTraits<MemoryDumpManager>;
|
||
|
friend class MemoryDumpManagerTest;
|
||
|
|
||
|
// Holds the state of a process memory dump that needs to be carried over
|
||
|
// across task runners in order to fulfill an asynchronous CreateProcessDump()
|
||
|
// request. At any time exactly one task runner owns a
|
||
|
// ProcessMemoryDumpAsyncState.
|
||
|
struct ProcessMemoryDumpAsyncState {
|
||
|
ProcessMemoryDumpAsyncState(
|
||
|
MemoryDumpRequestArgs req_args,
|
||
|
const MemoryDumpProviderInfo::OrderedSet& dump_providers,
|
||
|
scoped_refptr<HeapProfilerSerializationState>
|
||
|
heap_profiler_serialization_state,
|
||
|
ProcessMemoryDumpCallback callback,
|
||
|
scoped_refptr<SequencedTaskRunner> dump_thread_task_runner);
|
||
|
~ProcessMemoryDumpAsyncState();
|
||
|
|
||
|
// A ProcessMemoryDump to collect data from MemoryDumpProviders.
|
||
|
std::unique_ptr<ProcessMemoryDump> process_memory_dump;
|
||
|
|
||
|
// The arguments passed to the initial CreateProcessDump() request.
|
||
|
const MemoryDumpRequestArgs req_args;
|
||
|
|
||
|
// An ordered sequence of dump providers that have to be invoked to complete
|
||
|
// the dump. This is a copy of |dump_providers_| at the beginning of a dump
|
||
|
// and becomes empty at the end, when all dump providers have been invoked.
|
||
|
std::vector<scoped_refptr<MemoryDumpProviderInfo>> pending_dump_providers;
|
||
|
|
||
|
// The HeapProfilerSerializationState object, which is shared by all
|
||
|
// the ProcessMemoryDump and MemoryAllocatorDump instances through all the
|
||
|
// tracing session lifetime.
|
||
|
scoped_refptr<HeapProfilerSerializationState>
|
||
|
heap_profiler_serialization_state;
|
||
|
|
||
|
// Callback passed to the initial call to CreateProcessDump().
|
||
|
ProcessMemoryDumpCallback callback;
|
||
|
|
||
|
// The thread on which FinishAsyncProcessDump() (and hence |callback|)
|
||
|
// should be invoked. This is the thread on which the initial
|
||
|
// CreateProcessDump() request was called.
|
||
|
const scoped_refptr<SingleThreadTaskRunner> callback_task_runner;
|
||
|
|
||
|
// The thread on which unbound dump providers should be invoked.
|
||
|
// This is essentially |dump_thread_|.task_runner() but needs to be kept
|
||
|
// as a separate variable as it needs to be accessed by arbitrary dumpers'
|
||
|
// threads outside of the lock_ to avoid races when disabling tracing.
|
||
|
// It is immutable for all the duration of a tracing session.
|
||
|
const scoped_refptr<SequencedTaskRunner> dump_thread_task_runner;
|
||
|
|
||
|
private:
|
||
|
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState);
|
||
|
};
|
||
|
|
||
|
static const int kMaxConsecutiveFailuresCount;
|
||
|
static const char* const kSystemAllocatorPoolName;
|
||
|
|
||
|
MemoryDumpManager();
|
||
|
virtual ~MemoryDumpManager();
|
||
|
|
||
|
static void SetInstanceForTesting(MemoryDumpManager* instance);
|
||
|
static uint32_t GetDumpsSumKb(const std::string&, const ProcessMemoryDump*);
|
||
|
|
||
|
void FinishAsyncProcessDump(
|
||
|
std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state);
|
||
|
|
||
|
// Lazily initializes dump_thread_ and returns its TaskRunner.
|
||
|
scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked();
|
||
|
|
||
|
// Calls InvokeOnMemoryDump() for the next MDP on the task runner specified by
|
||
|
// the MDP while registration. On failure to do so, skips and continues to
|
||
|
// next MDP.
|
||
|
void SetupNextMemoryDump(
|
||
|
std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state);
|
||
|
|
||
|
// Invokes OnMemoryDump() of the next MDP and calls SetupNextMemoryDump() at
|
||
|
// the end to continue the ProcessMemoryDump. Should be called on the MDP task
|
||
|
// runner.
|
||
|
void InvokeOnMemoryDump(ProcessMemoryDumpAsyncState* owned_pmd_async_state);
|
||
|
|
||
|
// Helper for RegierDumpProvider* functions.
|
||
|
void RegisterDumpProviderInternal(
|
||
|
MemoryDumpProvider* mdp,
|
||
|
const char* name,
|
||
|
scoped_refptr<SequencedTaskRunner> task_runner,
|
||
|
const MemoryDumpProvider::Options& options);
|
||
|
|
||
|
// Helper for the public UnregisterDumpProvider* functions.
|
||
|
void UnregisterDumpProviderInternal(MemoryDumpProvider* mdp,
|
||
|
bool take_mdp_ownership_and_delete_async);
|
||
|
|
||
|
// Fills the passed vector with the subset of dump providers which were
|
||
|
// registered with is_fast_polling_supported == true.
|
||
|
void GetDumpProvidersForPolling(
|
||
|
std::vector<scoped_refptr<MemoryDumpProviderInfo>>*);
|
||
|
|
||
|
// Initialize |heap_profiler_serialization_state_| when tracing and heap
|
||
|
// profiler are enabled.
|
||
|
void InitializeHeapProfilerStateIfNeededLocked();
|
||
|
|
||
|
// Sends OnHeapProfilingEnabled() notifcation to mdp ensuring OnMemoryDump()
|
||
|
// is not called at the same time.
|
||
|
void NotifyHeapProfilingEnabledLocked(
|
||
|
scoped_refptr<MemoryDumpProviderInfo> mdpinfo,
|
||
|
bool enabled);
|
||
|
|
||
|
bool can_request_global_dumps() const {
|
||
|
return !request_dump_function_.is_null();
|
||
|
}
|
||
|
|
||
|
// An ordered set of registered MemoryDumpProviderInfo(s), sorted by task
|
||
|
// runner affinity (MDPs belonging to the same task runners are adjacent).
|
||
|
MemoryDumpProviderInfo::OrderedSet dump_providers_;
|
||
|
|
||
|
// Shared among all the PMDs to keep state scoped to the tracing session.
|
||
|
scoped_refptr<HeapProfilerSerializationState>
|
||
|
heap_profiler_serialization_state_;
|
||
|
|
||
|
// Function provided by the embedder to handle global dump requests.
|
||
|
RequestGlobalDumpFunction request_dump_function_;
|
||
|
|
||
|
// True when current process coordinates the periodic dump triggering.
|
||
|
bool is_coordinator_;
|
||
|
|
||
|
// Protects from concurrent accesses to the local state, eg: to guard against
|
||
|
// disabling logging while dumping on another thread.
|
||
|
Lock lock_;
|
||
|
|
||
|
// Thread used for MemoryDumpProviders which don't specify a task runner
|
||
|
// affinity.
|
||
|
std::unique_ptr<Thread> dump_thread_;
|
||
|
|
||
|
// The unique id of the child process. This is created only for tracing and is
|
||
|
// expected to be valid only when tracing is enabled.
|
||
|
uint64_t tracing_process_id_;
|
||
|
|
||
|
// When true, calling |RegisterMemoryDumpProvider| is a no-op.
|
||
|
bool dumper_registrations_ignored_for_testing_;
|
||
|
|
||
|
HeapProfilingMode heap_profiling_mode_;
|
||
|
|
||
|
DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
|
||
|
};
|
||
|
|
||
|
} // namespace trace_event
|
||
|
} // namespace base
|
||
|
|
||
|
#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
|