diff options
Diffstat (limited to 'vendor/github.com/prometheus/procfs/cpuinfo.go')
-rw-r--r-- | vendor/github.com/prometheus/procfs/cpuinfo.go | 265 |
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 | |||
14 | package procfs | 16 | package procfs |
15 | 17 | ||
16 | import ( | 18 | import ( |
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 | ||
59 | var ( | ||
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 |
57 | func (fs FS) CPUInfo() ([]CPUInfo, error) { | 66 | func (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 | 74 | func parseCPUInfoX86(info []byte) ([]CPUInfo, error) { |
66 | func 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 | |||
189 | func 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 | |||
254 | func 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 | |||
322 | func 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 | |||
365 | func 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 | ||
412 | func 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 | } |