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