From 1c26c9730999d2380979ccd2609328628c80b6d8 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 15 Dec 2021 13:41:39 +0100 Subject: [PATCH] Add isolated cpu parsing --- fixtures.ttar | 5 +++++ sysfs/system_cpu.go | 47 ++++++++++++++++++++++++++++++++++++++++ sysfs/system_cpu_test.go | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/fixtures.ttar b/fixtures.ttar index e005ee94a..50294186f 100644 --- a/fixtures.ttar +++ b/fixtures.ttar @@ -6462,6 +6462,11 @@ Mode: 644 Directory: fixtures/sys/devices/system/cpu/cpufreq/policy1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/devices/system/cpu/isolated +Lines: 1 +1,2-7,9 +Mode: 664 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/system/node Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go index 40fc94b43..46ac5cb5a 100644 --- a/sysfs/system_cpu.go +++ b/sysfs/system_cpu.go @@ -16,8 +16,11 @@ package sysfs import ( + "fmt" + "io/ioutil" "os" "path/filepath" + "strconv" "strings" "golang.org/x/sync/errgroup" @@ -237,3 +240,47 @@ func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) { SetSpeed: stringOut[4], }, nil } + +func (fs FS) IsolatedCPUs() ([]uint16, error) { + isolcpus, err := ioutil.ReadFile(fs.sys.Path("devices/system/cpu/isolated")) + if err != nil { + return nil, fmt.Errorf("failed to read isolcpus from sysfs: %w", err) + } + + return parseIsolCpus(isolcpus) +} + +func parseIsolCpus(data []byte) ([]uint16, error) { + isolcpus_str := strings.TrimRight(string(data), "\n") + + var isolcpus_int = []uint16{} + + for _, cpu := range strings.Split(isolcpus_str, ",") { + if cpu == "" { + continue + } + if strings.Contains(cpu, "-") { + ranges := strings.Split(cpu, "-") + startRange, err := strconv.Atoi(ranges[0]) + if err != nil { + return nil, err + } + endRange, err := strconv.Atoi(ranges[1]) + if err != nil { + return nil, err + } + + for i := startRange; i <= endRange; i++ { + isolcpus_int = append(isolcpus_int, uint16(i)) + } + continue + } + + _cpu, err := strconv.Atoi(cpu) + if err != nil { + return nil, err + } + isolcpus_int = append(isolcpus_int, uint16(_cpu)) + } + return isolcpus_int, nil +} diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go index 522b58b56..4603f8928 100644 --- a/sysfs/system_cpu_test.go +++ b/sysfs/system_cpu_test.go @@ -140,3 +140,43 @@ func TestSystemCpufreq(t *testing.T) { t.Errorf("Result not correct: want %v, have %v", systemCpufreq, c) } } + +func TestIsolatedParsingCPU(t *testing.T) { + var testParams = []struct { + in []byte + res []uint16 + err error + }{ + {[]byte(""), []uint16{}, nil}, + {[]byte("1\n"), []uint16{1}, nil}, + {[]byte("1"), []uint16{1}, nil}, + {[]byte("1,2"), []uint16{1, 2}, nil}, + {[]byte("1-2"), []uint16{1, 2}, nil}, + {[]byte("1-3"), []uint16{1, 2, 3}, nil}, + {[]byte("1,2-4"), []uint16{1, 2, 3, 4}, nil}, + {[]byte("1,3-4"), []uint16{1, 3, 4}, nil}, + {[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil}, + } + for _, params := range testParams { + t.Run("blabla", func(t *testing.T) { + res, err := parseIsolCpus(params.in) + if !reflect.DeepEqual(res, params.res) { + t.Fatalf("should have %v result: got %v", params.res, res) + } + if err != params.err { + t.Fatalf("should have %v error: got %v", params.err, err) + } + }) + } +} +func TestIsolatedCPUs(t *testing.T) { + fs, err := NewFS(sysTestFixtures) + if err != nil { + t.Fatal(err) + } + isolated, err := fs.IsolatedCPUs() + expected := []uint16{1, 2, 3, 4, 5, 6, 7, 9} + if !reflect.DeepEqual(isolated, expected) { + t.Errorf("Result not correct: want %v, have %v", expected, isolated) + } +}