1// +build darwin
2
3package cpu
4
5import (
6	"context"
7	"strconv"
8	"strings"
9
10	"github.com/tklauser/go-sysconf"
11	"golang.org/x/sys/unix"
12)
13
14// sys/resource.h
15const (
16	CPUser    = 0
17	CPNice    = 1
18	CPSys     = 2
19	CPIntr    = 3
20	CPIdle    = 4
21	CPUStates = 5
22)
23
24// default value. from time.h
25var ClocksPerSec = float64(128)
26
27func init() {
28	clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
29	// ignore errors
30	if err == nil {
31		ClocksPerSec = float64(clkTck)
32	}
33}
34
35func Times(percpu bool) ([]TimesStat, error) {
36	return TimesWithContext(context.Background(), percpu)
37}
38
39func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
40	if percpu {
41		return perCPUTimes()
42	}
43
44	return allCPUTimes()
45}
46
47// Returns only one CPUInfoStat on FreeBSD
48func Info() ([]InfoStat, error) {
49	return InfoWithContext(context.Background())
50}
51
52func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
53	var ret []InfoStat
54
55	c := InfoStat{}
56	c.ModelName, _ = unix.Sysctl("machdep.cpu.brand_string")
57	family, _ := unix.SysctlUint32("machdep.cpu.family")
58	c.Family = strconv.FormatUint(uint64(family), 10)
59	model, _ := unix.SysctlUint32("machdep.cpu.model")
60	c.Model = strconv.FormatUint(uint64(model), 10)
61	stepping, _ := unix.SysctlUint32("machdep.cpu.stepping")
62	c.Stepping = int32(stepping)
63	features, err := unix.Sysctl("machdep.cpu.features")
64	if err == nil {
65		for _, v := range strings.Fields(features) {
66			c.Flags = append(c.Flags, strings.ToLower(v))
67		}
68	}
69	leaf7Features, err := unix.Sysctl("machdep.cpu.leaf7_features")
70	if err == nil {
71		for _, v := range strings.Fields(leaf7Features) {
72			c.Flags = append(c.Flags, strings.ToLower(v))
73		}
74	}
75	extfeatures, err := unix.Sysctl("machdep.cpu.extfeatures")
76	if err == nil {
77		for _, v := range strings.Fields(extfeatures) {
78			c.Flags = append(c.Flags, strings.ToLower(v))
79		}
80	}
81	cores, _ := unix.SysctlUint32("machdep.cpu.core_count")
82	c.Cores = int32(cores)
83	cacheSize, _ := unix.SysctlUint32("machdep.cpu.cache.size")
84	c.CacheSize = int32(cacheSize)
85	c.VendorID, _ = unix.Sysctl("machdep.cpu.vendor")
86
87	// Use the rated frequency of the CPU. This is a static value and does not
88	// account for low power or Turbo Boost modes.
89	cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency")
90	if err != nil {
91		return ret, err
92	}
93	c.Mhz = float64(cpuFrequency) / 1000000.0
94
95	return append(ret, c), nil
96}
97
98func CountsWithContext(ctx context.Context, logical bool) (int, error) {
99	var cpuArgument string
100	if logical {
101		cpuArgument = "hw.logicalcpu"
102	} else {
103		cpuArgument = "hw.physicalcpu"
104	}
105
106	count, err := unix.SysctlUint32(cpuArgument)
107	if err != nil {
108		return 0, err
109	}
110
111	return int(count), nil
112}
113