123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- package cpu
- import (
- "context"
- "errors"
- "fmt"
- "os/exec"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "github.com/shirou/gopsutil/internal/common"
- )
- var ClocksPerSec = float64(128)
- func init() {
- getconf, err := exec.LookPath("/usr/bin/getconf")
- if err != nil {
- return
- }
- out, err := invoke.Command(getconf, "CLK_TCK")
- // ignore errors
- if err == nil {
- i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
- if err == nil {
- ClocksPerSec = float64(i)
- }
- }
- }
- func Times(percpu bool) ([]TimesStat, error) {
- return TimesWithContext(context.Background(), percpu)
- }
- func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
- return []TimesStat{}, common.ErrNotImplementedError
- }
- func Info() ([]InfoStat, error) {
- return InfoWithContext(context.Background())
- }
- func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
- psrInfo, err := exec.LookPath("/usr/sbin/psrinfo")
- if err != nil {
- return nil, fmt.Errorf("cannot find psrinfo: %s", err)
- }
- psrInfoOut, err := invoke.CommandWithContext(ctx, psrInfo, "-p", "-v")
- if err != nil {
- return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
- }
- isaInfo, err := exec.LookPath("/usr/bin/isainfo")
- if err != nil {
- return nil, fmt.Errorf("cannot find isainfo: %s", err)
- }
- isaInfoOut, err := invoke.CommandWithContext(ctx, isaInfo, "-b", "-v")
- if err != nil {
- return nil, fmt.Errorf("cannot execute isainfo: %s", err)
- }
- procs, err := parseProcessorInfo(string(psrInfoOut))
- if err != nil {
- return nil, fmt.Errorf("error parsing psrinfo output: %s", err)
- }
- flags, err := parseISAInfo(string(isaInfoOut))
- if err != nil {
- return nil, fmt.Errorf("error parsing isainfo output: %s", err)
- }
- result := make([]InfoStat, 0, len(flags))
- for _, proc := range procs {
- procWithFlags := proc
- procWithFlags.Flags = flags
- result = append(result, procWithFlags)
- }
- return result, nil
- }
- var flagsMatch = regexp.MustCompile(`[\w\.]+`)
- func parseISAInfo(cmdOutput string) ([]string, error) {
- words := flagsMatch.FindAllString(cmdOutput, -1)
- // Sanity check the output
- if len(words) < 4 || words[1] != "bit" || words[3] != "applications" {
- return nil, errors.New("attempted to parse invalid isainfo output")
- }
- flags := make([]string, len(words)-4)
- for i, val := range words[4:] {
- flags[i] = val
- }
- sort.Strings(flags)
- return flags, nil
- }
- var psrInfoMatch = regexp.MustCompile(`The physical processor has (?:([\d]+) virtual processor \(([\d]+)\)|([\d]+) cores and ([\d]+) virtual processors[^\n]+)\n(?:\s+ The core has.+\n)*\s+.+ \((\w+) ([\S]+) family (.+) model (.+) step (.+) clock (.+) MHz\)\n[\s]*(.*)`)
- const (
- psrNumCoresOffset = 1
- psrNumCoresHTOffset = 3
- psrNumHTOffset = 4
- psrVendorIDOffset = 5
- psrFamilyOffset = 7
- psrModelOffset = 8
- psrStepOffset = 9
- psrClockOffset = 10
- psrModelNameOffset = 11
- )
- func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
- matches := psrInfoMatch.FindAllStringSubmatch(cmdOutput, -1)
- var infoStatCount int32
- result := make([]InfoStat, 0, len(matches))
- for physicalIndex, physicalCPU := range matches {
- var step int32
- var clock float64
- if physicalCPU[psrStepOffset] != "" {
- stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err)
- }
- step = int32(stepParsed)
- }
- if physicalCPU[psrClockOffset] != "" {
- clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64)
- if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err)
- }
- clock = float64(clockParsed)
- }
- var err error
- var numCores int64
- var numHT int64
- switch {
- case physicalCPU[psrNumCoresOffset] != "":
- numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err)
- }
- for i := 0; i < int(numCores); i++ {
- result = append(result, InfoStat{
- CPU: infoStatCount,
- PhysicalID: strconv.Itoa(physicalIndex),
- CoreID: strconv.Itoa(i),
- Cores: 1,
- VendorID: physicalCPU[psrVendorIDOffset],
- ModelName: physicalCPU[psrModelNameOffset],
- Family: physicalCPU[psrFamilyOffset],
- Model: physicalCPU[psrModelOffset],
- Stepping: step,
- Mhz: clock,
- })
- infoStatCount++
- }
- case physicalCPU[psrNumCoresHTOffset] != "":
- numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err)
- }
- numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32)
- if err != nil {
- return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err)
- }
- for i := 0; i < int(numCores); i++ {
- result = append(result, InfoStat{
- CPU: infoStatCount,
- PhysicalID: strconv.Itoa(physicalIndex),
- CoreID: strconv.Itoa(i),
- Cores: int32(numHT) / int32(numCores),
- VendorID: physicalCPU[psrVendorIDOffset],
- ModelName: physicalCPU[psrModelNameOffset],
- Family: physicalCPU[psrFamilyOffset],
- Model: physicalCPU[psrModelOffset],
- Stepping: step,
- Mhz: clock,
- })
- infoStatCount++
- }
- default:
- return nil, errors.New("values for cores with and without hyperthreading are both set")
- }
- }
- return result, nil
- }
|