1 // Copyright 2013 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 #include "base/process/process_metrics.h"
6
7 #include <limits.h>
8 #include <mach/task.h>
9 #include <mach/vm_region.h>
10 #include <malloc/malloc.h>
11 #include <stddef.h>
12
13 #include "base/check_op.h"
14 #include "base/mac/scoped_mach_port.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/notreached.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "build/blink_buildflags.h"
19
20 namespace base {
21
ProcessMetrics(ProcessHandle process)22 ProcessMetrics::ProcessMetrics(ProcessHandle process) {}
23
24 // static
CreateProcessMetrics(ProcessHandle process)25 std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
26 ProcessHandle process) {
27 return WrapUnique(new ProcessMetrics(process));
28 }
29
GetCumulativeCPUUsage()30 TimeDelta ProcessMetrics::GetCumulativeCPUUsage() {
31 NOTIMPLEMENTED();
32 return TimeDelta();
33 }
34
35 // The blink code path pulls in process_metrics_posix.cc which
36 // is used for the following implementations.
37 #if !BUILDFLAG(USE_BLINK)
38
GetMaxFds()39 size_t GetMaxFds() {
40 static const rlim_t kSystemDefaultMaxFds = 256;
41 rlim_t max_fds;
42 struct rlimit nofile;
43 if (getrlimit(RLIMIT_NOFILE, &nofile)) {
44 // Error case: Take a best guess.
45 max_fds = kSystemDefaultMaxFds;
46 } else {
47 max_fds = nofile.rlim_cur;
48 }
49
50 if (max_fds > INT_MAX)
51 max_fds = INT_MAX;
52
53 return static_cast<size_t>(max_fds);
54 }
55
IncreaseFdLimitTo(unsigned int max_descriptors)56 void IncreaseFdLimitTo(unsigned int max_descriptors) {
57 // Unimplemented.
58 }
59
GetMallocUsage()60 size_t ProcessMetrics::GetMallocUsage() {
61 malloc_statistics_t stats;
62 malloc_zone_statistics(nullptr, &stats);
63 return stats.size_in_use;
64 }
65 #endif // !BUILDFLAG(USE_BLINK)
66
67 // Bytes committed by the system.
GetSystemCommitCharge()68 size_t GetSystemCommitCharge() {
69 NOTIMPLEMENTED();
70 return 0;
71 }
72
GetSystemMemoryInfo(SystemMemoryInfoKB * meminfo)73 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
74 struct host_basic_info hostinfo;
75 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
76 base::mac::ScopedMachSendRight host(mach_host_self());
77 int result = host_info(host.get(), HOST_BASIC_INFO,
78 reinterpret_cast<host_info_t>(&hostinfo), &count);
79 if (result != KERN_SUCCESS)
80 return false;
81
82 DCHECK_EQ(HOST_BASIC_INFO_COUNT, count);
83 meminfo->total = static_cast<int>(hostinfo.max_mem / 1024);
84
85 vm_statistics64_data_t vm_info;
86 count = HOST_VM_INFO64_COUNT;
87
88 if (host_statistics64(host.get(), HOST_VM_INFO64,
89 reinterpret_cast<host_info64_t>(&vm_info),
90 &count) != KERN_SUCCESS) {
91 return false;
92 }
93 DCHECK_EQ(HOST_VM_INFO64_COUNT, count);
94
95 // Check that PAGE_SIZE is divisible by 1024 (2^10).
96 CHECK_EQ(PAGE_SIZE, (PAGE_SIZE >> 10) << 10);
97 meminfo->free = saturated_cast<int>(
98 PAGE_SIZE / 1024 * (vm_info.free_count - vm_info.speculative_count));
99 meminfo->speculative =
100 saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.speculative_count);
101 meminfo->file_backed =
102 saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.external_page_count);
103 meminfo->purgeable =
104 saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.purgeable_count);
105
106 return true;
107 }
108
ParseOutputFromVMRegion(kern_return_t kr)109 MachVMRegionResult ParseOutputFromVMRegion(kern_return_t kr) {
110 if (kr == KERN_INVALID_ADDRESS) {
111 // We're at the end of the address space.
112 return MachVMRegionResult::Finished;
113 } else if (kr != KERN_SUCCESS) {
114 return MachVMRegionResult::Error;
115 }
116 return MachVMRegionResult::Success;
117 }
118
GetBasicInfo(mach_port_t task,mach_vm_size_t * size,mach_vm_address_t * address,vm_region_basic_info_64 * info)119 MachVMRegionResult GetBasicInfo(mach_port_t task,
120 mach_vm_size_t* size,
121 mach_vm_address_t* address,
122 vm_region_basic_info_64* info) {
123 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
124 mac::ScopedMachSendRight object_name;
125 kern_return_t kr =
126 vm_region_64(task, reinterpret_cast<vm_address_t*>(address),
127 reinterpret_cast<vm_size_t*>(size), VM_REGION_BASIC_INFO_64,
128 reinterpret_cast<vm_region_info_t>(info), &info_count,
129 mac::ScopedMachSendRight::Receiver(object_name).get());
130 return ParseOutputFromVMRegion(kr);
131 }
132
133 } // namespace base
134