Skip to content

Commit 701a74b

Browse files
committed
feat(cpu, mem, sensors)(darwin): cgo-free implementations
1 parent 211eb8c commit 701a74b

16 files changed

+735
-696
lines changed

cpu/cpu_darwin.go

+90-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ package cpu
55

66
import (
77
"context"
8+
"fmt"
89
"strconv"
910
"strings"
11+
"unsafe"
1012

1113
"github.com/shoenig/go-m1cpu"
1214
"github.com/tklauser/go-sysconf"
1315
"golang.org/x/sys/unix"
16+
17+
"github.com/shirou/gopsutil/v4/internal/common"
1418
)
1519

1620
// sys/resource.h
@@ -23,6 +27,24 @@ const (
2327
cpUStates = 5
2428
)
2529

30+
// mach/machine.h
31+
const (
32+
cpuStateUser = 0
33+
cpuStateSystem = 1
34+
cpuStateIdle = 2
35+
cpuStateNice = 3
36+
cpuStateMax = 4
37+
)
38+
39+
// mach/processor_info.h
40+
const (
41+
processorCpuLoadInfo = 2
42+
)
43+
44+
type hostCpuLoadInfoData struct {
45+
cpuTicks [cpuStateMax]uint32
46+
}
47+
2648
// default value. from time.h
2749
var ClocksPerSec = float64(128)
2850

@@ -39,11 +61,17 @@ func Times(percpu bool) ([]TimesStat, error) {
3961
}
4062

4163
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
64+
lib, err := common.NewLibrary(common.Kernel)
65+
if err != nil {
66+
return nil, err
67+
}
68+
defer lib.Close()
69+
4270
if percpu {
43-
return perCPUTimes()
71+
return perCPUTimes(lib)
4472
}
4573

46-
return allCPUTimes()
74+
return allCPUTimes(lib)
4775
}
4876

4977
// Returns only one CPUInfoStat on FreeBSD
@@ -115,3 +143,63 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
115143

116144
return int(count), nil
117145
}
146+
147+
func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
148+
machHostSelf := common.GetFunc[common.MachHostSelfFunc](machLib, common.MachHostSelfSym)
149+
machTaskSelf := common.GetFunc[common.MachTaskSelfFunc](machLib, common.MachTaskSelfSym)
150+
hostProcessorInfo := common.GetFunc[common.HostProcessorInfoFunc](machLib, common.HostProcessorInfoSym)
151+
vmDeallocate := common.GetFunc[common.VMDeallocateFunc](machLib, common.VMDeallocateSym)
152+
153+
var count, ncpu uint32
154+
var cpuload *hostCpuLoadInfoData
155+
156+
status := hostProcessorInfo(machHostSelf(), processorCpuLoadInfo, &ncpu, uintptr(unsafe.Pointer(&cpuload)), &count)
157+
158+
if status != common.KERN_SUCCESS {
159+
return nil, fmt.Errorf("host_processor_info error=%d", status)
160+
}
161+
162+
defer vmDeallocate(machTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu))
163+
164+
ret := []TimesStat{}
165+
loads := unsafe.Slice(cpuload, ncpu)
166+
167+
for i := 0; i < int(ncpu); i++ {
168+
c := TimesStat{
169+
CPU: fmt.Sprintf("cpu%d", i),
170+
User: float64(loads[i].cpuTicks[cpuStateUser]) / ClocksPerSec,
171+
System: float64(loads[i].cpuTicks[cpuStateSystem]) / ClocksPerSec,
172+
Nice: float64(loads[i].cpuTicks[cpuStateNice]) / ClocksPerSec,
173+
Idle: float64(loads[i].cpuTicks[cpuStateIdle]) / ClocksPerSec,
174+
}
175+
176+
ret = append(ret, c)
177+
}
178+
179+
return ret, nil
180+
}
181+
182+
func allCPUTimes(machLib *common.Library) ([]TimesStat, error) {
183+
machHostSelf := common.GetFunc[common.MachHostSelfFunc](machLib, common.MachHostSelfSym)
184+
hostStatistics := common.GetFunc[common.HostStatisticsFunc](machLib, common.HostStatisticsSym)
185+
186+
var cpuload hostCpuLoadInfoData
187+
count := uint32(cpuStateMax)
188+
189+
status := hostStatistics(machHostSelf(), common.HOST_CPU_LOAD_INFO,
190+
uintptr(unsafe.Pointer(&cpuload)), &count)
191+
192+
if status != common.KERN_SUCCESS {
193+
return nil, fmt.Errorf("host_statistics error=%d", status)
194+
}
195+
196+
c := TimesStat{
197+
CPU: "cpu-total",
198+
User: float64(cpuload.cpuTicks[cpuStateUser]) / ClocksPerSec,
199+
System: float64(cpuload.cpuTicks[cpuStateSystem]) / ClocksPerSec,
200+
Nice: float64(cpuload.cpuTicks[cpuStateNice]) / ClocksPerSec,
201+
Idle: float64(cpuload.cpuTicks[cpuStateIdle]) / ClocksPerSec,
202+
}
203+
204+
return []TimesStat{c}, nil
205+
}

cpu/cpu_darwin_cgo.go

-111
This file was deleted.

cpu/cpu_darwin_nocgo.go

-14
This file was deleted.

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/shirou/gopsutil/v4
33
go 1.18
44

55
require (
6+
github.com/ebitengine/purego v0.7.1
67
github.com/google/go-cmp v0.6.0
78
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
89
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
4+
github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
35
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
46
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
57
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=

0 commit comments

Comments
 (0)