• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
6 #define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <unordered_set>
13 #include <vector>
14 
15 #include "base/base_export.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/memory/singleton.h"
18 #include "base/synchronization/lock.h"
19 #include "base/trace_event/memory_allocator_dump.h"
20 #include "base/trace_event/memory_dump_provider_info.h"
21 #include "base/trace_event/memory_dump_request_args.h"
22 #include "base/trace_event/process_memory_dump.h"
23 #include "base/trace_event/base_tracing.h"
24 
25 namespace base {
26 
27 class SequencedTaskRunner;
28 class SingleThreadTaskRunner;
29 class Thread;
30 
31 namespace trace_event {
32 
33 class MemoryDumpProvider;
34 
35 // This is the interface exposed to the rest of the codebase to deal with
36 // memory tracing. The main entry point for clients is represented by
37 // RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
38 class BASE_EXPORT MemoryDumpManager {
39  public:
40   using RequestGlobalDumpFunction =
41       RepeatingCallback<void(MemoryDumpType, MemoryDumpLevelOfDetail)>;
42 
43   static constexpr const char* const kTraceCategory =
44       TRACE_DISABLED_BY_DEFAULT("memory-infra");
45 
46   // This value is returned as the tracing id of the child processes by
47   // GetTracingProcessId() when tracing is not enabled.
48   static const uint64_t kInvalidTracingProcessId;
49 
50   static MemoryDumpManager* GetInstance();
51   static std::unique_ptr<MemoryDumpManager> CreateInstanceForTesting();
52 
53   MemoryDumpManager(const MemoryDumpManager&) = delete;
54   MemoryDumpManager& operator=(const MemoryDumpManager&) = delete;
55 
56   // Invoked once per process to listen to trace begin / end events.
57   // Initialization can happen after (Un)RegisterMemoryDumpProvider() calls
58   // and the MemoryDumpManager guarantees to support this.
59   // On the other side, the MemoryDumpManager will not be fully operational
60   // (any CreateProcessDump() will return a failure) until initialized.
61   // Arguments:
62   //  is_coordinator: True when current process coordinates the periodic dump
63   //      triggering.
64   //  request_dump_function: Function to invoke a global dump. Global dump
65   //      involves embedder-specific behaviors like multiprocess handshaking.
66   //      TODO(primiano): this is only required to trigger global dumps from
67   //      the scheduler. Should be removed once they are both moved out of base.
68   void Initialize(RequestGlobalDumpFunction request_dump_function,
69                   bool is_coordinator);
70 
71   // (Un)Registers a MemoryDumpProvider instance.
72   // Args:
73   //  - mdp: the MemoryDumpProvider instance to be registered. MemoryDumpManager
74   //      does NOT take memory ownership of |mdp|, which is expected to either
75   //      be a singleton or unregister itself.
76   //  - name: a friendly name (duplicates allowed). Used for debugging and
77   //      run-time profiling of memory-infra internals. Must be a long-lived
78   //      C string.
79   //  - task_runner: either a SingleThreadTaskRunner or SequencedTaskRunner. All
80   //      the calls to |mdp| will be run on the given |task_runner|. If passed
81   //      null |mdp| should be able to handle calls on arbitrary threads.
82   //  - options: extra optional arguments. See memory_dump_provider.h.
83   void RegisterDumpProvider(MemoryDumpProvider* mdp,
84                             const char* name,
85                             scoped_refptr<SingleThreadTaskRunner> task_runner);
86   void RegisterDumpProvider(MemoryDumpProvider* mdp,
87                             const char* name,
88                             scoped_refptr<SingleThreadTaskRunner> task_runner,
89                             MemoryDumpProvider::Options options);
90   void RegisterDumpProviderWithSequencedTaskRunner(
91       MemoryDumpProvider* mdp,
92       const char* name,
93       scoped_refptr<SequencedTaskRunner> task_runner,
94       MemoryDumpProvider::Options options);
95   void UnregisterDumpProvider(MemoryDumpProvider* mdp);
96 
97   // Unregisters an unbound dump provider and takes care about its deletion
98   // asynchronously. Can be used only for for dump providers with no
99   // task-runner affinity.
100   // This method takes ownership of the dump provider and guarantees that:
101   //  - The |mdp| will be deleted at some point in the near future.
102   //  - Its deletion will not happen concurrently with the OnMemoryDump() call.
103   // Note that OnMemoryDump() calls can still happen after this method returns.
104   void UnregisterAndDeleteDumpProviderSoon(
105       std::unique_ptr<MemoryDumpProvider> mdp);
106 
107   // Prepare MemoryDumpManager for CreateProcessDump() calls for tracing-related
108   // modes (i.e. |level_of_detail| != SUMMARY_ONLY).
109   // Also initializes the scheduler with the given config.
110   void SetupForTracing(const TraceConfig::MemoryDumpConfig&);
111 
112   // Tear-down tracing related state.
113   // Non-tracing modes (e.g. SUMMARY_ONLY) will continue to work.
114   void TeardownForTracing();
115 
116   // Creates a memory dump for the current process and appends it to the trace.
117   // |callback| will be invoked asynchronously upon completion on the same
118   // thread on which CreateProcessDump() was called. This method should only be
119   // used by the memory-infra service while creating a global memory dump.
120   void CreateProcessDump(const MemoryDumpRequestArgs& args,
121                          ProcessMemoryDumpCallback callback);
122 
123   // Lets tests see if a dump provider is registered.
124   bool IsDumpProviderRegisteredForTesting(MemoryDumpProvider*);
125 
126   // Returns a unique id for identifying the processes. The id can be
127   // retrieved by child processes only when tracing is enabled. This is
128   // intended to express cross-process sharing of memory dumps on the
129   // child-process side, without having to know its own child process id.
GetTracingProcessId()130   uint64_t GetTracingProcessId() const { return tracing_process_id_; }
set_tracing_process_id(uint64_t tracing_process_id)131   void set_tracing_process_id(uint64_t tracing_process_id) {
132     tracing_process_id_ = tracing_process_id;
133   }
134 
135   // Returns the name for a the allocated_objects dump. Use this to declare
136   // suballocator dumps from other dump providers.
137   // It will return nullptr if there is no dump provider for the system
138   // allocator registered (which is currently the case for Mac OS).
system_allocator_pool_name()139   const char* system_allocator_pool_name() const {
140     return kSystemAllocatorPoolName;
141   }
142 
143   // When set to true, calling |RegisterMemoryDumpProvider| is a no-op.
set_dumper_registrations_ignored_for_testing(bool ignored)144   void set_dumper_registrations_ignored_for_testing(bool ignored) {
145     dumper_registrations_ignored_for_testing_ = ignored;
146   }
147 
148   scoped_refptr<SequencedTaskRunner> GetDumpThreadTaskRunner();
149 
150  private:
151   friend std::default_delete<MemoryDumpManager>;  // For the testing instance.
152   friend struct DefaultSingletonTraits<MemoryDumpManager>;
153   friend class MemoryDumpManagerTest;
154   FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest,
155                            NoStackOverflowWithTooManyMDPs);
156 
157   // Holds the state of a process memory dump that needs to be carried over
158   // across task runners in order to fulfill an asynchronous CreateProcessDump()
159   // request. At any time exactly one task runner owns a
160   // ProcessMemoryDumpAsyncState.
161   struct ProcessMemoryDumpAsyncState {
162     ProcessMemoryDumpAsyncState(
163         MemoryDumpRequestArgs req_args,
164         const MemoryDumpProviderInfo::OrderedSet& dump_providers,
165         ProcessMemoryDumpCallback callback,
166         scoped_refptr<SequencedTaskRunner> dump_thread_task_runner);
167     ProcessMemoryDumpAsyncState(const ProcessMemoryDumpAsyncState&) = delete;
168     ProcessMemoryDumpAsyncState& operator=(const ProcessMemoryDumpAsyncState&) =
169         delete;
170     ~ProcessMemoryDumpAsyncState();
171 
172     // A ProcessMemoryDump to collect data from MemoryDumpProviders.
173     std::unique_ptr<ProcessMemoryDump> process_memory_dump;
174 
175     // The arguments passed to the initial CreateProcessDump() request.
176     const MemoryDumpRequestArgs req_args;
177 
178     // An ordered sequence of dump providers that have to be invoked to complete
179     // the dump. This is a copy of |dump_providers_| at the beginning of a dump
180     // and becomes empty at the end, when all dump providers have been invoked.
181     std::vector<scoped_refptr<MemoryDumpProviderInfo>> pending_dump_providers;
182 
183     // Callback passed to the initial call to CreateProcessDump().
184     ProcessMemoryDumpCallback callback;
185 
186     // The thread on which FinishAsyncProcessDump() (and hence |callback|)
187     // should be invoked. This is the thread on which the initial
188     // CreateProcessDump() request was called.
189     const scoped_refptr<SingleThreadTaskRunner> callback_task_runner;
190 
191     // The thread on which unbound dump providers should be invoked.
192     // This is essentially |dump_thread_|.task_runner() but needs to be kept
193     // as a separate variable as it needs to be accessed by arbitrary dumpers'
194     // threads outside of the lock_ to avoid races when disabling tracing.
195     // It is immutable for all the duration of a tracing session.
196     const scoped_refptr<SequencedTaskRunner> dump_thread_task_runner;
197   };
198 
199   static const int kMaxConsecutiveFailuresCount;
200   static const char* const kSystemAllocatorPoolName;
201 
202   MemoryDumpManager();
203   virtual ~MemoryDumpManager();
204 
205   static void SetInstanceForTesting(MemoryDumpManager* instance);
206 
207   // Lazily initializes dump_thread_ and returns its TaskRunner.
208   scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked()
209       EXCLUSIVE_LOCKS_REQUIRED(lock_);
210 
211   // Calls InvokeOnMemoryDump() for the each MDP that belongs to the current
212   // task runner and switches to the task runner of the next MDP. Handles
213   // failures in MDP and thread hops, and always calls FinishAsyncProcessDump()
214   // at the end.
215   void ContinueAsyncProcessDump(
216       ProcessMemoryDumpAsyncState* owned_pmd_async_state);
217 
218   // Invokes OnMemoryDump() of the given MDP. Should be called on the MDP task
219   // runner.
220   void InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo,
221                           ProcessMemoryDump* pmd);
222 
223   void FinishAsyncProcessDump(
224       std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state);
225 
226   // Helper for RegierDumpProvider* functions.
227   void RegisterDumpProviderInternal(
228       MemoryDumpProvider* mdp,
229       const char* name,
230       scoped_refptr<SequencedTaskRunner> task_runner,
231       const MemoryDumpProvider::Options& options);
232 
233   // Helper for the public UnregisterDumpProvider* functions.
234   void UnregisterDumpProviderInternal(MemoryDumpProvider* mdp,
235                                       bool take_mdp_ownership_and_delete_async);
236 
237   bool can_request_global_dumps() const {
238     return !request_dump_function_.is_null();
239   }
240 
241   // An ordered set of registered MemoryDumpProviderInfo(s), sorted by task
242   // runner affinity (MDPs belonging to the same task runners are adjacent).
243   MemoryDumpProviderInfo::OrderedSet dump_providers_ GUARDED_BY(lock_);
244 
245   // Function provided by the embedder to handle global dump requests.
246   RequestGlobalDumpFunction request_dump_function_;
247 
248   // True when current process coordinates the periodic dump triggering.
249   bool is_coordinator_ GUARDED_BY(lock_) = false;
250 
251   // Protects from concurrent accesses to the local state, eg: to guard against
252   // disabling logging while dumping on another thread.
253   Lock lock_;
254 
255   // Thread used for MemoryDumpProviders which don't specify a task runner
256   // affinity.
257   std::unique_ptr<Thread> dump_thread_ GUARDED_BY(lock_);
258 
259   // The unique id of the child process. This is created only for tracing and is
260   // expected to be valid only when tracing is enabled.
261   uint64_t tracing_process_id_ = kInvalidTracingProcessId;
262 
263   // When true, calling |RegisterMemoryDumpProvider| is a no-op.
264   bool dumper_registrations_ignored_for_testing_ = false;
265 };
266 
267 }  // namespace trace_event
268 }  // namespace base
269 
270 #endif  // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
271