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/. */
7 #include "mozilla/ProcInfo.h"
8 #include "mozilla/Sprintf.h"
9 #include "mozilla/Logging.h"
10 #include "mozilla/ScopeExit.h"
11 #include "mozilla/ipc/GeckoChildProcessHost.h"
12 #include "nsMemoryReporterManager.h"
13 #include "nsWhitespaceTokenizer.h"
20 #include <sys/types.h>
25 // Maximal length on /proc filename
26 // "/proc/999999/lwp/999999/lwpsinfo"
27 // "/proc/999999/psinfo"
28 #define FNMAX_PROCFS "/proc/999999/lwp/999999/lwpsinfo"
32 int GetCycleTimeFrequencyMHz() { return 0; }
34 nsresult
GetCpuTimeSinceProcessStartInMs(uint64_t* aResult
) {
36 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &t
) == 0) {
38 uint64_t(t
.tv_sec
) * 1'000'000'000u + uint64_t(t
.tv_nsec
);
39 *aResult
= cpuTime
/ PR_NSEC_PER_MSEC
;
43 return NS_ERROR_FAILURE
;
46 nsresult
GetGpuTimeSinceProcessStartInMs(uint64_t* aResult
) {
47 return NS_ERROR_NOT_IMPLEMENTED
;
50 ProcInfoPromise::ResolveOrRejectValue
GetProcInfoSync(
51 nsTArray
<ProcInfoRequest
>&& aRequests
) {
52 ProcInfoPromise::ResolveOrRejectValue result
;
54 HashMap
<base::ProcessId
, ProcInfo
> gathered
;
55 if (!gathered
.reserve(aRequests
.Length())) {
56 result
.SetReject(NS_ERROR_OUT_OF_MEMORY
);
59 for (const auto& request
: aRequests
) {
63 char filename
[sizeof(FNMAX_PROCFS
)];
65 snprintf(filename
, sizeof(FNMAX_PROCFS
), "/proc/%d/psinfo", request
.pid
);
66 if ((fd
= open(filename
, O_RDONLY
)) == -1) {
67 result
.SetReject(NS_ERROR_FAILURE
);
70 if (read(fd
, &psinfo
, sizeof(psinfo_t
)) != sizeof(psinfo_t
)) {
72 result
.SetReject(NS_ERROR_FAILURE
);
77 psinfo
.pr_time
.tv_sec
* 1'000'000'000u + psinfo
.pr_time
.tv_nsec
;
78 info
.memory
= psinfo
.pr_rssize
* 1024;
81 info
.pid
= request
.pid
;
82 info
.childId
= request
.childId
;
83 info
.type
= request
.processType
;
84 info
.origin
= request
.origin
;
85 info
.windows
= std::move(request
.windowInfo
);
86 info
.utilityActors
= std::move(request
.utilityInfo
);
88 // Let's look at the threads
89 for (int lwp
= 1, lwp_max
= psinfo
.pr_nlwp
; lwp
<= lwp_max
; lwp
++) {
91 snprintf(filename
, sizeof(FNMAX_PROCFS
), "/proc/%d/lwp/%d/lwpsinfo",
93 if ((fd
= open(filename
, O_RDONLY
)) == -1) {
94 // Some LWPs might no longer exist. That just means that there are
95 // probably others with bigger LWP id. But we need to limit the search
96 // because of possible race condition.
97 if (lwp_max
< 2 * psinfo
.pr_nlwp
) lwp_max
++;
100 if (read(fd
, &lwpsinfo
, sizeof(lwpsinfo_t
)) != sizeof(lwpsinfo_t
)) {
105 ThreadInfo threadInfo
;
106 threadInfo
.tid
= lwpsinfo
.pr_lwpid
;
108 lwpsinfo
.pr_time
.tv_sec
* 1'000'000'000u + lwpsinfo
.pr_time
.tv_nsec
;
109 threadInfo
.name
.AssignASCII(lwpsinfo
.pr_name
, strlen(lwpsinfo
.pr_name
));
110 info
.threads
.AppendElement(threadInfo
);
113 if (!gathered
.put(request
.pid
, std::move(info
))) {
114 result
.SetReject(NS_ERROR_OUT_OF_MEMORY
);
119 // ... and we're done!
120 result
.SetResolve(std::move(gathered
));
124 } // namespace mozilla