Merge pull request #2114 from lubinszARM/cpuinfo
Fix bug:getTopology will be failed on Arm platform
This commit is contained in:
commit
8b1337898f
@ -16,12 +16,13 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
// s390/s390x changes
|
||||
"runtime"
|
||||
|
||||
@ -36,9 +37,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
cpuRegExp = regexp.MustCompile(`^processor\s*:\s*([0-9]+)$`)
|
||||
coreRegExp = regexp.MustCompile(`^core id\s*:\s*([0-9]+)$`)
|
||||
nodeRegExp = regexp.MustCompile(`^physical id\s*:\s*([0-9]+)$`)
|
||||
cpuRegExp = regexp.MustCompile(`^processor\s*:\s*([0-9]+)$`)
|
||||
coreRegExp = regexp.MustCompile(`^core id\s*:\s*([0-9]+)$`)
|
||||
nodeRegExp = regexp.MustCompile(`^physical id\s*:\s*([0-9]+)$`)
|
||||
nodeBusRegExp = regexp.MustCompile(`^node([0-9]+)$`)
|
||||
// Power systems have a different format so cater for both
|
||||
cpuClockSpeedMHz = regexp.MustCompile(`(?:cpu MHz|clock)\s*:\s*([0-9]+\.[0-9]+)(?:MHz)?`)
|
||||
memoryCapacityRegexp = regexp.MustCompile(`MemTotal:\s*([0-9]+) kB`)
|
||||
@ -46,6 +48,7 @@ var (
|
||||
)
|
||||
|
||||
const maxFreqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
|
||||
const cpuBusPath = "/sys/bus/cpu/devices/"
|
||||
|
||||
// GetClockSpeed returns the CPU clock speed, given a []byte formatted as the /proc/cpuinfo file.
|
||||
func GetClockSpeed(procInfo []byte) (uint64, error) {
|
||||
@ -127,6 +130,67 @@ func parseCapacity(b []byte, r *regexp.Regexp) (uint64, error) {
|
||||
return m * 1024, err
|
||||
}
|
||||
|
||||
/* look for sysfs cpu path containing core_id */
|
||||
/* such as: sys/bus/cpu/devices/cpu0/topology/core_id */
|
||||
func getCoreIdFromCpuBus(cpuBusPath string, threadId int) (int, error) {
|
||||
path := filepath.Join(cpuBusPath, fmt.Sprintf("cpu%d/topology", threadId))
|
||||
file := filepath.Join(path, "core_id")
|
||||
|
||||
num, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return threadId, err
|
||||
}
|
||||
|
||||
coreId, err := strconv.ParseInt(string(bytes.TrimSpace(num)), 10, 32)
|
||||
if err != nil {
|
||||
return threadId, err
|
||||
}
|
||||
|
||||
if coreId < 0 {
|
||||
// report threadId if found coreId < 0
|
||||
coreId = int64(threadId)
|
||||
}
|
||||
|
||||
return int(coreId), nil
|
||||
}
|
||||
|
||||
/* look for sysfs cpu path containing node id */
|
||||
/* such as: /sys/bus/cpu/devices/cpu0/node%d */
|
||||
func getNodeIdFromCpuBus(cpuBusPath string, threadId int) (int, error) {
|
||||
path := filepath.Join(cpuBusPath, fmt.Sprintf("cpu%d", threadId))
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
nodeId := 0
|
||||
for _, file := range files {
|
||||
filename := file.Name()
|
||||
|
||||
isNode, error := regexp.MatchString("^node([0-9]+)$", filename)
|
||||
if error != nil {
|
||||
continue
|
||||
}
|
||||
if !isNode {
|
||||
continue
|
||||
}
|
||||
|
||||
ok, val, _ := extractValue(filename, nodeBusRegExp)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ok {
|
||||
if val < 0 {
|
||||
continue
|
||||
}
|
||||
nodeId = val
|
||||
}
|
||||
}
|
||||
|
||||
return nodeId, nil
|
||||
}
|
||||
|
||||
func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) {
|
||||
nodes := []info.Node{}
|
||||
|
||||
@ -161,8 +225,34 @@ func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) {
|
||||
lastNode = -1
|
||||
}
|
||||
lastThread = thread
|
||||
|
||||
/* On Arm platform, no 'core id' and 'physical id' in '/proc/cpuinfo'. */
|
||||
/* So we search sysfs cpu path directly. */
|
||||
/* This method can also be used on other platforms, such as x86, ppc64le... */
|
||||
/* /sys/bus/cpu/devices/cpu%d contains the information of 'core_id' & 'node_id'. */
|
||||
/* Such as: /sys/bus/cpu/devices/cpu0/topology/core_id */
|
||||
/* Such as: /sys/bus/cpu/devices/cpu0/node0 */
|
||||
if isAArch64() {
|
||||
val, err = getCoreIdFromCpuBus(cpuBusPath, lastThread)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("could not parse core info from %q: %v", cpuBusPath, err)
|
||||
}
|
||||
lastCore = val
|
||||
|
||||
val, err = getNodeIdFromCpuBus(cpuBusPath, lastThread)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("could not parse node info from %q: %v", cpuBusPath, err)
|
||||
}
|
||||
lastNode = val
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if isAArch64() {
|
||||
/* On Arm platform, no 'core id' and 'physical id' in '/proc/cpuinfo'. */
|
||||
continue
|
||||
}
|
||||
|
||||
ok, val, err = extractValue(line, coreRegExp)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("could not parse core info from %q: %v", line, err)
|
||||
@ -171,6 +261,7 @@ func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) {
|
||||
lastCore = val
|
||||
continue
|
||||
}
|
||||
|
||||
ok, val, err = extractValue(line, nodeRegExp)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("could not parse node info from %q: %v", line, err)
|
||||
@ -180,6 +271,7 @@ func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
nodeIdx, err := addNode(&nodes, lastNode)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("failed to add node %d: %v", lastNode, err)
|
||||
|
0
machine/testdata/cpu0/node0/null
vendored
Normal file
0
machine/testdata/cpu0/node0/null
vendored
Normal file
1
machine/testdata/cpu0/topology/core_id
vendored
Normal file
1
machine/testdata/cpu0/topology/core_id
vendored
Normal file
@ -0,0 +1 @@
|
||||
0
|
0
machine/testdata/cpu9999/node1234/null
vendored
Normal file
0
machine/testdata/cpu9999/node1234/null
vendored
Normal file
1
machine/testdata/cpu9999/topology/core_id
vendored
Normal file
1
machine/testdata/cpu9999/topology/core_id
vendored
Normal file
@ -0,0 +1 @@
|
||||
8888
|
@ -115,3 +115,27 @@ func TestTopologyEmptyCpuinfo(t *testing.T) {
|
||||
t.Errorf("Expected empty cpuinfo to fail.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopologyCoreId(t *testing.T) {
|
||||
val, _ := getCoreIdFromCpuBus("./testdata", 0)
|
||||
if val != 0 {
|
||||
t.Errorf("Expected core 0, found %d", val)
|
||||
}
|
||||
|
||||
val, _ = getCoreIdFromCpuBus("./testdata", 9999)
|
||||
if val != 8888 {
|
||||
t.Errorf("Expected core 8888, found %d", val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopologyNodeId(t *testing.T) {
|
||||
val, _ := getNodeIdFromCpuBus("./testdata", 0)
|
||||
if val != 0 {
|
||||
t.Errorf("Expected core 0, found %d", val)
|
||||
}
|
||||
|
||||
val, _ = getNodeIdFromCpuBus("./testdata", 9999)
|
||||
if val != 1234 {
|
||||
t.Errorf("Expected core 1234 , found %d", val)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user