...

Source file src/github.com/shirou/gopsutil/mem/mem_freebsd.go

Documentation: github.com/shirou/gopsutil/mem

     1  // +build freebsd
     2  
     3  package mem
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"unsafe"
     9  
    10  	"golang.org/x/sys/unix"
    11  
    12  	"github.com/shirou/gopsutil/internal/common"
    13  )
    14  
    15  func VirtualMemory() (*VirtualMemoryStat, error) {
    16  	return VirtualMemoryWithContext(context.Background())
    17  }
    18  
    19  func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
    20  	pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	physmem, err := common.SysctlUint("hw.physmem")
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	free, err := common.SysctlUint("vm.stats.vm.v_free_count")
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	active, err := common.SysctlUint("vm.stats.vm.v_active_count")
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	inactive, err := common.SysctlUint("vm.stats.vm.v_inactive_count")
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	buffers, err := common.SysctlUint("vfs.bufspace")
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	wired, err := common.SysctlUint("vm.stats.vm.v_wire_count")
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	var cached, laundry uint64
    50  	osreldate, _ := common.SysctlUint("kern.osreldate")
    51  	if osreldate < 1102000 {
    52  		cached, err = common.SysctlUint("vm.stats.vm.v_cache_count")
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  	} else {
    57  		laundry, err = common.SysctlUint("vm.stats.vm.v_laundry_count")
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  
    63  	p := pageSize
    64  	ret := &VirtualMemoryStat{
    65  		Total:    physmem,
    66  		Free:     free * p,
    67  		Active:   active * p,
    68  		Inactive: inactive * p,
    69  		Cached:   cached * p,
    70  		Buffers:  buffers,
    71  		Wired:    wired * p,
    72  		Laundry:  laundry * p,
    73  	}
    74  
    75  	ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry
    76  	ret.Used = ret.Total - ret.Available
    77  	ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
    78  
    79  	return ret, nil
    80  }
    81  
    82  // Return swapinfo
    83  func SwapMemory() (*SwapMemoryStat, error) {
    84  	return SwapMemoryWithContext(context.Background())
    85  }
    86  
    87  // Constants from vm/vm_param.h
    88  // nolint: golint
    89  const (
    90  	XSWDEV_VERSION11 = 1
    91  	XSWDEV_VERSION   = 2
    92  )
    93  
    94  // Types from vm/vm_param.h
    95  type xswdev struct {
    96  	Version uint32 // Version is the version
    97  	Dev     uint64 // Dev is the device identifier
    98  	Flags   int32  // Flags is the swap flags applied to the device
    99  	NBlks   int32  // NBlks is the total number of blocks
   100  	Used    int32  // Used is the number of blocks used
   101  }
   102  
   103  // xswdev11 is a compatibility for under FreeBSD 11
   104  // sys/vm/swap_pager.c
   105  type xswdev11 struct {
   106  	Version uint32 // Version is the version
   107  	Dev     uint32 // Dev is the device identifier
   108  	Flags   int32  // Flags is the swap flags applied to the device
   109  	NBlks   int32  // NBlks is the total number of blocks
   110  	Used    int32  // Used is the number of blocks used
   111  }
   112  
   113  func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
   114  	// FreeBSD can have multiple swap devices so we total them up
   115  	i, err := common.SysctlUint("vm.nswapdev")
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	if i == 0 {
   121  		return nil, errors.New("no swap devices found")
   122  	}
   123  
   124  	c := int(i)
   125  
   126  	i, err = common.SysctlUint("vm.stats.vm.v_page_size")
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	pageSize := i
   131  
   132  	var buf []byte
   133  	s := &SwapMemoryStat{}
   134  	for n := 0; n < c; n++ {
   135  		buf, err = unix.SysctlRaw("vm.swap_info", n)
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  
   140  		// first, try to parse with version 2
   141  		xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
   142  		if xsw.Version == XSWDEV_VERSION11 {
   143  			// this is version 1, so try to parse again
   144  			xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
   145  			if xsw.Version != XSWDEV_VERSION11 {
   146  				return nil, errors.New("xswdev version mismatch(11)")
   147  			}
   148  			s.Total += uint64(xsw.NBlks)
   149  			s.Used += uint64(xsw.Used)
   150  		} else if xsw.Version != XSWDEV_VERSION {
   151  			return nil, errors.New("xswdev version mismatch")
   152  		} else {
   153  			s.Total += uint64(xsw.NBlks)
   154  			s.Used += uint64(xsw.Used)
   155  		}
   156  
   157  	}
   158  
   159  	if s.Total != 0 {
   160  		s.UsedPercent = float64(s.Used) / float64(s.Total) * 100
   161  	}
   162  	s.Total *= pageSize
   163  	s.Used *= pageSize
   164  	s.Free = s.Total - s.Used
   165  
   166  	return s, nil
   167  }
   168  

View as plain text