Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "MemoryReportRequest.h"
8 : #include "mozilla/Unused.h"
9 : #include "mozilla/dom/ContentChild.h"
10 : #include "mozilla/gfx/GPUParent.h"
11 :
12 : namespace mozilla {
13 : namespace dom {
14 :
15 0 : MemoryReportRequestHost::MemoryReportRequestHost(uint32_t aGeneration)
16 : : mGeneration(aGeneration),
17 0 : mSuccess(false)
18 : {
19 0 : MOZ_COUNT_CTOR(MemoryReportRequestHost);
20 0 : mReporterManager = nsMemoryReporterManager::GetOrCreate();
21 0 : NS_WARNING_ASSERTION(mReporterManager, "GetOrCreate failed");
22 0 : }
23 :
24 : void
25 0 : MemoryReportRequestHost::RecvReport(const MemoryReport& aReport)
26 : {
27 : // Skip reports from older generations. We need to do this here since we
28 : // could receive older reports from a subprocesses before it acknowledges
29 : // a new request, and we only track one active request per process.
30 0 : if (aReport.generation() != mGeneration) {
31 0 : return;
32 : }
33 :
34 0 : if (mReporterManager) {
35 0 : mReporterManager->HandleChildReport(mGeneration, aReport);
36 : }
37 : }
38 :
39 : void
40 0 : MemoryReportRequestHost::Finish(uint32_t aGeneration)
41 : {
42 : // Skip reports from older generations. See the comment in RecvReport.
43 0 : if (mGeneration != aGeneration) {
44 0 : return;
45 : }
46 0 : mSuccess = true;
47 : }
48 :
49 0 : MemoryReportRequestHost::~MemoryReportRequestHost()
50 : {
51 0 : MOZ_COUNT_DTOR(MemoryReportRequestHost);
52 :
53 0 : if (mReporterManager) {
54 0 : mReporterManager->EndProcessReport(mGeneration, mSuccess);
55 0 : mReporterManager = nullptr;
56 : }
57 0 : }
58 :
59 0 : NS_IMPL_ISUPPORTS(MemoryReportRequestClient, nsIRunnable)
60 :
61 : /* static */ void
62 0 : MemoryReportRequestClient::Start(uint32_t aGeneration,
63 : bool aAnonymize,
64 : bool aMinimizeMemoryUsage,
65 : const MaybeFileDesc& aDMDFile,
66 : const nsACString& aProcessString)
67 : {
68 : RefPtr<MemoryReportRequestClient> request = new MemoryReportRequestClient(
69 : aGeneration,
70 : aAnonymize,
71 : aDMDFile,
72 0 : aProcessString);
73 :
74 0 : DebugOnly<nsresult> rv;
75 0 : if (aMinimizeMemoryUsage) {
76 : nsCOMPtr<nsIMemoryReporterManager> mgr =
77 0 : do_GetService("@mozilla.org/memory-reporter-manager;1");
78 0 : rv = mgr->MinimizeMemoryUsage(request);
79 : // mgr will eventually call actor->Run()
80 : } else {
81 0 : rv = request->Run();
82 : }
83 :
84 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "actor operation failed");
85 0 : }
86 :
87 0 : MemoryReportRequestClient::MemoryReportRequestClient(uint32_t aGeneration,
88 : bool aAnonymize,
89 : const MaybeFileDesc& aDMDFile,
90 0 : const nsACString& aProcessString)
91 : : mGeneration(aGeneration),
92 : mAnonymize(aAnonymize),
93 0 : mProcessString(aProcessString)
94 : {
95 0 : if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
96 0 : mDMDFile = aDMDFile.get_FileDescriptor();
97 : }
98 0 : }
99 :
100 0 : MemoryReportRequestClient::~MemoryReportRequestClient()
101 : {
102 0 : }
103 :
104 : class HandleReportCallback final : public nsIHandleReportCallback
105 : {
106 : public:
107 : NS_DECL_ISUPPORTS
108 :
109 0 : explicit HandleReportCallback(uint32_t aGeneration,
110 : const nsACString& aProcess)
111 0 : : mGeneration(aGeneration)
112 0 : , mProcess(aProcess)
113 0 : { }
114 :
115 0 : NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
116 : int32_t aKind, int32_t aUnits, int64_t aAmount,
117 : const nsACString& aDescription,
118 : nsISupports* aUnused) override
119 : {
120 0 : MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
121 0 : aAmount, mGeneration, nsCString(aDescription));
122 0 : switch (XRE_GetProcessType()) {
123 : case GeckoProcessType_Content:
124 0 : ContentChild::GetSingleton()->SendAddMemoryReport(memreport);
125 0 : break;
126 : case GeckoProcessType_GPU:
127 0 : Unused << gfx::GPUParent::GetSingleton()->SendAddMemoryReport(memreport);
128 0 : break;
129 : default:
130 0 : MOZ_ASSERT_UNREACHABLE("Unhandled process type");
131 : }
132 0 : return NS_OK;
133 : }
134 : private:
135 0 : ~HandleReportCallback() = default;
136 :
137 : uint32_t mGeneration;
138 : const nsCString mProcess;
139 : };
140 :
141 0 : NS_IMPL_ISUPPORTS(
142 : HandleReportCallback
143 : , nsIHandleReportCallback
144 : )
145 :
146 : class FinishReportingCallback final : public nsIFinishReportingCallback
147 : {
148 : public:
149 : NS_DECL_ISUPPORTS
150 :
151 0 : explicit FinishReportingCallback(uint32_t aGeneration)
152 0 : : mGeneration(aGeneration)
153 : {
154 0 : }
155 :
156 0 : NS_IMETHOD Callback(nsISupports* aUnused) override
157 : {
158 0 : bool sent = false;
159 0 : switch (XRE_GetProcessType()) {
160 : case GeckoProcessType_Content:
161 0 : sent = ContentChild::GetSingleton()->SendFinishMemoryReport(mGeneration);
162 0 : break;
163 : case GeckoProcessType_GPU:
164 0 : sent = gfx::GPUParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
165 0 : break;
166 : default:
167 0 : MOZ_ASSERT_UNREACHABLE("Unhandled process type");
168 : }
169 0 : return sent ? NS_OK : NS_ERROR_FAILURE;
170 : }
171 :
172 : private:
173 : ~FinishReportingCallback() = default;
174 :
175 : uint32_t mGeneration;
176 : };
177 :
178 0 : NS_IMPL_ISUPPORTS(
179 : FinishReportingCallback
180 : , nsIFinishReportingCallback
181 : )
182 :
183 0 : NS_IMETHODIMP MemoryReportRequestClient::Run()
184 : {
185 : nsCOMPtr<nsIMemoryReporterManager> mgr =
186 0 : do_GetService("@mozilla.org/memory-reporter-manager;1");
187 :
188 : // Run the reporters. The callback will turn each measurement into a
189 : // MemoryReport.
190 : RefPtr<HandleReportCallback> handleReport =
191 0 : new HandleReportCallback(mGeneration, mProcessString);
192 : RefPtr<FinishReportingCallback> finishReporting =
193 0 : new FinishReportingCallback(mGeneration);
194 :
195 : nsresult rv =
196 0 : mgr->GetReportsForThisProcessExtended(handleReport, nullptr, mAnonymize,
197 : FileDescriptorToFILE(mDMDFile, "wb"),
198 0 : finishReporting, nullptr);
199 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
200 : "GetReportsForThisProcessExtended failed");
201 0 : return rv;
202 : }
203 :
204 : } // namespace dom
205 : } // namespace mozilla
|