| // 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(MemoryDumpType, MemoryDumpLevelOfDetail)>; | 
 |  | 
 |   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); | 
 |  | 
 |   // 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; | 
 |   FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest, | 
 |                            NoStackOverflowWithTooManyMDPs); | 
 |  | 
 |   // 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); | 
 |  | 
 |   // Lazily initializes dump_thread_ and returns its TaskRunner. | 
 |   scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked(); | 
 |  | 
 |   // Calls InvokeOnMemoryDump() for the each MDP that belongs to the current | 
 |   // task runner and switches to the task runner of the next MDP. Handles | 
 |   // failures in MDP and thread hops, and always calls FinishAsyncProcessDump() | 
 |   // at the end. | 
 |   void ContinueAsyncProcessDump( | 
 |       ProcessMemoryDumpAsyncState* owned_pmd_async_state); | 
 |  | 
 |   // Invokes OnMemoryDump() of the given MDP. Should be called on the MDP task | 
 |   // runner. | 
 |   void InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo, | 
 |                           ProcessMemoryDump* pmd); | 
 |  | 
 |   void FinishAsyncProcessDump( | 
 |       std::unique_ptr<ProcessMemoryDumpAsyncState> 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_ |