125 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build openbsd
 | 
						|
 | 
						|
package mem
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"context"
 | 
						|
	"encoding/binary"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"os/exec"
 | 
						|
 | 
						|
	"github.com/shirou/gopsutil/internal/common"
 | 
						|
)
 | 
						|
 | 
						|
func GetPageSize() (uint64, error) {
 | 
						|
	return GetPageSizeWithContext(context.Background())
 | 
						|
}
 | 
						|
 | 
						|
func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
 | 
						|
	mib := []int32{CTLVm, VmUvmexp}
 | 
						|
	buf, length, err := common.CallSyscall(mib)
 | 
						|
	if err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
	if length < sizeOfUvmexp {
 | 
						|
		return 0, fmt.Errorf("short syscall ret %d bytes", length)
 | 
						|
	}
 | 
						|
	var uvmexp Uvmexp
 | 
						|
	br := bytes.NewReader(buf)
 | 
						|
	err = common.Read(br, binary.LittleEndian, &uvmexp)
 | 
						|
	if err != nil {
 | 
						|
		return 0, err
 | 
						|
	}
 | 
						|
	return uint64(uvmexp.Pagesize), nil
 | 
						|
}
 | 
						|
 | 
						|
func VirtualMemory() (*VirtualMemoryStat, error) {
 | 
						|
	return VirtualMemoryWithContext(context.Background())
 | 
						|
}
 | 
						|
 | 
						|
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
 | 
						|
	mib := []int32{CTLVm, VmUvmexp}
 | 
						|
	buf, length, err := common.CallSyscall(mib)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if length < sizeOfUvmexp {
 | 
						|
		return nil, fmt.Errorf("short syscall ret %d bytes", length)
 | 
						|
	}
 | 
						|
	var uvmexp Uvmexp
 | 
						|
	br := bytes.NewReader(buf)
 | 
						|
	err = common.Read(br, binary.LittleEndian, &uvmexp)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	p := uint64(uvmexp.Pagesize)
 | 
						|
 | 
						|
	ret := &VirtualMemoryStat{
 | 
						|
		Total:    uint64(uvmexp.Npages) * p,
 | 
						|
		Free:     uint64(uvmexp.Free) * p,
 | 
						|
		Active:   uint64(uvmexp.Active) * p,
 | 
						|
		Inactive: uint64(uvmexp.Inactive) * p,
 | 
						|
		Cached:   0, // not available
 | 
						|
		Wired:    uint64(uvmexp.Wired) * p,
 | 
						|
	}
 | 
						|
 | 
						|
	ret.Available = ret.Inactive + ret.Cached + ret.Free
 | 
						|
	ret.Used = ret.Total - ret.Available
 | 
						|
	ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
 | 
						|
 | 
						|
	mib = []int32{CTLVfs, VfsGeneric, VfsBcacheStat}
 | 
						|
	buf, length, err = common.CallSyscall(mib)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if length < sizeOfBcachestats {
 | 
						|
		return nil, fmt.Errorf("short syscall ret %d bytes", length)
 | 
						|
	}
 | 
						|
	var bcs Bcachestats
 | 
						|
	br = bytes.NewReader(buf)
 | 
						|
	err = common.Read(br, binary.LittleEndian, &bcs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	ret.Buffers = uint64(bcs.Numbufpages) * p
 | 
						|
 | 
						|
	return ret, nil
 | 
						|
}
 | 
						|
 | 
						|
// Return swapctl summary info
 | 
						|
func SwapMemory() (*SwapMemoryStat, error) {
 | 
						|
	return SwapMemoryWithContext(context.Background())
 | 
						|
}
 | 
						|
 | 
						|
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
 | 
						|
	swapctl, err := exec.LookPath("swapctl")
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	out, err := invoke.CommandWithContext(ctx, swapctl, "-sk")
 | 
						|
	if err != nil {
 | 
						|
		return &SwapMemoryStat{}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	line := string(out)
 | 
						|
	var total, used, free uint64
 | 
						|
 | 
						|
	_, err = fmt.Sscanf(line,
 | 
						|
		"total: %d 1K-blocks allocated, %d used, %d available",
 | 
						|
		&total, &used, &free)
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.New("failed to parse swapctl output")
 | 
						|
	}
 | 
						|
 | 
						|
	percent := float64(used) / float64(total) * 100
 | 
						|
	return &SwapMemoryStat{
 | 
						|
		Total:       total * 1024,
 | 
						|
		Used:        used * 1024,
 | 
						|
		Free:        free * 1024,
 | 
						|
		UsedPercent: percent,
 | 
						|
	}, nil
 | 
						|
}
 |