2020-10-10 14:16:11 +02:00
|
|
|
# typed: false
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-06-23 14:11:05 +01:00
|
|
|
require "macho"
|
|
|
|
|
2016-04-25 18:00:01 +01:00
|
|
|
module Hardware
|
|
|
|
class CPU
|
|
|
|
class << self
|
2019-01-26 17:13:14 +00:00
|
|
|
undef type, family, universal_archs, features, sse4?
|
2016-04-25 18:00:01 +01:00
|
|
|
|
|
|
|
# These methods use info spewed out by sysctl.
|
|
|
|
# Look in <mach/machine.h> for decoding info.
|
|
|
|
def type
|
|
|
|
case sysctl_int("hw.cputype")
|
2020-06-22 21:56:39 -04:00
|
|
|
when MachO::Headers::CPU_TYPE_I386
|
2016-04-25 18:00:01 +01:00
|
|
|
:intel
|
2020-06-22 11:50:49 -07:00
|
|
|
when MachO::Headers::CPU_TYPE_ARM64
|
|
|
|
:arm
|
2016-04-25 18:00:01 +01:00
|
|
|
else
|
|
|
|
:dunno
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def family
|
2019-01-26 17:13:14 +00:00
|
|
|
case sysctl_int("hw.cpufamily")
|
|
|
|
when 0x73d67300 # Yonah: Core Solo/Duo
|
|
|
|
:core
|
|
|
|
when 0x426f69ef # Merom: Core 2 Duo
|
|
|
|
:core2
|
|
|
|
when 0x78ea4fbc # Penryn
|
|
|
|
:penryn
|
|
|
|
when 0x6b5a4cd2 # Nehalem
|
|
|
|
:nehalem
|
|
|
|
when 0x573B5EEC # Arrandale
|
|
|
|
:arrandale
|
|
|
|
when 0x5490B78C # Sandy Bridge
|
|
|
|
:sandybridge
|
|
|
|
when 0x1F65E835 # Ivy Bridge
|
|
|
|
:ivybridge
|
|
|
|
when 0x10B282DC # Haswell
|
|
|
|
:haswell
|
|
|
|
when 0x582ed09c # Broadwell
|
|
|
|
:broadwell
|
|
|
|
when 0x37fc219f # Skylake
|
|
|
|
:skylake
|
|
|
|
when 0x0f817246 # Kaby Lake
|
|
|
|
:kabylake
|
2020-04-18 20:04:48 +10:00
|
|
|
when 0x38435547 # Ice Lake
|
|
|
|
:icelake
|
2020-07-06 20:28:10 +02:00
|
|
|
when 0x07d34b9f # ARMv8.3-A (Vortex, Tempest)
|
|
|
|
:arm_vortex_tempest
|
2019-01-26 17:13:14 +00:00
|
|
|
else
|
|
|
|
:dunno
|
2016-04-25 18:00:01 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Returns an array that's been extended with {ArchitectureListExtension},
|
|
|
|
# which provides helpers like `#as_arch_flags`.
|
2016-04-25 18:00:01 +01:00
|
|
|
def universal_archs
|
2019-01-08 19:13:46 +00:00
|
|
|
# Amazingly, this order (64, then 32) matters. It shouldn't, but it
|
|
|
|
# does. GCC (some versions? some systems?) can blow up if the other
|
|
|
|
# order is used.
|
|
|
|
# https://superuser.com/questions/740563/gcc-4-8-on-macos-fails-depending-on-arch-order
|
|
|
|
[arch_64_bit, arch_32_bit].extend ArchitectureListExtension
|
2016-04-25 18:00:01 +01:00
|
|
|
end
|
|
|
|
|
2020-11-12 17:06:47 +00:00
|
|
|
# True when running under an Intel-based shell via Rosetta 2 on an
|
2020-07-13 11:00:14 -07:00
|
|
|
# Apple Silicon Mac. This can be detected via seeing if there's a
|
2020-11-05 17:17:03 -05:00
|
|
|
# conflict between what `uname` reports and the underlying `sysctl` flags,
|
2020-11-12 17:06:47 +00:00
|
|
|
# since the `sysctl` flags don't change behaviour under Rosetta 2.
|
|
|
|
def in_rosetta2?
|
2020-11-22 00:43:03 +01:00
|
|
|
sysctl_bool("sysctl.proc_translated")
|
2020-07-13 11:00:14 -07:00
|
|
|
end
|
|
|
|
|
2016-04-25 18:00:01 +01:00
|
|
|
def features
|
|
|
|
@features ||= sysctl_n(
|
|
|
|
"machdep.cpu.features",
|
|
|
|
"machdep.cpu.extfeatures",
|
2017-02-12 15:06:54 +00:00
|
|
|
"machdep.cpu.leaf7_features",
|
2016-04-25 18:00:01 +01:00
|
|
|
).split(" ").map { |s| s.downcase.to_sym }
|
|
|
|
end
|
|
|
|
|
2018-04-07 20:28:56 +01:00
|
|
|
def sse4?
|
|
|
|
sysctl_bool("hw.optional.sse4_1")
|
|
|
|
end
|
|
|
|
|
|
|
|
def extmodel
|
|
|
|
sysctl_int("machdep.cpu.extmodel")
|
|
|
|
end
|
|
|
|
|
2016-04-25 18:00:01 +01:00
|
|
|
def aes?
|
|
|
|
sysctl_bool("hw.optional.aes")
|
|
|
|
end
|
|
|
|
|
|
|
|
def altivec?
|
|
|
|
sysctl_bool("hw.optional.altivec")
|
|
|
|
end
|
|
|
|
|
|
|
|
def avx?
|
|
|
|
sysctl_bool("hw.optional.avx1_0")
|
|
|
|
end
|
|
|
|
|
|
|
|
def avx2?
|
|
|
|
sysctl_bool("hw.optional.avx2_0")
|
|
|
|
end
|
|
|
|
|
|
|
|
def sse3?
|
|
|
|
sysctl_bool("hw.optional.sse3")
|
|
|
|
end
|
|
|
|
|
|
|
|
def ssse3?
|
|
|
|
sysctl_bool("hw.optional.supplementalsse3")
|
|
|
|
end
|
|
|
|
|
|
|
|
def sse4_2?
|
|
|
|
sysctl_bool("hw.optional.sse4_2")
|
|
|
|
end
|
|
|
|
|
2020-11-13 09:49:06 -05:00
|
|
|
# NOTE: this is more reliable than checking uname.
|
2020-11-12 17:06:47 +00:00
|
|
|
# `sysctl` returns the right answer even when running in Rosetta 2.
|
2020-07-13 11:00:14 -07:00
|
|
|
def physical_cpu_arm64?
|
|
|
|
sysctl_bool("hw.optional.arm64")
|
|
|
|
end
|
|
|
|
|
2020-11-12 17:06:47 +00:00
|
|
|
private
|
|
|
|
|
2016-04-25 18:00:01 +01:00
|
|
|
def sysctl_bool(key)
|
|
|
|
sysctl_int(key) == 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def sysctl_int(key)
|
|
|
|
sysctl_n(key).to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
def sysctl_n(*keys)
|
|
|
|
(@properties ||= {}).fetch(keys) do
|
|
|
|
@properties[keys] = Utils.popen_read("/usr/sbin/sysctl", "-n", *keys)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|