1// +build openbsd 2 3package mem 4 5import ( 6 "bytes" 7 "context" 8 "encoding/binary" 9 "errors" 10 "fmt" 11 "os/exec" 12 13 "github.com/shirou/gopsutil/internal/common" 14) 15 16func GetPageSize() (uint64, error) { 17 return GetPageSizeWithContext(context.Background()) 18} 19 20func GetPageSizeWithContext(ctx context.Context) (uint64, error) { 21 mib := []int32{CTLVm, VmUvmexp} 22 buf, length, err := common.CallSyscall(mib) 23 if err != nil { 24 return 0, err 25 } 26 if length < sizeOfUvmexp { 27 return 0, fmt.Errorf("short syscall ret %d bytes", length) 28 } 29 var uvmexp Uvmexp 30 br := bytes.NewReader(buf) 31 err = common.Read(br, binary.LittleEndian, &uvmexp) 32 if err != nil { 33 return 0, err 34 } 35 return uint64(uvmexp.Pagesize), nil 36} 37 38func VirtualMemory() (*VirtualMemoryStat, error) { 39 return VirtualMemoryWithContext(context.Background()) 40} 41 42func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { 43 mib := []int32{CTLVm, VmUvmexp} 44 buf, length, err := common.CallSyscall(mib) 45 if err != nil { 46 return nil, err 47 } 48 if length < sizeOfUvmexp { 49 return nil, fmt.Errorf("short syscall ret %d bytes", length) 50 } 51 var uvmexp Uvmexp 52 br := bytes.NewReader(buf) 53 err = common.Read(br, binary.LittleEndian, &uvmexp) 54 if err != nil { 55 return nil, err 56 } 57 p := uint64(uvmexp.Pagesize) 58 59 ret := &VirtualMemoryStat{ 60 Total: uint64(uvmexp.Npages) * p, 61 Free: uint64(uvmexp.Free) * p, 62 Active: uint64(uvmexp.Active) * p, 63 Inactive: uint64(uvmexp.Inactive) * p, 64 Cached: 0, // not available 65 Wired: uint64(uvmexp.Wired) * p, 66 } 67 68 ret.Available = ret.Inactive + ret.Cached + ret.Free 69 ret.Used = ret.Total - ret.Available 70 ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0 71 72 mib = []int32{CTLVfs, VfsGeneric, VfsBcacheStat} 73 buf, length, err = common.CallSyscall(mib) 74 if err != nil { 75 return nil, err 76 } 77 if length < sizeOfBcachestats { 78 return nil, fmt.Errorf("short syscall ret %d bytes", length) 79 } 80 var bcs Bcachestats 81 br = bytes.NewReader(buf) 82 err = common.Read(br, binary.LittleEndian, &bcs) 83 if err != nil { 84 return nil, err 85 } 86 ret.Buffers = uint64(bcs.Numbufpages) * p 87 88 return ret, nil 89} 90 91// Return swapctl summary info 92func SwapMemory() (*SwapMemoryStat, error) { 93 return SwapMemoryWithContext(context.Background()) 94} 95 96func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { 97 swapctl, err := exec.LookPath("swapctl") 98 if err != nil { 99 return nil, err 100 } 101 102 out, err := invoke.CommandWithContext(ctx, swapctl, "-sk") 103 if err != nil { 104 return &SwapMemoryStat{}, nil 105 } 106 107 line := string(out) 108 var total, used, free uint64 109 110 _, err = fmt.Sscanf(line, 111 "total: %d 1K-blocks allocated, %d used, %d available", 112 &total, &used, &free) 113 if err != nil { 114 return nil, errors.New("failed to parse swapctl output") 115 } 116 117 percent := float64(used) / float64(total) * 100 118 return &SwapMemoryStat{ 119 Total: total * 1024, 120 Used: used * 1024, 121 Free: free * 1024, 122 UsedPercent: percent, 123 }, nil 124} 125