Merge pull request #1244 from omar-polo/master

fix cpu_openbsd.go once and for all
tags/v3.22.2 v3.22.2
shirou 3 years ago committed by GitHub
commit d33b2dfda5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,141 +4,99 @@
package cpu
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"runtime"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v3/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
)
const (
// sys/sched.h
var (
CPUser = 0
cpNice = 1
cpSys = 2
cpIntr = 3
cpIdle = 4
cpUStates = 5
)
cpuOnline = 0x0001 // CPUSTATS_ONLINE
// sys/sysctl.h
const (
ctlKern = 1 // "high kernel": proc, limits
ctlHw = 6 // CTL_HW
sMT = 24 // HW_sMT
kernCptime = 40 // KERN_CPTIME
kernCptime2 = 71 // KERN_CPTIME2
smt = 24 // HW_SMT
kernCpTime = 40 // KERN_CPTIME
kernCPUStats = 85 // KERN_CPUSTATS
)
var ClocksPerSec = float64(128)
type cpuStats struct {
// cs_time[CPUSTATES]
User uint64
Nice uint64
Sys uint64
Spin uint64
Intr uint64
Idle uint64
// cs_flags
Flags uint64
}
func init() {
clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
// ignore errors
if err == nil {
ClocksPerSec = float64(clkTck)
}
func() {
v, err := unix.Sysctl("kern.osrelease") // can't reuse host.PlatformInformation because of circular import
if err != nil {
return
}
v = strings.ToLower(v)
version, err := strconv.ParseFloat(v, 64)
if err != nil {
return
}
if version >= 6.4 {
cpIntr = 4
cpIdle = 5
cpUStates = 6
}
}()
}
func smt() (bool, error) {
mib := []int32{ctlHw, sMT}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return false, err
}
var ret bool
br := bytes.NewReader(buf)
if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
return false, err
}
return ret, nil
}
func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
var ret []TimesStat
var ncpu int
if percpu {
ncpu, _ = Counts(true)
} else {
ncpu = 1
func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
if !percpu {
mib := []int32{ctlKern, kernCpTime}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return ret, err
}
smt, err := smt()
if err == syscall.EOPNOTSUPP {
// if hw.smt is not applicable for this platform (e.g. i386),
// pretend it's enabled
smt = true
} else if err != nil {
return nil, err
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
stat := TimesStat{
CPU: "cpu-total",
User: float64(times.User) / ClocksPerSec,
Nice: float64(times.Nice) / ClocksPerSec,
System: float64(times.Sys) / ClocksPerSec,
Idle: float64(times.Idle) / ClocksPerSec,
Irq: float64(times.Intr) / ClocksPerSec,
}
for i := 0; i < ncpu; i++ {
j := i
if !smt {
j *= 2
return []TimesStat{stat}, nil
}
cpuTimes := make([]int32, cpUStates)
var mib []int32
if percpu {
mib = []int32{ctlKern, kernCptime2, int32(j)}
} else {
mib = []int32{ctlKern, kernCptime}
}
buf, _, err := common.CallSyscall(mib)
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return ret, err
return
}
br := bytes.NewReader(buf)
err = binary.Read(br, binary.LittleEndian, &cpuTimes)
var i uint32
for i = 0; i < ncpu; i++ {
mib := []int32{ctlKern, kernCPUStats, int32(i)}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return ret, err
}
c := TimesStat{
User: float64(cpuTimes[CPUser]) / ClocksPerSec,
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,
System: float64(cpuTimes[cpSys]) / ClocksPerSec,
Idle: float64(cpuTimes[cpIdle]) / ClocksPerSec,
Irq: float64(cpuTimes[cpIntr]) / ClocksPerSec,
}
if percpu {
c.CPU = fmt.Sprintf("cpu%d", j)
} else {
c.CPU = "cpu-total"
stats := (*cpuStats)(unsafe.Pointer(&buf[0]))
if (stats.Flags & cpuOnline) == 0 {
continue
}
ret = append(ret, c)
ret = append(ret, TimesStat{
CPU: fmt.Sprintf("cpu%d", i),
User: float64(stats.User) / ClocksPerSec,
Nice: float64(stats.Nice) / ClocksPerSec,
System: float64(stats.Sys) / ClocksPerSec,
Idle: float64(stats.Idle) / ClocksPerSec,
Irq: float64(stats.Intr) / ClocksPerSec,
})
}
return ret, nil

@ -0,0 +1,10 @@
package cpu
type cpuTimes struct {
User uint32
Nice uint32
Sys uint32
Spin uint32
Intr uint32
Idle uint32
}

@ -0,0 +1,10 @@
package cpu
type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Spin uint64
Intr uint64
Idle uint64
}
Loading…
Cancel
Save