aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/prometheus/procfs/cpuinfo.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/prometheus/procfs/cpuinfo.go')
-rw-r--r--vendor/github.com/prometheus/procfs/cpuinfo.go265
1 files changed, 259 insertions, 6 deletions
diff --git a/vendor/github.com/prometheus/procfs/cpuinfo.go b/vendor/github.com/prometheus/procfs/cpuinfo.go
index 2e02215..31d42f7 100644
--- a/vendor/github.com/prometheus/procfs/cpuinfo.go
+++ b/vendor/github.com/prometheus/procfs/cpuinfo.go
@@ -11,11 +11,15 @@
11// See the License for the specific language governing permissions and 11// See the License for the specific language governing permissions and
12// limitations under the License. 12// limitations under the License.
13 13
14// +build linux
15
14package procfs 16package procfs
15 17
16import ( 18import (
17 "bufio" 19 "bufio"
18 "bytes" 20 "bytes"
21 "errors"
22 "regexp"
19 "strconv" 23 "strconv"
20 "strings" 24 "strings"
21 25
@@ -52,6 +56,11 @@ type CPUInfo struct {
52 PowerManagement string 56 PowerManagement string
53} 57}
54 58
59var (
60 cpuinfoClockRegexp = regexp.MustCompile(`([\d.]+)`)
61 cpuinfoS390XProcessorRegexp = regexp.MustCompile(`^processor\s+(\d+):.*`)
62)
63
55// CPUInfo returns information about current system CPUs. 64// CPUInfo returns information about current system CPUs.
56// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt 65// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
57func (fs FS) CPUInfo() ([]CPUInfo, error) { 66func (fs FS) CPUInfo() ([]CPUInfo, error) {
@@ -62,14 +71,26 @@ func (fs FS) CPUInfo() ([]CPUInfo, error) {
62 return parseCPUInfo(data) 71 return parseCPUInfo(data)
63} 72}
64 73
65// parseCPUInfo parses data from /proc/cpuinfo 74func parseCPUInfoX86(info []byte) ([]CPUInfo, error) {
66func parseCPUInfo(info []byte) ([]CPUInfo, error) {
67 cpuinfo := []CPUInfo{}
68 i := -1
69 scanner := bufio.NewScanner(bytes.NewReader(info)) 75 scanner := bufio.NewScanner(bytes.NewReader(info))
76
77 // find the first "processor" line
78 firstLine := firstNonEmptyLine(scanner)
79 if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
80 return nil, errors.New("invalid cpuinfo file: " + firstLine)
81 }
82 field := strings.SplitN(firstLine, ": ", 2)
83 v, err := strconv.ParseUint(field[1], 0, 32)
84 if err != nil {
85 return nil, err
86 }
87 firstcpu := CPUInfo{Processor: uint(v)}
88 cpuinfo := []CPUInfo{firstcpu}
89 i := 0
90
70 for scanner.Scan() { 91 for scanner.Scan() {
71 line := scanner.Text() 92 line := scanner.Text()
72 if strings.TrimSpace(line) == "" { 93 if !strings.Contains(line, ":") {
73 continue 94 continue
74 } 95 }
75 field := strings.SplitN(line, ": ", 2) 96 field := strings.SplitN(line, ": ", 2)
@@ -82,7 +103,7 @@ func parseCPUInfo(info []byte) ([]CPUInfo, error) {
82 return nil, err 103 return nil, err
83 } 104 }
84 cpuinfo[i].Processor = uint(v) 105 cpuinfo[i].Processor = uint(v)
85 case "vendor_id": 106 case "vendor", "vendor_id":
86 cpuinfo[i].VendorID = field[1] 107 cpuinfo[i].VendorID = field[1]
87 case "cpu family": 108 case "cpu family":
88 cpuinfo[i].CPUFamily = field[1] 109 cpuinfo[i].CPUFamily = field[1]
@@ -163,5 +184,237 @@ func parseCPUInfo(info []byte) ([]CPUInfo, error) {
163 } 184 }
164 } 185 }
165 return cpuinfo, nil 186 return cpuinfo, nil
187}
188
189func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
190 scanner := bufio.NewScanner(bytes.NewReader(info))
191
192 firstLine := firstNonEmptyLine(scanner)
193 match, _ := regexp.MatchString("^[Pp]rocessor", firstLine)
194 if !match || !strings.Contains(firstLine, ":") {
195 return nil, errors.New("invalid cpuinfo file: " + firstLine)
196 }
197 field := strings.SplitN(firstLine, ": ", 2)
198 cpuinfo := []CPUInfo{}
199 featuresLine := ""
200 commonCPUInfo := CPUInfo{}
201 i := 0
202 if strings.TrimSpace(field[0]) == "Processor" {
203 commonCPUInfo = CPUInfo{ModelName: field[1]}
204 i = -1
205 } else {
206 v, err := strconv.ParseUint(field[1], 0, 32)
207 if err != nil {
208 return nil, err
209 }
210 firstcpu := CPUInfo{Processor: uint(v)}
211 cpuinfo = []CPUInfo{firstcpu}
212 }
213
214 for scanner.Scan() {
215 line := scanner.Text()
216 if !strings.Contains(line, ":") {
217 continue
218 }
219 field := strings.SplitN(line, ": ", 2)
220 switch strings.TrimSpace(field[0]) {
221 case "processor":
222 cpuinfo = append(cpuinfo, commonCPUInfo) // start of the next processor
223 i++
224 v, err := strconv.ParseUint(field[1], 0, 32)
225 if err != nil {
226 return nil, err
227 }
228 cpuinfo[i].Processor = uint(v)
229 case "BogoMIPS":
230 if i == -1 {
231 cpuinfo = append(cpuinfo, commonCPUInfo) // There is only one processor
232 i++
233 cpuinfo[i].Processor = 0
234 }
235 v, err := strconv.ParseFloat(field[1], 64)
236 if err != nil {
237 return nil, err
238 }
239 cpuinfo[i].BogoMips = v
240 case "Features":
241 featuresLine = line
242 case "model name":
243 cpuinfo[i].ModelName = field[1]
244 }
245 }
246 fields := strings.SplitN(featuresLine, ": ", 2)
247 for i := range cpuinfo {
248 cpuinfo[i].Flags = strings.Fields(fields[1])
249 }
250 return cpuinfo, nil
251
252}
253
254func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
255 scanner := bufio.NewScanner(bytes.NewReader(info))
256
257 firstLine := firstNonEmptyLine(scanner)
258 if !strings.HasPrefix(firstLine, "vendor_id") || !strings.Contains(firstLine, ":") {
259 return nil, errors.New("invalid cpuinfo file: " + firstLine)
260 }
261 field := strings.SplitN(firstLine, ": ", 2)
262 cpuinfo := []CPUInfo{}
263 commonCPUInfo := CPUInfo{VendorID: field[1]}
264
265 for scanner.Scan() {
266 line := scanner.Text()
267 if !strings.Contains(line, ":") {
268 continue
269 }
270 field := strings.SplitN(line, ": ", 2)
271 switch strings.TrimSpace(field[0]) {
272 case "bogomips per cpu":
273 v, err := strconv.ParseFloat(field[1], 64)
274 if err != nil {
275 return nil, err
276 }
277 commonCPUInfo.BogoMips = v
278 case "features":
279 commonCPUInfo.Flags = strings.Fields(field[1])
280 }
281 if strings.HasPrefix(line, "processor") {
282 match := cpuinfoS390XProcessorRegexp.FindStringSubmatch(line)
283 if len(match) < 2 {
284 return nil, errors.New("Invalid line found in cpuinfo: " + line)
285 }
286 cpu := commonCPUInfo
287 v, err := strconv.ParseUint(match[1], 0, 32)
288 if err != nil {
289 return nil, err
290 }
291 cpu.Processor = uint(v)
292 cpuinfo = append(cpuinfo, cpu)
293 }
294 if strings.HasPrefix(line, "cpu number") {
295 break
296 }
297 }
298
299 i := 0
300 for scanner.Scan() {
301 line := scanner.Text()
302 if !strings.Contains(line, ":") {
303 continue
304 }
305 field := strings.SplitN(line, ": ", 2)
306 switch strings.TrimSpace(field[0]) {
307 case "cpu number":
308 i++
309 case "cpu MHz dynamic":
310 clock := cpuinfoClockRegexp.FindString(strings.TrimSpace(field[1]))
311 v, err := strconv.ParseFloat(clock, 64)
312 if err != nil {
313 return nil, err
314 }
315 cpuinfo[i].CPUMHz = v
316 }
317 }
318
319 return cpuinfo, nil
320}
321
322func parseCPUInfoMips(info []byte) ([]CPUInfo, error) {
323 scanner := bufio.NewScanner(bytes.NewReader(info))
324
325 // find the first "processor" line
326 firstLine := firstNonEmptyLine(scanner)
327 if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") {
328 return nil, errors.New("invalid cpuinfo file: " + firstLine)
329 }
330 field := strings.SplitN(firstLine, ": ", 2)
331 cpuinfo := []CPUInfo{}
332 systemType := field[1]
333
334 i := 0
335
336 for scanner.Scan() {
337 line := scanner.Text()
338 if !strings.Contains(line, ":") {
339 continue
340 }
341 field := strings.SplitN(line, ": ", 2)
342 switch strings.TrimSpace(field[0]) {
343 case "processor":
344 v, err := strconv.ParseUint(field[1], 0, 32)
345 if err != nil {
346 return nil, err
347 }
348 i = int(v)
349 cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor
350 cpuinfo[i].Processor = uint(v)
351 cpuinfo[i].VendorID = systemType
352 case "cpu model":
353 cpuinfo[i].ModelName = field[1]
354 case "BogoMIPS":
355 v, err := strconv.ParseFloat(field[1], 64)
356 if err != nil {
357 return nil, err
358 }
359 cpuinfo[i].BogoMips = v
360 }
361 }
362 return cpuinfo, nil
363}
364
365func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
366 scanner := bufio.NewScanner(bytes.NewReader(info))
367
368 firstLine := firstNonEmptyLine(scanner)
369 if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
370 return nil, errors.New("invalid cpuinfo file: " + firstLine)
371 }
372 field := strings.SplitN(firstLine, ": ", 2)
373 v, err := strconv.ParseUint(field[1], 0, 32)
374 if err != nil {
375 return nil, err
376 }
377 firstcpu := CPUInfo{Processor: uint(v)}
378 cpuinfo := []CPUInfo{firstcpu}
379 i := 0
380
381 for scanner.Scan() {
382 line := scanner.Text()
383 if !strings.Contains(line, ":") {
384 continue
385 }
386 field := strings.SplitN(line, ": ", 2)
387 switch strings.TrimSpace(field[0]) {
388 case "processor":
389 cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor
390 i++
391 v, err := strconv.ParseUint(field[1], 0, 32)
392 if err != nil {
393 return nil, err
394 }
395 cpuinfo[i].Processor = uint(v)
396 case "cpu":
397 cpuinfo[i].VendorID = field[1]
398 case "clock":
399 clock := cpuinfoClockRegexp.FindString(strings.TrimSpace(field[1]))
400 v, err := strconv.ParseFloat(clock, 64)
401 if err != nil {
402 return nil, err
403 }
404 cpuinfo[i].CPUMHz = v
405 }
406 }
407 return cpuinfo, nil
408}
166 409
410// firstNonEmptyLine advances the scanner to the first non-empty line
411// and returns the contents of that line
412func firstNonEmptyLine(scanner *bufio.Scanner) string {
413 for scanner.Scan() {
414 line := scanner.Text()
415 if strings.TrimSpace(line) != "" {
416 return line
417 }
418 }
419 return ""
167} 420}