mem_freebsd.go 3.2 KB

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