Skip to content

Commit 58f74b3

Browse files
init darwin cpu support
Signed-off-by: Nahian Pathan <nahian@me.com>
1 parent 633fd9f commit 58f74b3

File tree

2 files changed

+137
-2
lines changed

2 files changed

+137
-2
lines changed

pkg/cpu/cpu_darwin.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package cpu
2+
3+
import (
4+
"fmt"
5+
"github.com/pkg/errors"
6+
"os/exec"
7+
"strconv"
8+
"strings"
9+
)
10+
11+
var (
12+
hasARMArchitecture = false // determine if ARM
13+
sysctlOutput = make(map[string]string) // store all the sysctl output
14+
)
15+
16+
func (i *Info) load() error {
17+
err := populateSysctlOutput()
18+
if err != nil {
19+
return errors.Wrap(err, "unable to populate sysctl map")
20+
}
21+
22+
i.TotalCores = getTotalCores()
23+
i.TotalThreads = getTotalThreads()
24+
i.Processors = getProcessors()
25+
26+
return nil
27+
}
28+
29+
// getProcessors some more info https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities
30+
func getProcessors() []*Processor {
31+
p := make([]*Processor, getProcTopCount())
32+
for i, _ := range p {
33+
p[i] = new(Processor)
34+
p[i].Vendor = sysctlOutput[fmt.Sprintf("hw.perflevel%s.name", strconv.Itoa(i))]
35+
p[i].Model = getVendor()
36+
p[i].NumCores = getNumberCoresFromPerfLevel(i)
37+
p[i].Capabilities = getCapabilities()
38+
p[i].Cores = make([]*ProcessorCore, getTotalCores())
39+
}
40+
return p
41+
}
42+
43+
// getCapabilities valid for ARM, see https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
44+
func getCapabilities() []string {
45+
var caps []string
46+
47+
// add ARM capabilities
48+
if hasARMArchitecture {
49+
for cap, isEnabled := range sysctlOutput {
50+
if isEnabled == "1" {
51+
// capabilities with keys with a common prefix
52+
commonPrefix := "hw.optional.arm."
53+
if strings.HasPrefix(cap, commonPrefix) {
54+
caps = append(caps, strings.TrimPrefix(cap, commonPrefix))
55+
}
56+
// not following prefix convention but are important
57+
if cap == "hw.optional.AdvSIMD_HPFPCvt" {
58+
caps = append(caps, "AdvSIMD_HPFPCvt")
59+
}
60+
if cap == "hw.optional.armv8_crc32" {
61+
caps = append(caps, "armv8_crc32")
62+
}
63+
}
64+
}
65+
66+
// hw.optional.AdvSIMD and hw.optional.floatingpoint are always enabled (see linked doc)
67+
caps = append(caps, "AdvSIMD")
68+
caps = append(caps, "floatingpoint")
69+
}
70+
71+
return caps
72+
}
73+
74+
// populateSysctlOutput to populate a map to quickly retrieve values later
75+
func populateSysctlOutput() error {
76+
// get sysctl output
77+
o, err := exec.Command("sysctl", "-a").CombinedOutput()
78+
if err != nil {
79+
return err
80+
}
81+
82+
// clean up and store sysctl output
83+
oS := strings.Split(string(o), "\n")
84+
for _, l := range oS {
85+
if l != "" {
86+
s := strings.SplitN(l, ":", 2)
87+
k, v := strings.TrimSpace(s[0]), strings.TrimSpace(s[1])
88+
sysctlOutput[k] = v
89+
90+
// see if it's possible to determine if ARM
91+
if k == "hw.optional.arm64" && v == "1" {
92+
hasARMArchitecture = true
93+
}
94+
}
95+
}
96+
97+
return nil
98+
}
99+
100+
func getNumberCoresFromPerfLevel(i int) uint32 {
101+
key := fmt.Sprintf("hw.perflevel%s.physicalcpu_max", strconv.Itoa(i))
102+
nCores := sysctlOutput[key]
103+
return stringToUint32(nCores)
104+
}
105+
106+
func getVendor() string {
107+
v := sysctlOutput["machdep.cpu.brand_string"]
108+
return v
109+
}
110+
111+
func getProcTopCount() int {
112+
pC, ok := sysctlOutput["hw.nperflevels"]
113+
if !ok {
114+
// most likely intel so no performance/efficiency core seperation
115+
return 1
116+
}
117+
i, _ := strconv.Atoi(pC)
118+
return i
119+
}
120+
121+
// num of physical cores
122+
func getTotalCores() uint32 {
123+
nCores := sysctlOutput["hw.physicalcpu_max"]
124+
return stringToUint32(nCores)
125+
}
126+
127+
func getTotalThreads() uint32 {
128+
nThreads := sysctlOutput["machdep.cpu.thread_count"]
129+
return stringToUint32(nThreads)
130+
}
131+
132+
func stringToUint32(s string) uint32 {
133+
o, _ := strconv.ParseUint(s, 10, 0)
134+
return uint32(o)
135+
}

pkg/cpu/cpu_stub.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build !linux && !windows
2-
// +build !linux,!windows
1+
//go:build !linux && !windows && !darwin
2+
// +build !linux,!windows,!darwin
33

44
// Use and distribution licensed under the Apache license version 2.
55
//

0 commit comments

Comments
 (0)