From 9f2e6a74cc20ee6085a8c7891bfdf65ad5ab312f Mon Sep 17 00:00:00 2001 From: Daniel Theophanes Date: Sat, 17 Oct 2015 12:25:18 -0700 Subject: [PATCH 1/2] cpu: support ARM CPUs. ARM CPUs don't include the same fields as x86 and amd64 CPUs in the /proc/cpuinfo list. Pull information from the /sys/... device tree as well as updating when a CPU is done in cpuinfo. Fixes #88 --- cpu/cpu_linux.go | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go index 942ef0c2..8bfa1ce8 100644 --- a/cpu/cpu_linux.go +++ b/cpu/cpu_linux.go @@ -3,6 +3,7 @@ package cpu import ( + "fmt" "errors" "os/exec" "strconv" @@ -55,19 +56,36 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { return ret, nil } +func finishCPUInfo(c *CPUInfoStat) error { + if c.Mhz == 0 { + lines, err := common.ReadLines(fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", c.CPU)) + if err == nil { + value, err := strconv.ParseFloat(lines[0], 64) + if err != nil { + return err + } + c.Mhz = value + } + } + if len(c.CoreID) == 0 { + lines, err := common.ReadLines(fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/core_id", c.CPU)) + if err == nil { + c.CoreID = lines[0] + } + } + return nil +} + func CPUInfo() ([]CPUInfoStat, error) { filename := "/proc/cpuinfo" lines, _ := common.ReadLines(filename) var ret []CPUInfoStat - var c CPUInfoStat + c := CPUInfoStat{CPU: -1} for _, line := range lines { fields := strings.Split(line, ":") if len(fields) < 2 { - if c.VendorID != "" { - ret = append(ret, c) - } continue } key := strings.TrimSpace(fields[0]) @@ -75,6 +93,13 @@ func CPUInfo() ([]CPUInfoStat, error) { switch key { case "processor": + if c.CPU >= 0 { + err := finishCPUInfo(&c) + if err != nil { + return ret, err + } + ret = append(ret, c) + } c = CPUInfoStat{} t, err := strconv.ParseInt(value, 10, 64) if err != nil { @@ -117,10 +142,19 @@ func CPUInfo() ([]CPUInfoStat, error) { return ret, err } c.Cores = int32(t) - case "flags": - c.Flags = strings.Split(value, ",") + case "flags","Features": + c.Flags = strings.FieldsFunc(value, func(r rune) bool { + return r == ',' || r == ' ' + }) } } + if c.CPU >= 0 { + err := finishCPUInfo(&c) + if err != nil { + return ret, err + } + ret = append(ret, c) + } return ret, nil } From 69221741e8a907bbb209330b2324e4632a5f6bab Mon Sep 17 00:00:00 2001 From: Daniel Theophanes Date: Sun, 18 Oct 2015 09:46:21 -0700 Subject: [PATCH 2/2] cpu: allow override of /sys dir. Fix CPUInfo /proc + cpuinfo combine. --- README.rst | 1 + cpu/cpu_linux.go | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index a858ff09..bd931528 100644 --- a/README.rst +++ b/README.rst @@ -60,6 +60,7 @@ The output is below. {"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip)} You can set an alternative location to /proc by setting the HOST_PROC environment variable. +You can set an alternative location to /sys by setting the HOST_SYS environment variable. Documentation ------------------------ diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go index d187f780..6a4e672b 100644 --- a/cpu/cpu_linux.go +++ b/cpu/cpu_linux.go @@ -3,6 +3,7 @@ package cpu import ( + "path/filepath" "fmt" "errors" "os/exec" @@ -56,9 +57,14 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { return ret, nil } +func sysCpuPath(cpu int32, relPath string) string { + root := common.GetEnv("HOST_SYS", "/sys") + return filepath.Join(root, fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath) +} + func finishCPUInfo(c *CPUInfoStat) error { if c.Mhz == 0 { - lines, err := common.ReadLines(fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", c.CPU)) + lines, err := common.ReadLines(sysCpuPath(c.CPU, "cpufreq/cpuinfo_max_freq")) if err == nil { value, err := strconv.ParseFloat(lines[0], 64) if err != nil { @@ -68,7 +74,7 @@ func finishCPUInfo(c *CPUInfoStat) error { } } if len(c.CoreID) == 0 { - lines, err := common.ReadLines(fmt.Sprintf("/sys/devices/system/cpu/cpu%d/topology/core_id", c.CPU)) + lines, err := common.ReadLines(sysCpuPath(c.CPU, "topology/core_id")) if err == nil { c.CoreID = lines[0] } @@ -77,7 +83,7 @@ func finishCPUInfo(c *CPUInfoStat) error { } func CPUInfo() ([]CPUInfoStat, error) { - filename := common.GetEnv("HOST_PROC", "/proc") + "cpuinfo" + filename := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), "cpuinfo") lines, _ := common.ReadLines(filename) var ret []CPUInfoStat