From 61b1fce9fb3bf47fa162d783a4fd86114dfc9ead Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Sat, 21 Nov 2020 12:43:48 -0600 Subject: [PATCH 1/2] support for apple silicon macs Previously on darwin, it was safe to assume that `hw.cpufrequency` would be defined in sysctl. On the new M1 macs instead use the base frequency `hw.tbfrequency` and `kern.clockrate[hz]`. The computed value appears to be 2.4 GHz, which is I believe is the correct base clock. --- cpu/cpu_darwin.go | 22 +++++++++++++++++++++- v3/cpu/cpu_darwin.go | 22 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/cpu/cpu_darwin.go b/cpu/cpu_darwin.go index 3d3455ee6..bef5db020 100644 --- a/cpu/cpu_darwin.go +++ b/cpu/cpu_darwin.go @@ -93,7 +93,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { // Use the rated frequency of the CPU. This is a static value and does not // account for low power or Turbo Boost modes. - cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency") + cpuFrequency, err := getFrequency() if err != nil { return ret, err } @@ -102,6 +102,26 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { return append(ret, c), nil } +func getFrequency() (uint64, error) { + // This works for Intel macs. + if cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency"); err == nil { + return cpuFrequency, nil + } + + // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] + tbFreq, err := unix.SysctlUint64("hw.tbfrequency") + if err != nil { + return 0, err + } + + kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") + if err != nil { + return 0, err + } + + return uint64(kernClockrate.Hz) * tbFreq, nil +} + func CountsWithContext(ctx context.Context, logical bool) (int, error) { var cpuArgument string if logical { diff --git a/v3/cpu/cpu_darwin.go b/v3/cpu/cpu_darwin.go index 73151b40f..cbb1e6de3 100644 --- a/v3/cpu/cpu_darwin.go +++ b/v3/cpu/cpu_darwin.go @@ -93,7 +93,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { // Use the rated frequency of the CPU. This is a static value and does not // account for low power or Turbo Boost modes. - cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency") + cpuFrequency, err := getFrequency() if err != nil { return ret, err } @@ -102,6 +102,26 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { return append(ret, c), nil } +func getFrequency() (uint64, error) { + // This works for Intel macs. + if cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency"); err == nil { + return cpuFrequency, nil + } + + // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] + tbFreq, err := unix.SysctlUint64("hw.tbfrequency") + if err != nil { + return 0, err + } + + kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") + if err != nil { + return 0, err + } + + return uint64(kernClockrate.Hz) * tbFreq, nil +} + func CountsWithContext(ctx context.Context, logical bool) (int, error) { var cpuArgument string if logical { From 83b9e5244df73b6c4ae8ecb63c7f207fd992895a Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Sat, 28 Nov 2020 08:26:01 -0600 Subject: [PATCH 2/2] inline darwin cpufreq gathering --- cpu/cpu_darwin.go | 33 +++++++++++++-------------------- v3/cpu/cpu_darwin.go | 33 +++++++++++++-------------------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/cpu/cpu_darwin.go b/cpu/cpu_darwin.go index bef5db020..ff3829249 100644 --- a/cpu/cpu_darwin.go +++ b/cpu/cpu_darwin.go @@ -93,33 +93,26 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { // Use the rated frequency of the CPU. This is a static value and does not // account for low power or Turbo Boost modes. - cpuFrequency, err := getFrequency() - if err != nil { - return ret, err - } - c.Mhz = float64(cpuFrequency) / 1000000.0 - - return append(ret, c), nil -} -func getFrequency() (uint64, error) { // This works for Intel macs. if cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency"); err == nil { - return cpuFrequency, nil - } + c.Mhz = float64(cpuFrequency) / 1000000.0 + } else { + // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] + tbFreq, err := unix.SysctlUint64("hw.tbfrequency") + if err != nil { + return append(ret, c), err + } - // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] - tbFreq, err := unix.SysctlUint64("hw.tbfrequency") - if err != nil { - return 0, err - } + kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") + if err != nil { + return append(ret, c), err + } - kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") - if err != nil { - return 0, err + c.Mhz = (float64(tbFreq) * float64(kernClockrate.Hz)) / 1000000.0 } - return uint64(kernClockrate.Hz) * tbFreq, nil + return append(ret, c), nil } func CountsWithContext(ctx context.Context, logical bool) (int, error) { diff --git a/v3/cpu/cpu_darwin.go b/v3/cpu/cpu_darwin.go index cbb1e6de3..b4cf2838e 100644 --- a/v3/cpu/cpu_darwin.go +++ b/v3/cpu/cpu_darwin.go @@ -93,33 +93,26 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { // Use the rated frequency of the CPU. This is a static value and does not // account for low power or Turbo Boost modes. - cpuFrequency, err := getFrequency() - if err != nil { - return ret, err - } - c.Mhz = float64(cpuFrequency) / 1000000.0 - - return append(ret, c), nil -} -func getFrequency() (uint64, error) { // This works for Intel macs. if cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency"); err == nil { - return cpuFrequency, nil - } + c.Mhz = float64(cpuFrequency) / 1000000.0 + } else { + // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] + tbFreq, err := unix.SysctlUint64("hw.tbfrequency") + if err != nil { + return append(ret, c), err + } - // On Apple Silicon fallback to hw.tbfrequency and kern.clockrate[hz] - tbFreq, err := unix.SysctlUint64("hw.tbfrequency") - if err != nil { - return 0, err - } + kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") + if err != nil { + return append(ret, c), err + } - kernClockrate, err := unix.SysctlClockinfo("kern.clockrate") - if err != nil { - return 0, err + c.Mhz = (float64(tbFreq) * float64(kernClockrate.Hz)) / 1000000.0 } - return uint64(kernClockrate.Hz) * tbFreq, nil + return append(ret, c), nil } func CountsWithContext(ctx context.Context, logical bool) (int, error) {