mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
4683f588ce
The cgo in `meminfo_solaris.go` initializes variables in for loops, and therefore requires a `-std=c99` `CFLAG` in order to compile (at least on modern SmartOS). Signed-off-by: James Nugent <james@jen20.com>
129 lines
3.2 KiB
Go
129 lines
3.2 KiB
Go
// +build solaris,cgo
|
|
|
|
package system
|
|
|
|
import (
|
|
"fmt"
|
|
"unsafe"
|
|
)
|
|
|
|
// #cgo CFLAGS: -std=c99
|
|
// #cgo LDFLAGS: -lkstat
|
|
// #include <unistd.h>
|
|
// #include <stdlib.h>
|
|
// #include <stdio.h>
|
|
// #include <kstat.h>
|
|
// #include <sys/swap.h>
|
|
// #include <sys/param.h>
|
|
// struct swaptable *allocSwaptable(int num) {
|
|
// struct swaptable *st;
|
|
// struct swapent *swapent;
|
|
// st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int));
|
|
// swapent = st->swt_ent;
|
|
// for (int i = 0; i < num; i++,swapent++) {
|
|
// swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char));
|
|
// }
|
|
// st->swt_n = num;
|
|
// return st;
|
|
//}
|
|
// void freeSwaptable (struct swaptable *st) {
|
|
// struct swapent *swapent = st->swt_ent;
|
|
// for (int i = 0; i < st->swt_n; i++,swapent++) {
|
|
// free(swapent->ste_path);
|
|
// }
|
|
// free(st);
|
|
// }
|
|
// swapent_t getSwapEnt(swapent_t *ent, int i) {
|
|
// return ent[i];
|
|
// }
|
|
// int64_t getPpKernel() {
|
|
// int64_t pp_kernel = 0;
|
|
// kstat_ctl_t *ksc;
|
|
// kstat_t *ks;
|
|
// kstat_named_t *knp;
|
|
// kid_t kid;
|
|
//
|
|
// if ((ksc = kstat_open()) == NULL) {
|
|
// return -1;
|
|
// }
|
|
// if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) {
|
|
// return -1;
|
|
// }
|
|
// if (((kid = kstat_read(ksc, ks, NULL)) == -1) ||
|
|
// ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) {
|
|
// return -1;
|
|
// }
|
|
// switch (knp->data_type) {
|
|
// case KSTAT_DATA_UINT64:
|
|
// pp_kernel = knp->value.ui64;
|
|
// break;
|
|
// case KSTAT_DATA_UINT32:
|
|
// pp_kernel = knp->value.ui32;
|
|
// break;
|
|
// }
|
|
// pp_kernel *= sysconf(_SC_PAGESIZE);
|
|
// return (pp_kernel > 0 ? pp_kernel : -1);
|
|
// }
|
|
import "C"
|
|
|
|
// Get the system memory info using sysconf same as prtconf
|
|
func getTotalMem() int64 {
|
|
pagesize := C.sysconf(C._SC_PAGESIZE)
|
|
npages := C.sysconf(C._SC_PHYS_PAGES)
|
|
return int64(pagesize * npages)
|
|
}
|
|
|
|
func getFreeMem() int64 {
|
|
pagesize := C.sysconf(C._SC_PAGESIZE)
|
|
npages := C.sysconf(C._SC_AVPHYS_PAGES)
|
|
return int64(pagesize * npages)
|
|
}
|
|
|
|
// ReadMemInfo retrieves memory statistics of the host system and returns a
|
|
// MemInfo type.
|
|
func ReadMemInfo() (*MemInfo, error) {
|
|
|
|
ppKernel := C.getPpKernel()
|
|
MemTotal := getTotalMem()
|
|
MemFree := getFreeMem()
|
|
SwapTotal, SwapFree, err := getSysSwap()
|
|
|
|
if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 ||
|
|
SwapFree < 0 {
|
|
return nil, fmt.Errorf("error getting system memory info %v\n", err)
|
|
}
|
|
|
|
meminfo := &MemInfo{}
|
|
// Total memory is total physical memory less than memory locked by kernel
|
|
meminfo.MemTotal = MemTotal - int64(ppKernel)
|
|
meminfo.MemFree = MemFree
|
|
meminfo.SwapTotal = SwapTotal
|
|
meminfo.SwapFree = SwapFree
|
|
|
|
return meminfo, nil
|
|
}
|
|
|
|
func getSysSwap() (int64, int64, error) {
|
|
var tSwap int64
|
|
var fSwap int64
|
|
var diskblksPerPage int64
|
|
num, err := C.swapctl(C.SC_GETNSWP, nil)
|
|
if err != nil {
|
|
return -1, -1, err
|
|
}
|
|
st := C.allocSwaptable(num)
|
|
_, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st))
|
|
if err != nil {
|
|
C.freeSwaptable(st)
|
|
return -1, -1, err
|
|
}
|
|
|
|
diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT)
|
|
for i := 0; i < int(num); i++ {
|
|
swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i))
|
|
tSwap += int64(swapent.ste_pages) * diskblksPerPage
|
|
fSwap += int64(swapent.ste_free) * diskblksPerPage
|
|
}
|
|
C.freeSwaptable(st)
|
|
return tSwap, fSwap, nil
|
|
}
|