mirror of https://github.com/shirou/gopsutil
Merge pull request #1530 from darkgeek/feature/netbsd-arm64-port
Add some support for NetBSDtags/v3.23.9 v3.23.9
commit
826376d46a
@ -0,0 +1,119 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// sys/sysctl.h
|
||||
ctlKern = 1 // "high kernel": proc, limits
|
||||
ctlHw = 6 // CTL_HW
|
||||
kernCpTime = 51 // KERN_CPTIME
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(100)
|
||||
|
||||
func init() {
|
||||
clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
ClocksPerSec = float64(clkTck)
|
||||
}
|
||||
}
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
return TimesWithContext(context.Background(), percpu)
|
||||
}
|
||||
|
||||
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),
|
||||
Nice: float64(times.Nice),
|
||||
System: float64(times.Sys),
|
||||
Idle: float64(times.Idle),
|
||||
Irq: float64(times.Intr),
|
||||
}
|
||||
return []TimesStat{stat}, nil
|
||||
}
|
||||
|
||||
ncpu, err := unix.SysctlUint32("hw.ncpu")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var i uint32
|
||||
for i = 0; i < ncpu; i++ {
|
||||
mib := []int32{ctlKern, kernCpTime, int32(i)}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
stats := (*cpuTimes)(unsafe.Pointer(&buf[0]))
|
||||
ret = append(ret, TimesStat{
|
||||
CPU: fmt.Sprintf("cpu%d", i),
|
||||
User: float64(stats.User),
|
||||
Nice: float64(stats.Nice),
|
||||
System: float64(stats.Sys),
|
||||
Idle: float64(stats.Idle),
|
||||
Irq: float64(stats.Intr),
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Returns only one (minimal) CPUInfoStat on NetBSD
|
||||
func Info() ([]InfoStat, error) {
|
||||
return InfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var err error
|
||||
|
||||
c := InfoStat{}
|
||||
|
||||
mhz, err := unix.Sysctl("machdep.dmi.processor-frequency")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = fmt.Sscanf(mhz, "%f", &c.Mhz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ncpu, err := unix.SysctlUint32("hw.ncpuonline")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Cores = int32(ncpu)
|
||||
|
||||
if c.ModelName, err = unix.Sysctl("machdep.dmi.processor-version"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return append(ret, c), nil
|
||||
}
|
||||
|
||||
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package cpu
|
||||
|
||||
type cpuTimes struct {
|
||||
User uint64
|
||||
Nice uint64
|
||||
Sys uint64
|
||||
Intr uint64
|
||||
Idle uint64
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package cpu
|
||||
|
||||
type cpuTimes struct {
|
||||
User uint64
|
||||
Nice uint64
|
||||
Sys uint64
|
||||
Intr uint64
|
||||
Idle uint64
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// see sys/fstypes.h and `man 5 statvfs`
|
||||
MNT_RDONLY = 0x00000001 /* read only filesystem */
|
||||
MNT_SYNCHRONOUS = 0x00000002 /* file system written synchronously */
|
||||
MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */
|
||||
MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */
|
||||
MNT_NODEV = 0x00000010 /* don't interpret special files */
|
||||
MNT_ASYNC = 0x00000040 /* file system written asynchronously */
|
||||
MNT_NOATIME = 0x04000000 /* Never update access times in fs */
|
||||
MNT_SOFTDEP = 0x80000000 /* Use soft dependencies */
|
||||
)
|
||||
|
||||
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
flag := uint64(1) // ST_WAIT/MNT_WAIT, see sys/fstypes.h
|
||||
|
||||
// get required buffer size
|
||||
emptyBufSize := 0
|
||||
r, _, err := unix.Syscall(
|
||||
483, // SYS___getvfsstat90 syscall
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
uintptr(unsafe.Pointer(&emptyBufSize)),
|
||||
uintptr(unsafe.Pointer(&flag)),
|
||||
)
|
||||
if err != 0 {
|
||||
return ret, err
|
||||
}
|
||||
mountedFsCount := uint64(r)
|
||||
|
||||
// calculate the buffer size
|
||||
bufSize := sizeOfStatvfs * mountedFsCount
|
||||
buf := make([]Statvfs, mountedFsCount)
|
||||
|
||||
// request agian to get desired mount data
|
||||
_, _, err = unix.Syscall(
|
||||
483, // SYS___getvfsstat90 syscall
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&bufSize)),
|
||||
uintptr(unsafe.Pointer(&flag)),
|
||||
)
|
||||
if err != 0 {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, stat := range buf {
|
||||
opts := []string{"rw"}
|
||||
if stat.Flag&MNT_RDONLY != 0 {
|
||||
opts = []string{"rw"}
|
||||
}
|
||||
if stat.Flag&MNT_SYNCHRONOUS != 0 {
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.Flag&MNT_NOEXEC != 0 {
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.Flag&MNT_NOSUID != 0 {
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.Flag&MNT_NODEV != 0 {
|
||||
opts = append(opts, "nodev")
|
||||
}
|
||||
if stat.Flag&MNT_ASYNC != 0 {
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.Flag&MNT_SOFTDEP != 0 {
|
||||
opts = append(opts, "softdep")
|
||||
}
|
||||
if stat.Flag&MNT_NOATIME != 0 {
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
Device: common.ByteToString([]byte(stat.Mntfromname[:])),
|
||||
Mountpoint: common.ByteToString([]byte(stat.Mntonname[:])),
|
||||
Fstype: common.ByteToString([]byte(stat.Fstypename[:])),
|
||||
Opts: opts,
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
ret := make(map[string]IOCountersStat)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
stat := Statvfs{}
|
||||
flag := uint64(1) // ST_WAIT/MNT_WAIT, see sys/fstypes.h
|
||||
|
||||
_path, e := unix.BytePtrFromString(path)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
_, _, err := unix.Syscall(
|
||||
484, // SYS___statvfs190, see sys/syscall.h
|
||||
uintptr(unsafe.Pointer(_path)),
|
||||
uintptr(unsafe.Pointer(&stat)),
|
||||
uintptr(unsafe.Pointer(&flag)),
|
||||
)
|
||||
if err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// frsize is the real block size on NetBSD. See discuss here: https://bugzilla.samba.org/show_bug.cgi?id=11810
|
||||
bsize := stat.Frsize
|
||||
ret := &UsageStat{
|
||||
Path: path,
|
||||
Fstype: getFsType(stat),
|
||||
Total: (uint64(stat.Blocks) * uint64(bsize)),
|
||||
Free: (uint64(stat.Bavail) * uint64(bsize)),
|
||||
InodesTotal: (uint64(stat.Files)),
|
||||
InodesFree: (uint64(stat.Ffree)),
|
||||
}
|
||||
|
||||
ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
|
||||
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
|
||||
ret.Used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize)
|
||||
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func getFsType(stat Statvfs) string {
|
||||
return common.ByteToString(stat.Fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//go:build netbsd && amd64
|
||||
// +build netbsd,amd64
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_netbsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeOfStatvfs = 0xce0
|
||||
)
|
||||
|
||||
type (
|
||||
Statvfs struct {
|
||||
Flag uint64
|
||||
Bsize uint64
|
||||
Frsize uint64
|
||||
Iosize uint64
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail uint64
|
||||
Bresvd uint64
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
Favail uint64
|
||||
Fresvd uint64
|
||||
Syncreads uint64
|
||||
Syncwrites uint64
|
||||
Asyncreads uint64
|
||||
Asyncwrites uint64
|
||||
Fsidx _Ctype_struct___0
|
||||
Fsid uint64
|
||||
Namemax uint64
|
||||
Owner uint32
|
||||
Spare [4]uint64
|
||||
Fstypename [32]uint8
|
||||
Mntonname [1024]uint8
|
||||
Mntfromname [1024]uint8
|
||||
Mntfromlabel [1024]uint8
|
||||
}
|
||||
)
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
FsidVal [2]int32
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//go:build netbsd && arm64
|
||||
// +build netbsd,arm64
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_netbsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeOfStatvfs = 0xce0
|
||||
)
|
||||
|
||||
type (
|
||||
Statvfs struct {
|
||||
Flag uint64
|
||||
Bsize uint64
|
||||
Frsize uint64
|
||||
Iosize uint64
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail uint64
|
||||
Bresvd uint64
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
Favail uint64
|
||||
Fresvd uint64
|
||||
Syncreads uint64
|
||||
Syncwrites uint64
|
||||
Asyncreads uint64
|
||||
Asyncwrites uint64
|
||||
Fsidx _Ctype_struct___0
|
||||
Fsid uint64
|
||||
Namemax uint64
|
||||
Owner uint32
|
||||
Spare [4]uint64
|
||||
Fstypename [32]uint8
|
||||
Mntonname [1024]uint8
|
||||
Mntfromname [1024]uint8
|
||||
Mntfromlabel [1024]uint8
|
||||
}
|
||||
)
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
FsidVal [2]int32
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// Hand writing: _Ctype_struct___0
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package disk
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/featuretest.h>
|
||||
#include <sys/stdint.h>
|
||||
#include <machine/ansi.h>
|
||||
#include <sys/ansi.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const (
|
||||
sizeOfStatvfs = C.sizeof_struct_statvfs
|
||||
)
|
||||
|
||||
type (
|
||||
Statvfs C.struct_statvfs
|
||||
)
|
@ -0,0 +1,55 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func numProcs(ctx context.Context) (uint64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
|
||||
p, err := unix.Sysctl("kern.ostype")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(p)
|
||||
}
|
||||
v, err := unix.Sysctl("kern.osrelease")
|
||||
if err == nil {
|
||||
version = strings.ToLower(v)
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
}
|
||||
|
||||
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
return "", "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
var ret []UserStat
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
return []TemperatureStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func KernelVersionWithContext(ctx context.Context) (string, error) {
|
||||
_, _, version, err := PlatformInformationWithContext(ctx)
|
||||
return version, err
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
cmd := exec.Command("sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
// get required buffer size
|
||||
length := uint64(0)
|
||||
_, _, err := unix.Syscall6(
|
||||
unix.SYS___SYSCTL,
|
||||
uintptr(mibptr),
|
||||
uintptr(miblen),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
var b []byte
|
||||
return b, length, err
|
||||
}
|
||||
if length == 0 {
|
||||
var b []byte
|
||||
return b, length, err
|
||||
}
|
||||
// get proc info itself
|
||||
buf := make([]byte, length)
|
||||
_, _, err = unix.Syscall6(
|
||||
unix.SYS___SYSCTL,
|
||||
uintptr(mibptr),
|
||||
uintptr(miblen),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
return buf, length, err
|
||||
}
|
||||
|
||||
return buf, length, nil
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func GetPageSize() (uint64, error) {
|
||||
return GetPageSizeWithContext(context.Background())
|
||||
}
|
||||
|
||||
func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
|
||||
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(uvmexp.Pagesize), nil
|
||||
}
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
return VirtualMemoryWithContext(context.Background())
|
||||
}
|
||||
|
||||
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
|
||||
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := uint64(uvmexp.Pagesize)
|
||||
|
||||
ret := &VirtualMemoryStat{
|
||||
Total: uint64(uvmexp.Npages) * p,
|
||||
Free: uint64(uvmexp.Free) * p,
|
||||
Active: uint64(uvmexp.Active) * p,
|
||||
Inactive: uint64(uvmexp.Inactive) * p,
|
||||
Cached: 0, // not available
|
||||
Wired: uint64(uvmexp.Wired) * p,
|
||||
}
|
||||
|
||||
ret.Available = ret.Inactive + ret.Cached + ret.Free
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
||||
|
||||
// Get buffers from vm.bufmem sysctl
|
||||
ret.Buffers, err = unix.SysctlUint64("vm.bufmem")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Return swapctl summary info
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
return SwapMemoryWithContext(context.Background())
|
||||
}
|
||||
|
||||
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
out, err := invoke.CommandWithContext(ctx, "swapctl", "-sk")
|
||||
if err != nil {
|
||||
return &SwapMemoryStat{}, nil
|
||||
}
|
||||
|
||||
line := string(out)
|
||||
var total, used, free uint64
|
||||
|
||||
_, err = fmt.Sscanf(line,
|
||||
"total: %d 1K-blocks allocated, %d used, %d available",
|
||||
&total, &used, &free)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to parse swapctl output")
|
||||
}
|
||||
|
||||
percent := float64(used) / float64(total) * 100
|
||||
return &SwapMemoryStat{
|
||||
Total: total * 1024,
|
||||
Used: used * 1024,
|
||||
Free: free * 1024,
|
||||
UsedPercent: percent,
|
||||
}, nil
|
||||
}
|
Loading…
Reference in New Issue