1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef __mozilla_ProcInfo_h
7 #define __mozilla_ProcInfo_h
9 #include <base/process.h>
11 #include "mozilla/dom/BindingDeclarations.h"
12 #include "mozilla/dom/ChromeUtilsBinding.h"
13 #include "mozilla/dom/ipc/IdType.h"
14 #include "mozilla/HashTable.h"
15 #include "mozilla/MozPromise.h"
20 class GeckoChildProcessHost
;
24 * Return the number of milliseconds of CPU time used since process start.
26 * @return NS_OK on success.
28 nsresult
GetCpuTimeSinceProcessStartInMs(uint64_t* aResult
);
31 * Return the number of milliseconds of GPU time used since process start.
33 * @return NS_OK on success.
35 nsresult
GetGpuTimeSinceProcessStartInMs(uint64_t* aResult
);
37 // Process types. When updating this enum, please make sure to update
38 // WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
39 // mirror the changes.
41 // These must match the ones in RemoteType.h, and E10SUtils.sys.mjs
51 // the rest matches GeckoProcessTypes.h
52 #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
53 process_bin_type, procinfo_typename, \
54 webidl_typename, allcaps_name) \
56 #define SKIP_PROCESS_TYPE_CONTENT
57 #ifndef MOZ_ENABLE_FORKSERVER
58 # define SKIP_PROCESS_TYPE_FORKSERVER
59 #endif // MOZ_ENABLE_FORKSERVER
60 #include "mozilla/GeckoProcessTypes.h"
61 #undef SKIP_PROCESS_TYPE_CONTENT
62 #ifndef MOZ_ENABLE_FORKSERVER
63 # undef SKIP_PROCESS_TYPE_FORKSERVER
64 #endif // MOZ_ENABLE_FORKSERVER
65 #undef GECKO_PROCESS_TYPE
67 // Unknown type of process
72 using UtilityActorName
= mozilla::dom::WebIDLUtilityActorName
;
74 // String that will be used e.g. to annotate crash reports
75 nsCString
GetUtilityActorName(const UtilityActorName aActorName
);
78 int GetCpuFrequencyMHz();
81 /* Get the CPU frequency to use to convert cycle time values to actual time.
82 * @returns the TSC (Time Stamp Counter) frequency in MHz, or 0 if converting
83 * cycle time values should not be attempted. */
84 int GetCycleTimeFrequencyMHz();
88 base::ProcessId tid
= 0;
89 // Thread name, if any.
93 // CPU time in cycles if available.
94 uint64_t cpuCycleCount
= 0;
97 // Info on a DOM window.
101 documentURI(nullptr),
102 documentTitle(u
""_ns
),
103 isProcessRoot(false),
104 isInProcess(false) {}
105 WindowInfo(uint64_t aOuterWindowId
, nsIURI
* aDocumentURI
,
106 nsAString
&& aDocumentTitle
, bool aIsProcessRoot
, bool aIsInProcess
)
107 : outerWindowId(aOuterWindowId
),
108 documentURI(aDocumentURI
),
109 documentTitle(std::move(aDocumentTitle
)),
110 isProcessRoot(aIsProcessRoot
),
111 isInProcess(aIsInProcess
) {}
113 // Internal window id.
114 const uint64_t outerWindowId
;
116 // URI of the document.
117 const nsCOMPtr
<nsIURI
> documentURI
;
119 // Title of the document.
120 const nsString documentTitle
;
122 // True if this is the toplevel window of the process.
123 // Note that this may be an iframe from another process.
124 const bool isProcessRoot
;
126 const bool isInProcess
;
129 // Info on a Utility process actor
131 explicit UtilityInfo() : actorName(UtilityActorName::Unknown
) {}
132 explicit UtilityInfo(UtilityActorName aActorName
) : actorName(aActorName
) {}
133 const UtilityActorName actorName
;
138 base::ProcessId pid
= 0;
139 // Child Id as defined by Firefox when a child process is created.
140 dom::ContentParentId childId
;
145 // Memory size in bytes.
148 uint64_t cpuTime
= 0;
149 uint64_t cpuCycleCount
= 0;
150 // Threads owned by this process.
151 CopyableTArray
<ThreadInfo
> threads
;
152 // DOM windows represented by this process.
153 CopyableTArray
<WindowInfo
> windows
;
154 // Utility process actors, empty for non Utility process
155 CopyableTArray
<UtilityInfo
> utilityActors
;
158 typedef MozPromise
<mozilla::HashMap
<base::ProcessId
, ProcInfo
>, nsresult
, true>
162 * Data we need to request process info (e.g. CPU usage, memory usage)
163 * from the operating system and populate the resulting `ProcInfo`.
165 * Note that this structure contains a mix of:
166 * - low-level handles that we need to request low-level process info
167 * (`aChildTask` on macOS, `aPid` on other platforms); and
168 * - high-level data that we already acquired while looking for
169 * `aPid`/`aChildTask` and that we will need further down the road.
171 struct ProcInfoRequest
{
172 ProcInfoRequest(base::ProcessId aPid
, ProcType aProcessType
,
173 const nsACString
& aOrigin
, nsTArray
<WindowInfo
>&& aWindowInfo
,
174 nsTArray
<UtilityInfo
>&& aUtilityInfo
, uint32_t aChildId
= 0
177 mach_port_t aChildTask
= 0
181 processType(aProcessType
),
183 windowInfo(std::move(aWindowInfo
)),
184 utilityInfo(std::move(aUtilityInfo
)),
188 childTask(aChildTask
)
192 const base::ProcessId pid
;
193 const ProcType processType
;
194 const nsCString origin
;
195 const nsTArray
<WindowInfo
> windowInfo
;
196 const nsTArray
<UtilityInfo
> utilityInfo
;
197 // If the process is a child, its child id, otherwise `0`.
198 const int32_t childId
;
200 const mach_port_t childTask
;
205 * Batch a request for low-level information on Gecko processes.
209 * Argument `aRequests` is a list of processes, along with high-level data
210 * we have already obtained on them and that we need to populate the
211 * resulting array of `ProcInfo`.
215 * This call succeeds (possibly with missing data, see below) unless we
216 * cannot allocate memory.
220 * - This call is always executed on a background thread.
221 * - This call does NOT wake up children processes.
222 * - This function is sometimes observably slow to resolve, in particular
225 * # Error-handling and race conditions
227 * Requesting low-level information on a process and its threads is inherently
228 * subject to race conditions. Typically, if a process or a thread is killed
229 * while we're preparing to fetch information, we can easily end up with
230 * system/lib calls that return failures.
232 * For this reason, this API assumes that errors when placing a system/lib call
233 * are likely and normal. When some information cannot be obtained, the API will
234 * simply skip over said information.
236 * Note that due to different choices by OSes, the exact information we skip may
237 * vary across platforms. For instance, under Unix, failing to access the
238 * threads of a process will cause us to skip all data on the process, while
239 * under Windows, process information will be returned without thread
242 RefPtr
<ProcInfoPromise
> GetProcInfo(nsTArray
<ProcInfoRequest
>&& aRequests
);
245 * Synchronous version of GetProcInfo.
247 ProcInfoPromise::ResolveOrRejectValue
GetProcInfoSync(
248 nsTArray
<ProcInfoRequest
>&& aRequests
);
251 * Utility function: copy data from a `ProcInfo` and into either a
252 * `ParentProcInfoDictionary` or a `ChildProcInfoDictionary`.
254 template <typename T
>
255 nsresult
CopySysProcInfoToDOM(const ProcInfo
& source
, T
* dest
) {
257 dest
->mPid
= source
.pid
;
258 dest
->mMemory
= source
.memory
;
259 dest
->mCpuTime
= source
.cpuTime
;
260 dest
->mCpuCycleCount
= source
.cpuCycleCount
;
263 mozilla::dom::Sequence
<mozilla::dom::ThreadInfoDictionary
> threads
;
264 for (const ThreadInfo
& entry
: source
.threads
) {
265 mozilla::dom::ThreadInfoDictionary
* thread
=
266 threads
.AppendElement(fallible
);
267 if (NS_WARN_IF(!thread
)) {
268 return NS_ERROR_OUT_OF_MEMORY
;
270 thread
->mCpuTime
= entry
.cpuTime
;
271 thread
->mCpuCycleCount
= entry
.cpuCycleCount
;
272 thread
->mTid
= entry
.tid
;
273 thread
->mName
.Assign(entry
.name
);
275 dest
->mThreads
= std::move(threads
);
279 } // namespace mozilla