1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-28 13:48:49 +08:00

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.
This commit is contained in:
Omar Polo 2022-02-06 23:47:17 +00:00
parent 73db061652
commit 16cc7d7d73

View File

@ -4,18 +4,19 @@
package cpu package cpu
import ( import (
"bytes"
"context" "context"
"encoding/binary"
"fmt" "fmt"
"runtime" "runtime"
"syscall" "syscall"
"unsafe"
"github.com/shirou/gopsutil/v3/internal/common" "github.com/shirou/gopsutil/v3/internal/common"
"github.com/tklauser/go-sysconf" "github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
import "C"
const ( const (
// sys/sched.h // sys/sched.h
cpUser = 0 cpUser = 0
@ -51,13 +52,8 @@ func smtEnabled() (bool, error) {
return false, err return false, err
} }
var ret bool smt := *(*uint32)(unsafe.Pointer(&buf[0]))
br := bytes.NewReader(buf) return smt == 1, nil
if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
return false, err
}
return ret, nil
} }
func Times(percpu bool) ([]TimesStat, error) { func Times(percpu bool) ([]TimesStat, error) {
@ -89,7 +85,6 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
j *= 2 j *= 2
} }
cpuTimes := make([]int32, cpuStates)
var mib []int32 var mib []int32
if percpu { if percpu {
mib = []int32{ctlKern, kernCptime2, int32(j)} mib = []int32{ctlKern, kernCptime2, int32(j)}
@ -101,11 +96,24 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return ret, err return ret, err
} }
br := bytes.NewReader(buf) var cpuTimes [cpuStates]uint64
err = binary.Read(br, binary.LittleEndian, &cpuTimes) if percpu {
if err != nil { // could use unsafe.Slice but it's only for go1.17+
return ret, err var x []uint64
x = (*[cpuStates]uint64)(unsafe.Pointer(&buf[0]))[:]
for i := range x {
cpuTimes[i] = x[i]
} }
} else {
// KERN_CPTIME yields long[CPUSTATES] and `long' is
// platform dependent
var x []C.long
x = (*[cpuStates]C.long)(unsafe.Pointer(&buf[0]))[:]
for i := range x {
cpuTimes[i] = uint64(x[i])
}
}
c := TimesStat{ c := TimesStat{
User: float64(cpuTimes[cpUser]) / ClocksPerSec, User: float64(cpuTimes[cpUser]) / ClocksPerSec,
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec, Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,