Skip to content

Commit f930a52

Browse files
taherkkdiscordianfish
authored andcommitted
Bug Fix: SystemCPUfreq fails when any core is offline
Signed-off-by: taherk <[email protected]>
1 parent 80824fa commit f930a52

File tree

3 files changed

+95
-7
lines changed

3 files changed

+95
-7
lines changed

sysfs/system_cpu.go

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,49 @@ func parseCPUThermalThrottle(cpuPath string) (*CPUThermalThrottle, error) {
142142
return &t, nil
143143
}
144144

145+
func binSearch(elem uint16, elemSlice *[]uint16) bool {
146+
if len(*elemSlice) == 0 {
147+
return false
148+
}
149+
150+
if len(*elemSlice) == 1 {
151+
return elem == (*elemSlice)[0]
152+
}
153+
154+
start := 0
155+
end := len(*elemSlice) - 1
156+
157+
var mid int
158+
159+
for start <= end {
160+
mid = (start + end) / 2
161+
if (*elemSlice)[mid] == elem {
162+
return true
163+
} else if (*elemSlice)[mid] > elem {
164+
end = mid - 1
165+
} else if (*elemSlice)[mid] < elem {
166+
start = mid + 1
167+
}
168+
}
169+
170+
return false
171+
}
172+
173+
func filterOfflineCPUs(offlineCpus *[]uint16, cpus *[]string) error {
174+
for i, cpu := range *cpus {
175+
cpuName := strings.TrimPrefix(filepath.Base(cpu), "cpu")
176+
cpuNameUint16, err := strconv.Atoi(cpuName)
177+
if err != nil {
178+
return err
179+
}
180+
if binSearch(uint16(cpuNameUint16), offlineCpus) {
181+
*cpus = append((*cpus)[:i], (*cpus)[i+1:]...)
182+
}
183+
}
184+
185+
return nil
186+
}
187+
145188
// SystemCpufreq returns CPU frequency metrics for all CPUs.
146189
func (fs FS) SystemCpufreq() ([]SystemCPUCpufreqStats, error) {
147190
var g errgroup.Group
@@ -151,6 +194,25 @@ func (fs FS) SystemCpufreq() ([]SystemCPUCpufreqStats, error) {
151194
return nil, err
152195
}
153196

197+
line, err := util.ReadFileNoStat(fs.sys.Path("devices/system/cpu/offline"))
198+
if err != nil {
199+
return nil, err
200+
}
201+
202+
if strings.TrimSpace(string(line)) != "" {
203+
offlineCPUs, err := parseCPURange(line)
204+
if err != nil {
205+
return nil, err
206+
}
207+
208+
if len(offlineCPUs) > 0 {
209+
err = filterOfflineCPUs(&offlineCPUs, &cpus)
210+
if err != nil {
211+
return nil, err
212+
}
213+
}
214+
}
215+
154216
systemCpufreq := make([]SystemCPUCpufreqStats, len(cpus))
155217
for i, cpu := range cpus {
156218
cpuName := strings.TrimPrefix(filepath.Base(cpu), "cpu")
@@ -251,12 +313,12 @@ func (fs FS) IsolatedCPUs() ([]uint16, error) {
251313
return nil, err
252314
}
253315

254-
return parseIsolatedCPUs(isolcpus)
316+
return parseCPURange(isolcpus)
255317
}
256318

257-
func parseIsolatedCPUs(data []byte) ([]uint16, error) {
319+
func parseCPURange(data []byte) ([]uint16, error) {
258320

259-
var isolcpusInt = []uint16{}
321+
var cpusInt = []uint16{}
260322

261323
for _, cpu := range strings.Split(strings.TrimRight(string(data), "\n"), ",") {
262324
if cpu == "" {
@@ -277,7 +339,7 @@ func parseIsolatedCPUs(data []byte) ([]uint16, error) {
277339
}
278340

279341
for i := startRange; i <= endRange; i++ {
280-
isolcpusInt = append(isolcpusInt, uint16(i))
342+
cpusInt = append(cpusInt, uint16(i))
281343
}
282344
continue
283345
}
@@ -286,7 +348,7 @@ func parseIsolatedCPUs(data []byte) ([]uint16, error) {
286348
if err != nil {
287349
return nil, err
288350
}
289-
isolcpusInt = append(isolcpusInt, uint16(cpuN))
351+
cpusInt = append(cpusInt, uint16(cpuN))
290352
}
291-
return isolcpusInt, nil
353+
return cpusInt, nil
292354
}

sysfs/system_cpu_test.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func TestIsolatedParsingCPU(t *testing.T) {
165165
}
166166
for _, params := range testParams {
167167
t.Run("blabla", func(t *testing.T) {
168-
res, err := parseIsolatedCPUs(params.in)
168+
res, err := parseCPURange(params.in)
169169
if !reflect.DeepEqual(res, params.res) {
170170
t.Fatalf("should have %v result: got %v", params.res, res)
171171
}
@@ -193,3 +193,24 @@ func TestIsolatedCPUs(t *testing.T) {
193193
t.Errorf("Error not correct: want %v, have %v", nil, err)
194194
}
195195
}
196+
197+
func TestBinSearch(t *testing.T) {
198+
var testParams = []struct {
199+
elem uint16
200+
elems []uint16
201+
res bool
202+
}{
203+
{3, []uint16{1, 3, 5, 7, 9}, true},
204+
{4, []uint16{1, 3, 5, 7, 9}, false},
205+
{2, []uint16{}, false},
206+
}
207+
208+
for _, param := range testParams {
209+
res := binSearch(param.elem, &param.elems)
210+
211+
if res != param.res {
212+
t.Fatalf("Result not correct: want %v, have %v", param.res, res)
213+
}
214+
215+
}
216+
}

testdata/fixtures.ttar

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12729,6 +12729,11 @@ Lines: 1
1272912729
1,2-7,9
1273012730
Mode: 664
1273112731
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
12732+
Path: fixtures/sys/devices/system/cpu/offline
12733+
Lines: 1
12734+
2,12-15
12735+
Mode: 664
12736+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1273212737
Directory: fixtures/sys/devices/system/node
1273312738
Mode: 775
1273412739
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0 commit comments

Comments
 (0)