Skip to content

Commit c6f5590

Browse files
authored
Add isolated cpu parsing (#427)
* Add isolated cpu parsing Signed-off-by: david <[email protected]> * Address PR comments Signed-off-by: david <[email protected]> * Fix start/end range message Signed-off-by: david <[email protected]> * rename to parseIsolatedCPUs Signed-off-by: david <[email protected]> * Do not wrap error Signed-off-by: david <[email protected]> * also check error is nil Signed-off-by: david <[email protected]>
1 parent 5bd7067 commit c6f5590

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

fixtures.ttar

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6462,6 +6462,11 @@ Mode: 644
64626462
Directory: fixtures/sys/devices/system/cpu/cpufreq/policy1
64636463
Mode: 755
64646464
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6465+
Path: fixtures/sys/devices/system/cpu/isolated
6466+
Lines: 1
6467+
1,2-7,9
6468+
Mode: 664
6469+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
64656470
Directory: fixtures/sys/devices/system/node
64666471
Mode: 775
64676472
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sysfs/system_cpu.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
package sysfs
1717

1818
import (
19+
"fmt"
20+
"io/ioutil"
1921
"os"
2022
"path/filepath"
23+
"strconv"
2124
"strings"
2225

2326
"golang.org/x/sync/errgroup"
@@ -237,3 +240,49 @@ func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) {
237240
SetSpeed: stringOut[4],
238241
}, nil
239242
}
243+
244+
func (fs FS) IsolatedCPUs() ([]uint16, error) {
245+
isolcpus, err := ioutil.ReadFile(fs.sys.Path("devices/system/cpu/isolated"))
246+
if err != nil {
247+
return nil, err
248+
}
249+
250+
return parseIsolatedCPUs(isolcpus)
251+
}
252+
253+
func parseIsolatedCPUs(data []byte) ([]uint16, error) {
254+
255+
var isolcpusInt = []uint16{}
256+
257+
for _, cpu := range strings.Split(strings.TrimRight(string(data), "\n"), ",") {
258+
if cpu == "" {
259+
continue
260+
}
261+
if strings.Contains(cpu, "-") {
262+
ranges := strings.Split(cpu, "-")
263+
if len(ranges) != 2 {
264+
return nil, fmt.Errorf("invalid cpu range: %s", cpu)
265+
}
266+
startRange, err := strconv.Atoi(ranges[0])
267+
if err != nil {
268+
return nil, fmt.Errorf("invalid cpu start range: %w", err)
269+
}
270+
endRange, err := strconv.Atoi(ranges[1])
271+
if err != nil {
272+
return nil, fmt.Errorf("invalid cpu end range: %w", err)
273+
}
274+
275+
for i := startRange; i <= endRange; i++ {
276+
isolcpusInt = append(isolcpusInt, uint16(i))
277+
}
278+
continue
279+
}
280+
281+
cpuN, err := strconv.Atoi(cpu)
282+
if err != nil {
283+
return nil, err
284+
}
285+
isolcpusInt = append(isolcpusInt, uint16(cpuN))
286+
}
287+
return isolcpusInt, nil
288+
}

sysfs/system_cpu_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package sysfs
1717

1818
import (
19+
"errors"
1920
"reflect"
2021
"testing"
2122
)
@@ -140,3 +141,54 @@ func TestSystemCpufreq(t *testing.T) {
140141
t.Errorf("Result not correct: want %v, have %v", systemCpufreq, c)
141142
}
142143
}
144+
145+
func TestIsolatedParsingCPU(t *testing.T) {
146+
var testParams = []struct {
147+
in []byte
148+
res []uint16
149+
err error
150+
}{
151+
{[]byte(""), []uint16{}, nil},
152+
{[]byte("1\n"), []uint16{1}, nil},
153+
{[]byte("1"), []uint16{1}, nil},
154+
{[]byte("1,2"), []uint16{1, 2}, nil},
155+
{[]byte("1-2"), []uint16{1, 2}, nil},
156+
{[]byte("1-3"), []uint16{1, 2, 3}, nil},
157+
{[]byte("1,2-4"), []uint16{1, 2, 3, 4}, nil},
158+
{[]byte("1,3-4"), []uint16{1, 3, 4}, nil},
159+
{[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil},
160+
161+
{[]byte("1,"), []uint16{1}, nil},
162+
{[]byte("1,2-"), nil, errors.New(`invalid cpu end range: strconv.Atoi: parsing "": invalid syntax`)},
163+
{[]byte("1,-3"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)},
164+
}
165+
for _, params := range testParams {
166+
t.Run("blabla", func(t *testing.T) {
167+
res, err := parseIsolatedCPUs(params.in)
168+
if !reflect.DeepEqual(res, params.res) {
169+
t.Fatalf("should have %v result: got %v", params.res, res)
170+
}
171+
if err != nil && params.err != nil && err.Error() != params.err.Error() {
172+
t.Fatalf("should have '%v' error: got '%v'", params.err, err)
173+
}
174+
if (err == nil || params.err == nil) && err != params.err {
175+
t.Fatalf("should have %v error: got %v", params.err, err)
176+
}
177+
178+
})
179+
}
180+
}
181+
func TestIsolatedCPUs(t *testing.T) {
182+
fs, err := NewFS(sysTestFixtures)
183+
if err != nil {
184+
t.Fatal(err)
185+
}
186+
isolated, err := fs.IsolatedCPUs()
187+
expected := []uint16{1, 2, 3, 4, 5, 6, 7, 9}
188+
if !reflect.DeepEqual(isolated, expected) {
189+
t.Errorf("Result not correct: want %v, have %v", expected, isolated)
190+
}
191+
if err != nil {
192+
t.Errorf("Error not correct: want %v, have %v", nil, err)
193+
}
194+
}

0 commit comments

Comments
 (0)