| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // Use and distribution licensed under the Apache license version 2.
- //
- // See the COPYING file in the root project directory for full text.
- //
- package topology
- import (
- "fmt"
- "io/ioutil"
- "path/filepath"
- "strconv"
- "strings"
- "github.com/jaypipes/ghw/pkg/context"
- "github.com/jaypipes/ghw/pkg/cpu"
- "github.com/jaypipes/ghw/pkg/linuxpath"
- "github.com/jaypipes/ghw/pkg/memory"
- )
- func (i *Info) load() error {
- i.Nodes = topologyNodes(i.ctx)
- if len(i.Nodes) == 1 {
- i.Architecture = ARCHITECTURE_SMP
- } else {
- i.Architecture = ARCHITECTURE_NUMA
- }
- return nil
- }
- func topologyNodes(ctx *context.Context) []*Node {
- paths := linuxpath.New(ctx)
- nodes := make([]*Node, 0)
- files, err := ioutil.ReadDir(paths.SysDevicesSystemNode)
- if err != nil {
- ctx.Warn("failed to determine nodes: %s\n", err)
- return nodes
- }
- for _, file := range files {
- filename := file.Name()
- if !strings.HasPrefix(filename, "node") {
- continue
- }
- node := &Node{}
- nodeID, err := strconv.Atoi(filename[4:])
- if err != nil {
- ctx.Warn("failed to determine node ID: %s\n", err)
- return nodes
- }
- node.ID = nodeID
- cores, err := cpu.CoresForNode(ctx, nodeID)
- if err != nil {
- ctx.Warn("failed to determine cores for node: %s\n", err)
- return nodes
- }
- node.Cores = cores
- caches, err := memory.CachesForNode(ctx, nodeID)
- if err != nil {
- ctx.Warn("failed to determine caches for node: %s\n", err)
- return nodes
- }
- node.Caches = caches
- distances, err := distancesForNode(ctx, nodeID)
- if err != nil {
- ctx.Warn("failed to determine node distances for node: %s\n", err)
- return nodes
- }
- node.Distances = distances
- area, err := memory.AreaForNode(ctx, nodeID)
- if err != nil {
- ctx.Warn("failed to determine memory area for node: %s\n", err)
- return nodes
- }
- node.Memory = area
- nodes = append(nodes, node)
- }
- return nodes
- }
- func distancesForNode(ctx *context.Context, nodeID int) ([]int, error) {
- paths := linuxpath.New(ctx)
- path := filepath.Join(
- paths.SysDevicesSystemNode,
- fmt.Sprintf("node%d", nodeID),
- "distance",
- )
- data, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- items := strings.Fields(strings.TrimSpace(string(data)))
- dists := make([]int, len(items)) // TODO: can a NUMA cell be offlined?
- for idx, item := range items {
- dist, err := strconv.Atoi(item)
- if err != nil {
- return dists, err
- }
- dists[idx] = dist
- }
- return dists, nil
- }
|