github.com/boomhut/fiber/v2@v2.0.0-20230603160335-b65c856e57d3/internal/gopsutil/cpu/cpu_openbsd.go (about) 1 //go:build openbsd 2 // +build openbsd 3 4 package cpu 5 6 import ( 7 "bytes" 8 "context" 9 "encoding/binary" 10 "fmt" 11 "os/exec" 12 "runtime" 13 "strconv" 14 "strings" 15 "syscall" 16 17 "github.com/boomhut/fiber/v2/internal/gopsutil/common" 18 "golang.org/x/sys/unix" 19 ) 20 21 // sys/sched.h 22 var ( 23 CPUser = 0 24 CPNice = 1 25 CPSys = 2 26 CPIntr = 3 27 CPIdle = 4 28 CPUStates = 5 29 ) 30 31 // sys/sysctl.h 32 const ( 33 CTLKern = 1 // "high kernel": proc, limits 34 CTLHw = 6 // CTL_HW 35 SMT = 24 // HW_SMT 36 KernCptime = 40 // KERN_CPTIME 37 KernCptime2 = 71 // KERN_CPTIME2 38 ) 39 40 var ClocksPerSec = float64(128) 41 42 func init() { 43 func() { 44 getconf, err := exec.LookPath("getconf") 45 if err != nil { 46 return 47 } 48 out, err := invoke.Command(getconf, "CLK_TCK") 49 // ignore errors 50 if err == nil { 51 i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64) 52 if err == nil { 53 ClocksPerSec = float64(i) 54 } 55 } 56 }() 57 func() { 58 v, err := unix.Sysctl("kern.osrelease") // can't reuse host.PlatformInformation because of circular import 59 if err != nil { 60 return 61 } 62 v = strings.ToLower(v) 63 version, err := strconv.ParseFloat(v, 64) 64 if err != nil { 65 return 66 } 67 if version >= 6.4 { 68 CPIntr = 4 69 CPIdle = 5 70 CPUStates = 6 71 } 72 }() 73 } 74 75 func smt() (bool, error) { 76 mib := []int32{CTLHw, SMT} 77 buf, _, err := common.CallSyscall(mib) 78 if err != nil { 79 return false, err 80 } 81 82 var ret bool 83 br := bytes.NewReader(buf) 84 if err := binary.Read(br, binary.LittleEndian, &ret); err != nil { 85 return false, err 86 } 87 88 return ret, nil 89 } 90 91 func Times(percpu bool) ([]TimesStat, error) { 92 return TimesWithContext(context.Background(), percpu) 93 } 94 95 func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { 96 var ret []TimesStat 97 98 var ncpu int 99 if percpu { 100 ncpu, _ = Counts(true) 101 } else { 102 ncpu = 1 103 } 104 105 smt, err := smt() 106 if err == syscall.EOPNOTSUPP { 107 // if hw.smt is not applicable for this platform (e.g. i386), 108 // pretend it's enabled 109 smt = true 110 } else if err != nil { 111 return nil, err 112 } 113 114 for i := 0; i < ncpu; i++ { 115 j := i 116 if !smt { 117 j *= 2 118 } 119 120 var cpuTimes = make([]int32, CPUStates) 121 var mib []int32 122 if percpu { 123 mib = []int32{CTLKern, KernCptime2, int32(j)} 124 } else { 125 mib = []int32{CTLKern, KernCptime} 126 } 127 buf, _, err := common.CallSyscall(mib) 128 if err != nil { 129 return ret, err 130 } 131 132 br := bytes.NewReader(buf) 133 err = binary.Read(br, binary.LittleEndian, &cpuTimes) 134 if err != nil { 135 return ret, err 136 } 137 c := TimesStat{ 138 User: float64(cpuTimes[CPUser]) / ClocksPerSec, 139 Nice: float64(cpuTimes[CPNice]) / ClocksPerSec, 140 System: float64(cpuTimes[CPSys]) / ClocksPerSec, 141 Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec, 142 Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec, 143 } 144 if percpu { 145 c.CPU = fmt.Sprintf("cpu%d", j) 146 } else { 147 c.CPU = "cpu-total" 148 } 149 ret = append(ret, c) 150 } 151 152 return ret, nil 153 } 154 155 // Returns only one (minimal) CPUInfoStat on OpenBSD 156 func Info() ([]InfoStat, error) { 157 return InfoWithContext(context.Background()) 158 } 159 160 func InfoWithContext(ctx context.Context) ([]InfoStat, error) { 161 var ret []InfoStat 162 var err error 163 164 c := InfoStat{} 165 166 mhz, err := unix.SysctlUint32("hw.cpuspeed") 167 if err != nil { 168 return nil, err 169 } 170 c.Mhz = float64(mhz) 171 172 ncpu, err := unix.SysctlUint32("hw.ncpuonline") 173 if err != nil { 174 return nil, err 175 } 176 c.Cores = int32(ncpu) 177 178 if c.ModelName, err = unix.Sysctl("hw.model"); err != nil { 179 return nil, err 180 } 181 182 return append(ret, c), nil 183 } 184 185 func CountsWithContext(ctx context.Context, logical bool) (int, error) { 186 return runtime.NumCPU(), nil 187 }