sigar_openbsd.go 11 KB

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