github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/sys/mem_darwin.go (about)

     1  // Package sys provides methods to read system information
     2  /*
     3   * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package sys
     6  
     7  /*
     8  #include <mach/mach_host.h>
     9  */
    10  import "C" //nolint:gci,gocritic // super weird case
    11  
    12  import (
    13  	"bytes"
    14  	"encoding/binary"
    15  	"errors"
    16  	"fmt"
    17  	"syscall"
    18  	"unsafe" //nolint:gocritic // super weird case
    19  )
    20  
    21  type (
    22  	swapStats struct {
    23  		Total uint64
    24  		Free  uint64
    25  		Used  uint64
    26  	}
    27  )
    28  
    29  func readSysctl(name string, data any) (err error) {
    30  	value, err := syscall.Sysctl(name)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	buf := []byte(value)
    36  
    37  	switch v := data.(type) {
    38  	case *uint64:
    39  		*v = *(*uint64)(unsafe.Pointer(&buf[0]))
    40  		return
    41  	default:
    42  		b := bytes.NewBuffer(buf)
    43  		return binary.Read(b, binary.LittleEndian, data)
    44  	}
    45  }
    46  
    47  func readTotalMemory() (uint64, error) {
    48  	var totalMem uint64
    49  	if err := readSysctl("hw.memsize", &totalMem); err != nil {
    50  		return 0, err
    51  	}
    52  	return totalMem, nil
    53  }
    54  
    55  func readVMStat(vmstat *C.vm_statistics_data_t) error {
    56  	var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT
    57  	status := C.host_statistics(
    58  		C.mach_host_self(),
    59  		C.HOST_VM_INFO,
    60  		C.host_info_t(unsafe.Pointer(vmstat)),
    61  		&count,
    62  	)
    63  	if status != C.KERN_SUCCESS {
    64  		return fmt.Errorf("host_statistics=%v", status)
    65  	}
    66  	return nil
    67  }
    68  
    69  func (mem *MemStat) host() error {
    70  	totalMem, err := readTotalMemory()
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	var vmstat C.vm_statistics_data_t
    76  	if err := readVMStat(&vmstat); err != nil {
    77  		return err
    78  	}
    79  
    80  	var (
    81  		sstats   = swapStats{}
    82  		pageSize = uint64(1 << 12)
    83  		freeMem  = uint64(vmstat.free_count) * pageSize
    84  		kern     = uint64(vmstat.inactive_count) * pageSize
    85  	)
    86  	if err := readSysctl("vm.swapusage", &sstats); err != nil {
    87  		return err
    88  	}
    89  	{
    90  		mem.Total = totalMem
    91  		mem.Free = freeMem
    92  		mem.Used = totalMem - freeMem
    93  		mem.ActualFree = freeMem + kern
    94  		mem.ActualUsed = totalMem - freeMem - kern
    95  		mem.SwapTotal = sstats.Total
    96  		mem.SwapFree = sstats.Free
    97  		mem.SwapUsed = sstats.Used
    98  	}
    99  	return nil
   100  }
   101  
   102  func (*MemStat) container() error { return errors.New("Darwin: cannot get container memory stats") }