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