Skip to content

Commit 16cc7d7

Browse files
committed
improve sysctl parsing: use native byte order
We can't use unix.Sysctl* for some sysctls, so we're on our own with converting data from C arrays. Don't assume that the byte order is little endian but do the right thing. Moreover, there's a little distinction in the sizes reported by KERN_CPTIME (long[cpustates]) and KERN_CPTIME2 (u_int64_t[cpustates]) so account for that too.
1 parent 73db061 commit 16cc7d7

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

cpu/cpu_openbsd.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@
44
package cpu
55

66
import (
7-
"bytes"
87
"context"
9-
"encoding/binary"
108
"fmt"
119
"runtime"
1210
"syscall"
11+
"unsafe"
1312

1413
"github.com/shirou/gopsutil/v3/internal/common"
1514
"github.com/tklauser/go-sysconf"
1615
"golang.org/x/sys/unix"
1716
)
1817

18+
import "C"
19+
1920
const (
2021
// sys/sched.h
2122
cpUser = 0
@@ -51,13 +52,8 @@ func smtEnabled() (bool, error) {
5152
return false, err
5253
}
5354

54-
var ret bool
55-
br := bytes.NewReader(buf)
56-
if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
57-
return false, err
58-
}
59-
60-
return ret, nil
55+
smt := *(*uint32)(unsafe.Pointer(&buf[0]))
56+
return smt == 1, nil
6157
}
6258

6359
func Times(percpu bool) ([]TimesStat, error) {
@@ -89,7 +85,6 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
8985
j *= 2
9086
}
9187

92-
cpuTimes := make([]int32, cpuStates)
9388
var mib []int32
9489
if percpu {
9590
mib = []int32{ctlKern, kernCptime2, int32(j)}
@@ -101,11 +96,24 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
10196
return ret, err
10297
}
10398

104-
br := bytes.NewReader(buf)
105-
err = binary.Read(br, binary.LittleEndian, &cpuTimes)
106-
if err != nil {
107-
return ret, err
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+
}
108115
}
116+
109117
c := TimesStat{
110118
User: float64(cpuTimes[cpUser]) / ClocksPerSec,
111119
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,

0 commit comments

Comments
 (0)