cpu_openbsd.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //go:build openbsd
  2. // +build openbsd
  3. package cpu
  4. import (
  5. "context"
  6. "fmt"
  7. "runtime"
  8. "unsafe"
  9. "github.com/shirou/gopsutil/v3/internal/common"
  10. "github.com/tklauser/go-sysconf"
  11. "golang.org/x/sys/unix"
  12. )
  13. const (
  14. // sys/sched.h
  15. cpuOnline = 0x0001 // CPUSTATS_ONLINE
  16. // sys/sysctl.h
  17. ctlKern = 1 // "high kernel": proc, limits
  18. ctlHw = 6 // CTL_HW
  19. smt = 24 // HW_SMT
  20. kernCpTime = 40 // KERN_CPTIME
  21. kernCPUStats = 85 // KERN_CPUSTATS
  22. )
  23. var ClocksPerSec = float64(128)
  24. type cpuStats struct {
  25. // cs_time[CPUSTATES]
  26. User uint64
  27. Nice uint64
  28. Sys uint64
  29. Spin uint64
  30. Intr uint64
  31. Idle uint64
  32. // cs_flags
  33. Flags uint64
  34. }
  35. func init() {
  36. clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
  37. // ignore errors
  38. if err == nil {
  39. ClocksPerSec = float64(clkTck)
  40. }
  41. }
  42. func Times(percpu bool) ([]TimesStat, error) {
  43. return TimesWithContext(context.Background(), percpu)
  44. }
  45. func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
  46. if !percpu {
  47. mib := []int32{ctlKern, kernCpTime}
  48. buf, _, err := common.CallSyscall(mib)
  49. if err != nil {
  50. return ret, err
  51. }
  52. times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
  53. stat := TimesStat{
  54. CPU: "cpu-total",
  55. User: float64(times.User) / ClocksPerSec,
  56. Nice: float64(times.Nice) / ClocksPerSec,
  57. System: float64(times.Sys) / ClocksPerSec,
  58. Idle: float64(times.Idle) / ClocksPerSec,
  59. Irq: float64(times.Intr) / ClocksPerSec,
  60. }
  61. return []TimesStat{stat}, nil
  62. }
  63. ncpu, err := unix.SysctlUint32("hw.ncpu")
  64. if err != nil {
  65. return
  66. }
  67. var i uint32
  68. for i = 0; i < ncpu; i++ {
  69. mib := []int32{ctlKern, kernCPUStats, int32(i)}
  70. buf, _, err := common.CallSyscall(mib)
  71. if err != nil {
  72. return ret, err
  73. }
  74. stats := (*cpuStats)(unsafe.Pointer(&buf[0]))
  75. if (stats.Flags & cpuOnline) == 0 {
  76. continue
  77. }
  78. ret = append(ret, TimesStat{
  79. CPU: fmt.Sprintf("cpu%d", i),
  80. User: float64(stats.User) / ClocksPerSec,
  81. Nice: float64(stats.Nice) / ClocksPerSec,
  82. System: float64(stats.Sys) / ClocksPerSec,
  83. Idle: float64(stats.Idle) / ClocksPerSec,
  84. Irq: float64(stats.Intr) / ClocksPerSec,
  85. })
  86. }
  87. return ret, nil
  88. }
  89. // Returns only one (minimal) CPUInfoStat on OpenBSD
  90. func Info() ([]InfoStat, error) {
  91. return InfoWithContext(context.Background())
  92. }
  93. func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
  94. var ret []InfoStat
  95. var err error
  96. c := InfoStat{}
  97. mhz, err := unix.SysctlUint32("hw.cpuspeed")
  98. if err != nil {
  99. return nil, err
  100. }
  101. c.Mhz = float64(mhz)
  102. ncpu, err := unix.SysctlUint32("hw.ncpuonline")
  103. if err != nil {
  104. return nil, err
  105. }
  106. c.Cores = int32(ncpu)
  107. if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
  108. return nil, err
  109. }
  110. return append(ret, c), nil
  111. }
  112. func CountsWithContext(ctx context.Context, logical bool) (int, error) {
  113. return runtime.NumCPU(), nil
  114. }