github.com/elastic/gosigar@v0.14.3/sigar_openbsd.go (about)

     1  // Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>.
     2  
     3  // +build openbsd
     4  
     5  package gosigar
     6  
     7  /*
     8  #include <sys/param.h>
     9  #include <sys/types.h>
    10  #include <sys/sysctl.h>
    11  #include <sys/mount.h>
    12  #include <sys/sched.h>
    13  #include <sys/swap.h>
    14  #include <stdlib.h>
    15  #include <unistd.h>
    16  */
    17  import "C"
    18  
    19  //import "github.com/davecgh/go-spew/spew"
    20  
    21  import (
    22  	"runtime"
    23  	"syscall"
    24  	"time"
    25  	"unsafe"
    26  )
    27  
    28  type Uvmexp struct {
    29  	pagesize           uint32
    30  	pagemask           uint32
    31  	pageshift          uint32
    32  	npages             uint32
    33  	free               uint32
    34  	active             uint32
    35  	inactive           uint32
    36  	paging             uint32
    37  	wired              uint32
    38  	zeropages          uint32
    39  	reserve_pagedaemon uint32
    40  	reserve_kernel     uint32
    41  	anonpages          uint32
    42  	vnodepages         uint32
    43  	vtextpages         uint32
    44  	freemin            uint32
    45  	freetarg           uint32
    46  	inactarg           uint32
    47  	wiredmax           uint32
    48  	anonmin            uint32
    49  	vtextmin           uint32
    50  	vnodemin           uint32
    51  	anonminpct         uint32
    52  	vtextmi            uint32
    53  	npct               uint32
    54  	vnodeminpct        uint32
    55  	nswapdev           uint32
    56  	swpages            uint32
    57  	swpginuse          uint32
    58  	swpgonly           uint32
    59  	nswget             uint32
    60  	nanon              uint32
    61  	nanonneeded        uint32
    62  	nfreeanon          uint32
    63  	faults             uint32
    64  	traps              uint32
    65  	intrs              uint32
    66  	swtch              uint32
    67  	softs              uint32
    68  	syscalls           uint32
    69  	pageins            uint32
    70  	obsolete_swapins   uint32
    71  	obsolete_swapouts  uint32
    72  	pgswapin           uint32
    73  	pgswapout          uint32
    74  	forks              uint32
    75  	forks_ppwait       uint32
    76  	forks_sharevm      uint32
    77  	pga_zerohit        uint32
    78  	pga_zeromiss       uint32
    79  	zeroaborts         uint32
    80  	fltnoram           uint32
    81  	fltnoanon          uint32
    82  	fltpgwait          uint32
    83  	fltpgrele          uint32
    84  	fltrelck           uint32
    85  	fltrelckok         uint32
    86  	fltanget           uint32
    87  	fltanretry         uint32
    88  	fltamcopy          uint32
    89  	fltnamap           uint32
    90  	fltnomap           uint32
    91  	fltlget            uint32
    92  	fltget             uint32
    93  	flt_anon           uint32
    94  	flt_acow           uint32
    95  	flt_obj            uint32
    96  	flt_prcopy         uint32
    97  	flt_przero         uint32
    98  	pdwoke             uint32
    99  	pdrevs             uint32
   100  	pdswout            uint32
   101  	pdfreed            uint32
   102  	pdscans            uint32
   103  	pdanscan           uint32
   104  	pdobscan           uint32
   105  	pdreact            uint32
   106  	pdbusy             uint32
   107  	pdpageouts         uint32
   108  	pdpending          uint32
   109  	pddeact            uint32
   110  	pdreanon           uint32
   111  	pdrevnode          uint32
   112  	pdrevtext          uint32
   113  	fpswtch            uint32
   114  	kmapent            uint32
   115  }
   116  
   117  type Bcachestats struct {
   118  	numbufs        uint64
   119  	numbufpages    uint64
   120  	numdirtypages  uint64
   121  	numcleanpages  uint64
   122  	pendingwrites  uint64
   123  	pendingreads   uint64
   124  	numwrites      uint64
   125  	numreads       uint64
   126  	cachehits      uint64
   127  	busymapped     uint64
   128  	dmapages       uint64
   129  	highpages      uint64
   130  	delwribufs     uint64
   131  	kvaslots       uint64
   132  	kvaslots_avail uint64
   133  }
   134  
   135  type Swapent struct {
   136  	se_dev      C.dev_t
   137  	se_flags    int32
   138  	se_nblks    int32
   139  	se_inuse    int32
   140  	se_priority int32
   141  	sw_path     []byte
   142  }
   143  
   144  func (self *FileSystemList) Get() error {
   145  	num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT)
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	buf := make([]syscall.Statfs_t, num)
   151  
   152  	_, err = syscall.Getfsstat(buf, C.MNT_NOWAIT)
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	fslist := make([]FileSystem, 0, num)
   158  
   159  	for i := 0; i < num; i++ {
   160  		fs := FileSystem{}
   161  
   162  		fs.DirName = byteListToString(buf[i].F_mntonname[:])
   163  		fs.DevName = byteListToString(buf[i].F_mntfromname[:])
   164  		fs.SysTypeName = byteListToString(buf[i].F_fstypename[:])
   165  
   166  		fslist = append(fslist, fs)
   167  	}
   168  
   169  	self.List = fslist
   170  
   171  	return err
   172  }
   173  
   174  func (self *FileSystemUsage) Get(path string) error {
   175  	stat := syscall.Statfs_t{}
   176  	err := syscall.Statfs(path, &stat)
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	self.Total = uint64(stat.F_blocks) * uint64(stat.F_bsize)
   182  	self.Free = uint64(stat.F_bfree) * uint64(stat.F_bsize)
   183  	self.Avail = uint64(stat.F_bavail) * uint64(stat.F_bsize)
   184  	self.Used = self.Total - self.Free
   185  	self.Files = stat.F_files
   186  	self.FreeFiles = stat.F_ffree
   187  
   188  	return nil
   189  }
   190  
   191  func (self *FDUsage) Get() error {
   192  	return ErrNotImplemented{runtime.GOOS}
   193  }
   194  
   195  func (self *LoadAverage) Get() error {
   196  	avg := []C.double{0, 0, 0}
   197  
   198  	C.getloadavg(&avg[0], C.int(len(avg)))
   199  
   200  	self.One = float64(avg[0])
   201  	self.Five = float64(avg[1])
   202  	self.Fifteen = float64(avg[2])
   203  
   204  	return nil
   205  }
   206  
   207  func (self *Uptime) Get() error {
   208  	tv := syscall.Timeval{}
   209  	mib := [2]int32{C.CTL_KERN, C.KERN_BOOTTIME}
   210  
   211  	n := uintptr(0)
   212  	// First we determine how much memory we'll need to pass later on (via `n`)
   213  	_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   214  
   215  	if errno != 0 || n == 0 {
   216  		return nil
   217  	}
   218  
   219  	// Now perform the actual sysctl(3) call, storing the result in tv
   220  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&tv)), uintptr(unsafe.Pointer(&n)), 0, 0)
   221  
   222  	if errno != 0 || n == 0 {
   223  		return nil
   224  	}
   225  
   226  	self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
   227  
   228  	return nil
   229  }
   230  
   231  func (self *Mem) Get() error {
   232  	n := uintptr(0)
   233  
   234  	var uvmexp Uvmexp
   235  	mib := [2]int32{C.CTL_VM, C.VM_UVMEXP}
   236  	n = uintptr(0)
   237  	// First we determine how much memory we'll need to pass later on (via `n`)
   238  	_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   239  	if errno != 0 || n == 0 {
   240  		return nil
   241  	}
   242  
   243  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&uvmexp)), uintptr(unsafe.Pointer(&n)), 0, 0)
   244  	if errno != 0 || n == 0 {
   245  		return nil
   246  	}
   247  
   248  	var bcachestats Bcachestats
   249  	mib3 := [3]int32{C.CTL_VFS, C.VFS_GENERIC, C.VFS_BCACHESTAT}
   250  	n = uintptr(0)
   251  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   252  	if errno != 0 || n == 0 {
   253  		return nil
   254  	}
   255  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, uintptr(unsafe.Pointer(&bcachestats)), uintptr(unsafe.Pointer(&n)), 0, 0)
   256  	if errno != 0 || n == 0 {
   257  		return nil
   258  	}
   259  
   260  	self.Total = uint64(uvmexp.npages) << uvmexp.pageshift
   261  	self.Used = uint64(uvmexp.npages-uvmexp.free) << uvmexp.pageshift
   262  	self.Free = uint64(uvmexp.free) << uvmexp.pageshift
   263  
   264  	self.ActualFree = self.Free + (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
   265  	self.ActualUsed = self.Used - (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
   266  
   267  	return nil
   268  }
   269  
   270  func (self *Swap) Get() error {
   271  	nswap := C.swapctl(C.SWAP_NSWAP, unsafe.Pointer(uintptr(0)), 0)
   272  
   273  	// If there are no swap devices, nothing to do here.
   274  	if nswap == 0 {
   275  		return nil
   276  	}
   277  
   278  	swdev := make([]Swapent, nswap)
   279  
   280  	rnswap := C.swapctl(C.SWAP_STATS, unsafe.Pointer(&swdev[0]), nswap)
   281  	if rnswap == 0 {
   282  		return nil
   283  	}
   284  
   285  	for i := 0; i < int(nswap); i++ {
   286  		if swdev[i].se_flags&C.SWF_ENABLE == 2 {
   287  			self.Used = self.Used + uint64(swdev[i].se_inuse/(1024/C.DEV_BSIZE))
   288  			self.Total = self.Total + uint64(swdev[i].se_nblks/(1024/C.DEV_BSIZE))
   289  		}
   290  	}
   291  
   292  	self.Free = self.Total - self.Used
   293  
   294  	return nil
   295  }
   296  
   297  func (self *HugeTLBPages) Get() error {
   298  	return ErrNotImplemented{runtime.GOOS}
   299  }
   300  
   301  func (self *Cpu) Get() error {
   302  	load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
   303  
   304  	mib := [2]int32{C.CTL_KERN, C.KERN_CPTIME}
   305  	n := uintptr(0)
   306  	// First we determine how much memory we'll need to pass later on (via `n`)
   307  	_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   308  	if errno != 0 || n == 0 {
   309  		return nil
   310  	}
   311  
   312  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&load)), uintptr(unsafe.Pointer(&n)), 0, 0)
   313  	if errno != 0 || n == 0 {
   314  		return nil
   315  	}
   316  
   317  	self.User = uint64(load[0])
   318  	self.Nice = uint64(load[1])
   319  	self.Sys = uint64(load[2])
   320  	self.Irq = uint64(load[3])
   321  	self.Idle = uint64(load[4])
   322  
   323  	return nil
   324  }
   325  
   326  func (self *CpuList) Get() error {
   327  	mib := [2]int32{C.CTL_HW, C.HW_NCPU}
   328  	var ncpu int
   329  
   330  	n := uintptr(0)
   331  	// First we determine how much memory we'll need to pass later on (via `n`)
   332  	_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   333  
   334  	if errno != 0 || n == 0 {
   335  		return nil
   336  	}
   337  
   338  	// Now perform the actual sysctl(3) call, storing the result in ncpu
   339  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&ncpu)), uintptr(unsafe.Pointer(&n)), 0, 0)
   340  
   341  	if errno != 0 || n == 0 {
   342  		return nil
   343  	}
   344  
   345  	load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
   346  
   347  	self.List = make([]Cpu, ncpu)
   348  	for curcpu := range self.List {
   349  		sysctlCptime(ncpu, curcpu, &load)
   350  		fillCpu(&self.List[curcpu], load)
   351  	}
   352  
   353  	return nil
   354  }
   355  
   356  func (self *ProcList) Get() error {
   357  	return nil
   358  }
   359  
   360  func (self *ProcArgs) Get(pid int) error {
   361  	return nil
   362  }
   363  
   364  func (self *ProcEnv) Get(pid int) error {
   365  	return ErrNotImplemented{runtime.GOOS}
   366  }
   367  
   368  func (self *ProcState) Get(pid int) error {
   369  	return nil
   370  }
   371  
   372  func (self *ProcMem) Get(pid int) error {
   373  	return nil
   374  }
   375  
   376  func (self *ProcTime) Get(pid int) error {
   377  	return ErrNotImplemented{runtime.GOOS}
   378  }
   379  
   380  func (self *ProcExe) Get(pid int) error {
   381  	return nil
   382  }
   383  
   384  func (self *ProcFDUsage) Get(pid int) error {
   385  	return ErrNotImplemented{runtime.GOOS}
   386  }
   387  
   388  func (self *Rusage) Get(pid int) error {
   389  	return ErrNotImplemented{runtime.GOOS}
   390  }
   391  
   392  func fillCpu(cpu *Cpu, load [C.CPUSTATES]C.long) {
   393  	cpu.User = uint64(load[0])
   394  	cpu.Nice = uint64(load[1])
   395  	cpu.Sys = uint64(load[2])
   396  	cpu.Irq = uint64(load[3])
   397  	cpu.Idle = uint64(load[4])
   398  }
   399  
   400  func sysctlCptime(ncpu int, curcpu int, load *[C.CPUSTATES]C.long) error {
   401  	var mib []int32
   402  
   403  	// Use the correct mib based on the number of CPUs and fill out the
   404  	// current CPU number in case of SMP. (0 indexed cf. self.List)
   405  	if ncpu == 0 {
   406  		mib = []int32{C.CTL_KERN, C.KERN_CPTIME}
   407  	} else {
   408  		mib = []int32{C.CTL_KERN, C.KERN_CPTIME2, int32(curcpu)}
   409  	}
   410  
   411  	len := len(mib)
   412  
   413  	n := uintptr(0)
   414  	// First we determine how much memory we'll need to pass later on (via `n`)
   415  	_, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), 0, uintptr(unsafe.Pointer(&n)), 0, 0)
   416  	if errno != 0 || n == 0 {
   417  		return nil
   418  	}
   419  
   420  	_, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), uintptr(unsafe.Pointer(load)), uintptr(unsafe.Pointer(&n)), 0, 0)
   421  	if errno != 0 || n == 0 {
   422  		return nil
   423  	}
   424  
   425  	return nil
   426  }