Skip to content

Commit 57d5711

Browse files
committed
refactor TimesWithContext
don't make assumptions on which CPUs are online and wich aren't based on hw.smt and hw.ncpuonline. Rather, use KERN_CPUSTATS to get the CPU statistics, which includes a flag field that can tell us if that CPU is online or not.
1 parent 16cc7d7 commit 57d5711

File tree

1 file changed

+49
-70
lines changed

1 file changed

+49
-70
lines changed

cpu/cpu_openbsd.go

+49-70
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"context"
88
"fmt"
99
"runtime"
10-
"syscall"
1110
"unsafe"
1211

1312
"github.com/shirou/gopsutil/v3/internal/common"
@@ -26,13 +25,14 @@ const (
2625
cpIntr = 4
2726
cpIdle = 5
2827
cpuStates = 6
28+
cpuOnline = 0x0001 // CPUSTATS_ONLINE
2929

3030
// sys/sysctl.h
31-
ctlKern = 1 // "high kernel": proc, limits
32-
ctlHw = 6 // CTL_HW
33-
smt = 24 // HW_SMT
34-
kernCptime = 40 // KERN_CPTIME
35-
kernCptime2 = 71 // KERN_CPTIME2
31+
ctlKern = 1 // "high kernel": proc, limits
32+
ctlHw = 6 // CTL_HW
33+
smt = 24 // HW_SMT
34+
kernCpTime = 40 // KERN_CPTIME
35+
kernCPUStats = 85 // KERN_CPUSTATS
3636
)
3737

3838
var ClocksPerSec = float64(128)
@@ -45,87 +45,66 @@ func init() {
4545
}
4646
}
4747

48-
func smtEnabled() (bool, error) {
49-
mib := []int32{ctlHw, smt}
50-
buf, _, err := common.CallSyscall(mib)
51-
if err != nil {
52-
return false, err
53-
}
54-
55-
smt := *(*uint32)(unsafe.Pointer(&buf[0]))
56-
return smt == 1, nil
57-
}
58-
5948
func Times(percpu bool) ([]TimesStat, error) {
6049
return TimesWithContext(context.Background(), percpu)
6150
}
6251

63-
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
64-
var ret []TimesStat
65-
66-
var ncpu int
67-
if percpu {
68-
ncpu, _ = Counts(true)
69-
} else {
70-
ncpu = 1
52+
func cpsToTS(cpuTimes [cpuStates]uint64, name string) TimesStat {
53+
return TimesStat{
54+
CPU: name,
55+
User: float64(cpuTimes[cpUser]) / ClocksPerSec,
56+
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,
57+
System: float64(cpuTimes[cpSys]) / ClocksPerSec,
58+
Idle: float64(cpuTimes[cpIdle]) / ClocksPerSec,
59+
Irq: float64(cpuTimes[cpIntr]) / ClocksPerSec,
7160
}
61+
}
7262

73-
smt, err := smtEnabled()
74-
if err == syscall.EOPNOTSUPP {
75-
// if hw.smt is not applicable for this platform (e.g. i386),
76-
// pretend it's enabled
77-
smt = true
78-
} else if err != nil {
79-
return nil, err
80-
}
63+
func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
64+
cpuTimes := [cpuStates]uint64{}
8165

82-
for i := 0; i < ncpu; i++ {
83-
j := i
84-
if !smt {
85-
j *= 2
66+
if !percpu {
67+
mib := []int32{ctlKern, kernCpTime}
68+
buf, _, err := common.CallSyscall(mib)
69+
if err != nil {
70+
return ret, err
8671
}
87-
88-
var mib []int32
89-
if percpu {
90-
mib = []int32{ctlKern, kernCptime2, int32(j)}
91-
} else {
92-
mib = []int32{ctlKern, kernCptime}
72+
var x []C.long
73+
// could use unsafe.Slice but it's only for go1.17+
74+
x = (*[cpuStates]C.long)(unsafe.Pointer(&buf[0]))[:]
75+
for i := range x {
76+
cpuTimes[i] = uint64(x[i])
9377
}
78+
c := cpsToTS(cpuTimes, "cpu-total")
79+
return []TimesStat{c}, nil
80+
}
81+
82+
ncpu, err := unix.SysctlUint32("hw.ncpu")
83+
if err != nil {
84+
return
85+
}
86+
87+
var i uint32
88+
for i = 0; i < ncpu; i++ {
89+
mib := []int32{ctlKern, kernCPUStats, int32(i)}
9490
buf, _, err := common.CallSyscall(mib)
9591
if err != nil {
9692
return ret, err
9793
}
9894

99-
var cpuTimes [cpuStates]uint64
100-
if percpu {
101-
// could use unsafe.Slice but it's only for go1.17+
102-
var x []uint64
103-
x = (*[cpuStates]uint64)(unsafe.Pointer(&buf[0]))[:]
104-
for i := range x {
105-
cpuTimes[i] = x[i]
106-
}
107-
} else {
108-
// KERN_CPTIME yields long[CPUSTATES] and `long' is
109-
// platform dependent
110-
var x []C.long
111-
x = (*[cpuStates]C.long)(unsafe.Pointer(&buf[0]))[:]
112-
for i := range x {
113-
cpuTimes[i] = uint64(x[i])
114-
}
95+
data := unsafe.Pointer(&buf[0])
96+
fptr := unsafe.Pointer(uintptr(data) + uintptr(8*cpuStates))
97+
flags := *(*uint64)(fptr)
98+
if (flags & cpuOnline) == 0 {
99+
continue
115100
}
116101

117-
c := TimesStat{
118-
User: float64(cpuTimes[cpUser]) / ClocksPerSec,
119-
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,
120-
System: float64(cpuTimes[cpSys]) / ClocksPerSec,
121-
Idle: float64(cpuTimes[cpIdle]) / ClocksPerSec,
122-
Irq: float64(cpuTimes[cpIntr]) / ClocksPerSec,
123-
}
124-
if percpu {
125-
c.CPU = fmt.Sprintf("cpu%d", j)
126-
} else {
127-
c.CPU = "cpu-total"
102+
var x []uint64
103+
x = (*[cpuStates]uint64)(data)[:]
104+
for i := range x {
105+
cpuTimes[i] = x[i]
128106
}
107+
c := cpsToTS(cpuTimes, fmt.Sprintf("cpu%d", i))
129108
ret = append(ret, c)
130109
}
131110

0 commit comments

Comments
 (0)