github.com/cdoern/storage@v1.12.13/pkg/system/meminfo_solaris.go (about)

     1  // +build solaris,cgo
     2  
     3  package system
     4  
     5  import (
     6  	"fmt"
     7  	"unsafe"
     8  )
     9  
    10  // #cgo CFLAGS: -std=c99
    11  // #cgo LDFLAGS: -lkstat
    12  // #include <unistd.h>
    13  // #include <stdlib.h>
    14  // #include <stdio.h>
    15  // #include <kstat.h>
    16  // #include <sys/swap.h>
    17  // #include <sys/param.h>
    18  // struct swaptable *allocSwaptable(int num) {
    19  //	struct swaptable *st;
    20  //	struct swapent *swapent;
    21  // 	st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int));
    22  //	swapent = st->swt_ent;
    23  //	for (int i = 0; i < num; i++,swapent++) {
    24  //		swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char));
    25  //	}
    26  //	st->swt_n = num;
    27  //	return st;
    28  //}
    29  // void freeSwaptable (struct swaptable *st) {
    30  //	struct swapent *swapent = st->swt_ent;
    31  //	for (int i = 0; i < st->swt_n; i++,swapent++) {
    32  //		free(swapent->ste_path);
    33  //	}
    34  //	free(st);
    35  // }
    36  // swapent_t getSwapEnt(swapent_t *ent, int i) {
    37  //	return ent[i];
    38  // }
    39  // int64_t getPpKernel() {
    40  //	int64_t pp_kernel = 0;
    41  //	kstat_ctl_t *ksc;
    42  //	kstat_t *ks;
    43  //	kstat_named_t *knp;
    44  //	kid_t kid;
    45  //
    46  //	if ((ksc = kstat_open()) == NULL) {
    47  //		return -1;
    48  //	}
    49  //	if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) {
    50  //		return -1;
    51  //	}
    52  //	if (((kid = kstat_read(ksc, ks, NULL)) == -1) ||
    53  //	    ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) {
    54  //		return -1;
    55  //	}
    56  //	switch (knp->data_type) {
    57  //	case KSTAT_DATA_UINT64:
    58  //		pp_kernel = knp->value.ui64;
    59  //		break;
    60  //	case KSTAT_DATA_UINT32:
    61  //		pp_kernel = knp->value.ui32;
    62  //		break;
    63  //	}
    64  //	pp_kernel *= sysconf(_SC_PAGESIZE);
    65  //	return (pp_kernel > 0 ? pp_kernel : -1);
    66  // }
    67  import "C"
    68  
    69  // Get the system memory info using sysconf same as prtconf
    70  func getTotalMem() int64 {
    71  	pagesize := C.sysconf(C._SC_PAGESIZE)
    72  	npages := C.sysconf(C._SC_PHYS_PAGES)
    73  	return int64(pagesize * npages)
    74  }
    75  
    76  func getFreeMem() int64 {
    77  	pagesize := C.sysconf(C._SC_PAGESIZE)
    78  	npages := C.sysconf(C._SC_AVPHYS_PAGES)
    79  	return int64(pagesize * npages)
    80  }
    81  
    82  // ReadMemInfo retrieves memory statistics of the host system and returns a
    83  //  MemInfo type.
    84  func ReadMemInfo() (*MemInfo, error) {
    85  
    86  	ppKernel := C.getPpKernel()
    87  	MemTotal := getTotalMem()
    88  	MemFree := getFreeMem()
    89  	SwapTotal, SwapFree, err := getSysSwap()
    90  
    91  	if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 ||
    92  		SwapFree < 0 {
    93  		return nil, fmt.Errorf("error getting system memory info %v\n", err)
    94  	}
    95  
    96  	meminfo := &MemInfo{}
    97  	// Total memory is total physical memory less than memory locked by kernel
    98  	meminfo.MemTotal = MemTotal - int64(ppKernel)
    99  	meminfo.MemFree = MemFree
   100  	meminfo.SwapTotal = SwapTotal
   101  	meminfo.SwapFree = SwapFree
   102  
   103  	return meminfo, nil
   104  }
   105  
   106  func getSysSwap() (int64, int64, error) {
   107  	var tSwap int64
   108  	var fSwap int64
   109  	var diskblksPerPage int64
   110  	num, err := C.swapctl(C.SC_GETNSWP, nil)
   111  	if err != nil {
   112  		return -1, -1, err
   113  	}
   114  	st := C.allocSwaptable(num)
   115  	_, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st))
   116  	if err != nil {
   117  		C.freeSwaptable(st)
   118  		return -1, -1, err
   119  	}
   120  
   121  	diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT)
   122  	for i := 0; i < int(num); i++ {
   123  		swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i))
   124  		tSwap += int64(swapent.ste_pages) * diskblksPerPage
   125  		fSwap += int64(swapent.ste_free) * diskblksPerPage
   126  	}
   127  	C.freeSwaptable(st)
   128  	return tSwap, fSwap, nil
   129  }