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