Skip to content

Commit

Permalink
Add isolated cpu parsing (#427)
Browse files Browse the repository at this point in the history
* Add isolated cpu parsing

Signed-off-by: david <davidventura27@gmail.com>

* Address PR comments

Signed-off-by: david <davidventura27@gmail.com>

* Fix start/end range message

Signed-off-by: david <davidventura27@gmail.com>

* rename to parseIsolatedCPUs

Signed-off-by: david <davidventura27@gmail.com>

* Do not wrap error

Signed-off-by: david <davidventura27@gmail.com>

* also check error is nil

Signed-off-by: david <davidventura27@gmail.com>
  • Loading branch information
DavidVentura committed Dec 20, 2021
1 parent 5bd7067 commit c6f5590
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
5 changes: 5 additions & 0 deletions fixtures.ttar
Expand Up @@ -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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down
49 changes: 49 additions & 0 deletions sysfs/system_cpu.go
Expand Up @@ -16,8 +16,11 @@
package sysfs

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"

"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -237,3 +240,49 @@ 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, err
}

return parseIsolatedCPUs(isolcpus)
}

func parseIsolatedCPUs(data []byte) ([]uint16, error) {

var isolcpusInt = []uint16{}

for _, cpu := range strings.Split(strings.TrimRight(string(data), "\n"), ",") {
if cpu == "" {
continue
}
if strings.Contains(cpu, "-") {
ranges := strings.Split(cpu, "-")
if len(ranges) != 2 {
return nil, fmt.Errorf("invalid cpu range: %s", cpu)
}
startRange, err := strconv.Atoi(ranges[0])
if err != nil {
return nil, fmt.Errorf("invalid cpu start range: %w", err)
}
endRange, err := strconv.Atoi(ranges[1])
if err != nil {
return nil, fmt.Errorf("invalid cpu end range: %w", err)
}

for i := startRange; i <= endRange; i++ {
isolcpusInt = append(isolcpusInt, uint16(i))
}
continue
}

cpuN, err := strconv.Atoi(cpu)
if err != nil {
return nil, err
}
isolcpusInt = append(isolcpusInt, uint16(cpuN))
}
return isolcpusInt, nil
}
52 changes: 52 additions & 0 deletions sysfs/system_cpu_test.go
Expand Up @@ -16,6 +16,7 @@
package sysfs

import (
"errors"
"reflect"
"testing"
)
Expand Down Expand Up @@ -140,3 +141,54 @@ 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},

{[]byte("1,"), []uint16{1}, nil},
{[]byte("1,2-"), nil, errors.New(`invalid cpu end range: strconv.Atoi: parsing "": invalid syntax`)},
{[]byte("1,-3"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)},
}
for _, params := range testParams {
t.Run("blabla", func(t *testing.T) {
res, err := parseIsolatedCPUs(params.in)
if !reflect.DeepEqual(res, params.res) {
t.Fatalf("should have %v result: got %v", params.res, res)
}
if err != nil && params.err != nil && err.Error() != params.err.Error() {
t.Fatalf("should have '%v' error: got '%v'", params.err, err)
}
if (err == nil || params.err == nil) && 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)
}
if err != nil {
t.Errorf("Error not correct: want %v, have %v", nil, err)
}
}

0 comments on commit c6f5590

Please sign in to comment.