| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // +build freebsd
- package mem
- import (
- "context"
- "errors"
- "unsafe"
- "golang.org/x/sys/unix"
- "github.com/shirou/gopsutil/internal/common"
- )
- func VirtualMemory() (*VirtualMemoryStat, error) {
- return VirtualMemoryWithContext(context.Background())
- }
- func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
- pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
- if err != nil {
- return nil, err
- }
- physmem, err := common.SysctlUint("hw.physmem")
- if err != nil {
- return nil, err
- }
- free, err := common.SysctlUint("vm.stats.vm.v_free_count")
- if err != nil {
- return nil, err
- }
- active, err := common.SysctlUint("vm.stats.vm.v_active_count")
- if err != nil {
- return nil, err
- }
- inactive, err := common.SysctlUint("vm.stats.vm.v_inactive_count")
- if err != nil {
- return nil, err
- }
- buffers, err := common.SysctlUint("vfs.bufspace")
- if err != nil {
- return nil, err
- }
- wired, err := common.SysctlUint("vm.stats.vm.v_wire_count")
- if err != nil {
- return nil, err
- }
- var cached, laundry uint64
- osreldate, _ := common.SysctlUint("kern.osreldate")
- if osreldate < 1102000 {
- cached, err = common.SysctlUint("vm.stats.vm.v_cache_count")
- if err != nil {
- return nil, err
- }
- } else {
- laundry, err = common.SysctlUint("vm.stats.vm.v_laundry_count")
- if err != nil {
- return nil, err
- }
- }
- p := pageSize
- ret := &VirtualMemoryStat{
- Total: physmem,
- Free: free * p,
- Active: active * p,
- Inactive: inactive * p,
- Cached: cached * p,
- Buffers: buffers,
- Wired: wired * p,
- Laundry: laundry * p,
- }
- ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry
- ret.Used = ret.Total - ret.Available
- ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
- return ret, nil
- }
- // Return swapinfo
- func SwapMemory() (*SwapMemoryStat, error) {
- return SwapMemoryWithContext(context.Background())
- }
- // Constants from vm/vm_param.h
- // nolint: golint
- const (
- XSWDEV_VERSION11 = 1
- XSWDEV_VERSION = 2
- )
- // Types from vm/vm_param.h
- type xswdev struct {
- Version uint32 // Version is the version
- Dev uint64 // Dev is the device identifier
- Flags int32 // Flags is the swap flags applied to the device
- NBlks int32 // NBlks is the total number of blocks
- Used int32 // Used is the number of blocks used
- }
- // xswdev11 is a compatibility for under FreeBSD 11
- // sys/vm/swap_pager.c
- type xswdev11 struct {
- Version uint32 // Version is the version
- Dev uint32 // Dev is the device identifier
- Flags int32 // Flags is the swap flags applied to the device
- NBlks int32 // NBlks is the total number of blocks
- Used int32 // Used is the number of blocks used
- }
- func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
- // FreeBSD can have multiple swap devices so we total them up
- i, err := common.SysctlUint("vm.nswapdev")
- if err != nil {
- return nil, err
- }
- if i == 0 {
- return nil, errors.New("no swap devices found")
- }
- c := int(i)
- i, err = common.SysctlUint("vm.stats.vm.v_page_size")
- if err != nil {
- return nil, err
- }
- pageSize := i
- var buf []byte
- s := &SwapMemoryStat{}
- for n := 0; n < c; n++ {
- buf, err = unix.SysctlRaw("vm.swap_info", n)
- if err != nil {
- return nil, err
- }
- // first, try to parse with version 2
- xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
- if xsw.Version == XSWDEV_VERSION11 {
- // this is version 1, so try to parse again
- xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
- if xsw.Version != XSWDEV_VERSION11 {
- return nil, errors.New("xswdev version mismatch(11)")
- }
- s.Total += uint64(xsw.NBlks)
- s.Used += uint64(xsw.Used)
- } else if xsw.Version != XSWDEV_VERSION {
- return nil, errors.New("xswdev version mismatch")
- } else {
- s.Total += uint64(xsw.NBlks)
- s.Used += uint64(xsw.Used)
- }
- }
- if s.Total != 0 {
- s.UsedPercent = float64(s.Used) / float64(s.Total) * 100
- }
- s.Total *= pageSize
- s.Used *= pageSize
- s.Free = s.Total - s.Used
- return s, nil
- }
|