• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 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/system/sys_info.h"
6
7#import <Foundation/Foundation.h>
8#include <mach/mach_host.h>
9#include <mach/mach_init.h>
10#include <stddef.h>
11#include <stdint.h>
12#include <sys/sysctl.h>
13#include <sys/types.h>
14
15#include <optional>
16#include <string_view>
17
18#include "base/apple/scoped_mach_port.h"
19#include "base/check_op.h"
20#include "base/debug/stack_trace.h"
21#include "base/feature_list.h"
22#include "base/mac/mac_util.h"
23#include "base/no_destructor.h"
24#include "base/notreached.h"
25#include "base/numerics/safe_conversions.h"
26#include "base/posix/sysctl.h"
27#include "base/process/process_metrics.h"
28#include "base/strings/string_number_conversions.h"
29#include "base/strings/string_util.h"
30#include "base/strings/stringprintf.h"
31#include "base/synchronization/lock.h"
32#include "base/system/sys_info_internal.h"
33
34namespace base {
35
36namespace {
37
38// Whether this process has CPU security mitigations enabled.
39bool g_is_cpu_security_mitigation_enabled = false;
40
41// Whether NumberOfProcessors() was called. Used to detect when the CPU security
42// mitigations state changes after a call to NumberOfProcessors().
43bool g_is_cpu_security_mitigation_enabled_read = false;
44
45}  // namespace
46
47namespace internal {
48
49std::optional<int> NumberOfPhysicalProcessors() {
50  return GetSysctlIntValue("hw.physicalcpu_max");
51}
52
53std::optional<int> NumberOfProcessorsWhenCpuSecurityMitigationEnabled() {
54  g_is_cpu_security_mitigation_enabled_read = true;
55
56  if (!g_is_cpu_security_mitigation_enabled ||
57      !FeatureList::IsEnabled(kNumberOfCoresWithCpuSecurityMitigation)) {
58    return std::nullopt;
59  }
60  return NumberOfPhysicalProcessors();
61}
62
63}  // namespace internal
64
65BASE_FEATURE(kNumberOfCoresWithCpuSecurityMitigation,
66             "NumberOfCoresWithCpuSecurityMitigation",
67             FEATURE_ENABLED_BY_DEFAULT);
68
69// static
70std::string SysInfo::OperatingSystemName() {
71  return "Mac OS X";
72}
73
74// static
75std::string SysInfo::OperatingSystemVersion() {
76  int32_t major, minor, bugfix;
77  OperatingSystemVersionNumbers(&major, &minor, &bugfix);
78  return base::StringPrintf("%d.%d.%d", major, minor, bugfix);
79}
80
81// static
82void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
83                                            int32_t* minor_version,
84                                            int32_t* bugfix_version) {
85  NSOperatingSystemVersion version =
86      NSProcessInfo.processInfo.operatingSystemVersion;
87  *major_version = saturated_cast<int32_t>(version.majorVersion);
88  *minor_version = saturated_cast<int32_t>(version.minorVersion);
89  *bugfix_version = saturated_cast<int32_t>(version.patchVersion);
90}
91
92// static
93std::string SysInfo::OperatingSystemArchitecture() {
94  switch (mac::GetCPUType()) {
95    case mac::CPUType::kIntel:
96      return "x86_64";
97    case mac::CPUType::kTranslatedIntel:
98    case mac::CPUType::kArm:
99      return "arm64";
100  }
101}
102
103// static
104uint64_t SysInfo::AmountOfPhysicalMemoryImpl() {
105  struct host_basic_info hostinfo;
106  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
107  base::apple::ScopedMachSendRight host(mach_host_self());
108  int result = host_info(host.get(), HOST_BASIC_INFO,
109                         reinterpret_cast<host_info_t>(&hostinfo), &count);
110  if (result != KERN_SUCCESS) {
111    NOTREACHED();
112  }
113  DCHECK_EQ(HOST_BASIC_INFO_COUNT, count);
114  return hostinfo.max_mem;
115}
116
117// static
118uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() {
119  SystemMemoryInfoKB info;
120  if (!GetSystemMemoryInfo(&info))
121    return 0;
122  // We should add inactive file-backed memory also but there is no such
123  // information from Mac OS unfortunately.
124  return checked_cast<uint64_t>(info.free + info.speculative) * 1024;
125}
126
127// static
128std::string SysInfo::CPUModelName() {
129  return StringSysctlByName("machdep.cpu.brand_string").value_or(std::string{});
130}
131
132// static
133std::string SysInfo::HardwareModelName() {
134  // Note that there is lots of code out there that uses "hw.model", but that is
135  // deprecated in favor of "hw.product" as used here. See the sysctl.h file for
136  // more info.
137  return StringSysctl({CTL_HW, HW_PRODUCT}).value_or(std::string{});
138}
139
140// static
141std::optional<SysInfo::HardwareModelNameSplit>
142SysInfo::SplitHardwareModelNameDoNotUse(std::string_view name) {
143  size_t number_loc = name.find_first_of("0123456789");
144  if (number_loc == std::string::npos) {
145    return std::nullopt;
146  }
147  size_t comma_loc = name.find(',', number_loc);
148  if (comma_loc == std::string::npos) {
149    return std::nullopt;
150  }
151
152  HardwareModelNameSplit split;
153  if (!StringToInt(name.substr(0u, comma_loc).substr(number_loc),
154                   &split.model) ||
155      !StringToInt(name.substr(comma_loc + 1), &split.variant)) {
156    return std::nullopt;
157  }
158  split.category = name.substr(0u, number_loc);
159  return split;
160}
161
162// static
163SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
164  HardwareInfo info;
165  info.manufacturer = "Apple Inc.";
166  info.model = HardwareModelName();
167  DCHECK(IsStringUTF8(info.manufacturer));
168  DCHECK(IsStringUTF8(info.model));
169  return info;
170}
171
172// static
173void SysInfo::SetCpuSecurityMitigationsEnabled() {
174  // Setting `g_is_cpu_security_mitigation_enabled_read` after it has been read
175  // is disallowed because it could indicate that some code got a number of
176  // processor computed without all the required state.
177  CHECK(!g_is_cpu_security_mitigation_enabled_read);
178
179  g_is_cpu_security_mitigation_enabled = true;
180}
181
182// static
183void SysInfo::ResetCpuSecurityMitigationsEnabledForTesting() {
184  g_is_cpu_security_mitigation_enabled_read = false;
185  g_is_cpu_security_mitigation_enabled = false;
186}
187
188}  // namespace base
189