Skip to content

Commit

Permalink
Merge pull request #1244 from omar-polo/master
Browse files Browse the repository at this point in the history
fix cpu_openbsd.go once and for all
  • Loading branch information
shirou authored Feb 25, 2022
2 parents 2fa880a + 73f9c8d commit d33b2df
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 99 deletions.
156 changes: 57 additions & 99 deletions cpu/cpu_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

// sys/sched.h
var (
CPUser = 0
cpNice = 1
cpSys = 2
cpIntr = 3
cpIdle = 4
cpUStates = 5
)

// 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
// sys/sched.h
cpuOnline = 0x0001 // CPUSTATS_ONLINE

// sys/sysctl.h
ctlKern = 1 // "high kernel": proc, limits
ctlHw = 6 // CTL_HW
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
}
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,
}
return []TimesStat{stat}, nil
}

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
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return
}

for i := 0; i < ncpu; i++ {
j := i
if !smt {
j *= 2
}

cpuTimes := make([]int32, cpUStates)
var mib []int32
if percpu {
mib = []int32{ctlKern, kernCptime2, int32(j)}
} else {
mib = []int32{ctlKern, kernCptime}
}
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
}

br := bytes.NewReader(buf)
err = binary.Read(br, binary.LittleEndian, &cpuTimes)
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
Expand Down
10 changes: 10 additions & 0 deletions cpu/cpu_openbsd_386.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cpu

type cpuTimes struct {
User uint32
Nice uint32
Sys uint32
Spin uint32
Intr uint32
Idle uint32
}
10 changes: 10 additions & 0 deletions cpu/cpu_openbsd_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cpu

type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Spin uint64
Intr uint64
Idle uint64
}

0 comments on commit d33b2df

Please sign in to comment.