1
2
3
4
5 package oshi.hardware.platform.linux;
6
7 import static oshi.software.os.linux.LinuxOperatingSystem.HAS_UDEV;
8 import static oshi.util.platform.linux.ProcPath.CPUINFO;
9 import static oshi.util.platform.linux.ProcPath.MODEL;
10
11 import java.io.File;
12 import java.io.IOException;
13 import java.nio.file.Files;
14 import java.nio.file.Path;
15 import java.nio.file.Paths;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.Comparator;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Locale;
24 import java.util.Map;
25 import java.util.Optional;
26 import java.util.Set;
27 import java.util.stream.Collectors;
28 import java.util.stream.LongStream;
29 import java.util.stream.Stream;
30
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.sun.jna.platform.linux.Udev;
35 import com.sun.jna.platform.linux.Udev.UdevContext;
36 import com.sun.jna.platform.linux.Udev.UdevDevice;
37 import com.sun.jna.platform.linux.Udev.UdevEnumerate;
38 import com.sun.jna.platform.linux.Udev.UdevListEntry;
39
40 import oshi.annotation.concurrent.ThreadSafe;
41 import oshi.driver.linux.Lshw;
42 import oshi.driver.linux.proc.CpuInfo;
43 import oshi.driver.linux.proc.CpuStat;
44 import oshi.hardware.CentralProcessor.ProcessorCache.Type;
45 import oshi.hardware.common.AbstractCentralProcessor;
46 import oshi.jna.platform.linux.LinuxLibc;
47 import oshi.software.os.linux.LinuxOperatingSystem;
48 import oshi.util.ExecutingCommand;
49 import oshi.util.FileUtil;
50 import oshi.util.ParseUtil;
51 import oshi.util.Util;
52 import oshi.util.platform.linux.SysPath;
53 import oshi.util.tuples.Quartet;
54
55
56
57
58 @ThreadSafe
59 final class LinuxCentralProcessor extends AbstractCentralProcessor {
60
61 private static final Logger LOG = LoggerFactory.getLogger(LinuxCentralProcessor.class);
62
63 @Override
64 protected ProcessorIdentifier queryProcessorId() {
65 String cpuVendor = "";
66 String cpuName = "";
67 String cpuFamily = "";
68 String cpuModel = "";
69 String cpuStepping = "";
70 String processorID;
71 long cpuFreq = 0L;
72 boolean cpu64bit = false;
73
74 StringBuilder armStepping = new StringBuilder();
75 String[] flags = new String[0];
76 List<String> cpuInfo = FileUtil.readFile(CPUINFO);
77 for (String line : cpuInfo) {
78 String[] splitLine = ParseUtil.whitespacesColonWhitespace.split(line);
79 if (splitLine.length < 2) {
80
81 if (line.startsWith("CPU architecture: ")) {
82 cpuFamily = line.replace("CPU architecture: ", "").trim();
83 }
84 continue;
85 }
86 switch (splitLine[0].toLowerCase(Locale.ROOT)) {
87 case "vendor_id":
88 case "cpu implementer":
89 cpuVendor = splitLine[1];
90 break;
91 case "model name":
92 case "processor":
93
94 if (!splitLine[1].matches("[0-9]+")) {
95 cpuName = splitLine[1];
96 }
97 break;
98 case "flags":
99 flags = splitLine[1].toLowerCase(Locale.ROOT).split(" ");
100 for (String flag : flags) {
101 if ("lm".equals(flag)) {
102 cpu64bit = true;
103 break;
104 }
105 }
106 break;
107 case "stepping":
108 cpuStepping = splitLine[1];
109 break;
110 case "cpu variant":
111 if (!armStepping.toString().startsWith("r")) {
112
113 int rev = ParseUtil.parseLastInt(splitLine[1], 0);
114 armStepping.insert(0, "r" + rev);
115 }
116 break;
117 case "cpu revision":
118 if (!armStepping.toString().contains("p")) {
119 armStepping.append('p').append(splitLine[1]);
120 }
121 break;
122 case "model":
123 case "cpu part":
124 cpuModel = splitLine[1];
125 break;
126 case "cpu family":
127 cpuFamily = splitLine[1];
128 break;
129 case "cpu mhz":
130 cpuFreq = ParseUtil.parseHertz(splitLine[1]);
131 break;
132 default:
133
134 }
135 }
136 if (cpuName.isEmpty()) {
137 cpuName = FileUtil.getStringFromFile(MODEL);
138 }
139 if (cpuName.contains("Hz")) {
140
141 cpuFreq = -1L;
142 } else {
143
144 long cpuCapacity = Lshw.queryCpuCapacity();
145 if (cpuCapacity > cpuFreq) {
146 cpuFreq = cpuCapacity;
147 }
148 }
149 if (cpuStepping.isEmpty()) {
150 cpuStepping = armStepping.toString();
151 }
152 processorID = getProcessorID(cpuVendor, cpuStepping, cpuModel, cpuFamily, flags);
153 if (cpuVendor.startsWith("0x") || cpuModel.isEmpty() || cpuName.isEmpty()) {
154 List<String> lscpu = ExecutingCommand.runNative("lscpu");
155 for (String line : lscpu) {
156 if (line.startsWith("Architecture:") && cpuVendor.startsWith("0x")) {
157 cpuVendor = line.replace("Architecture:", "").trim();
158 } else if (line.startsWith("Vendor ID:")) {
159 cpuVendor = line.replace("Vendor ID:", "").trim();
160 } else if (line.startsWith("Model name:")) {
161 String modelName = line.replace("Model name:", "").trim();
162 cpuModel = cpuModel.isEmpty() ? modelName : cpuModel;
163 cpuName = cpuName.isEmpty() ? modelName : cpuName;
164 }
165 }
166 }
167 return new ProcessorIdentifier(cpuVendor, cpuName, cpuFamily, cpuModel, cpuStepping, processorID, cpu64bit,
168 cpuFreq);
169 }
170
171 @Override
172 protected Quartet<List<LogicalProcessor>, List<PhysicalProcessor>, List<ProcessorCache>, List<String>> initProcessorCounts() {
173
174 Quartet<List<LogicalProcessor>, List<ProcessorCache>, Map<Integer, Integer>, Map<Integer, String>> topology = HAS_UDEV
175 ? readTopologyFromUdev()
176 : readTopologyFromSysfs();
177
178 if (topology.getA().isEmpty()) {
179 topology = readTopologyFromCpuinfo();
180 }
181 List<LogicalProcessor> logProcs = topology.getA();
182 List<ProcessorCache> caches = topology.getB();
183 Map<Integer, Integer> coreEfficiencyMap = topology.getC();
184 Map<Integer, String> modAliasMap = topology.getD();
185
186 if (logProcs.isEmpty()) {
187 logProcs.add(new LogicalProcessor(0, 0, 0));
188 }
189 if (coreEfficiencyMap.isEmpty()) {
190 coreEfficiencyMap.put(0, 0);
191 }
192
193 logProcs.sort(Comparator.comparingInt(LogicalProcessor::getProcessorNumber));
194
195 List<PhysicalProcessor> physProcs = coreEfficiencyMap.entrySet().stream().sorted(Map.Entry.comparingByKey())
196 .map(e -> {
197 int pkgId = e.getKey() >> 16;
198 int coreId = e.getKey() & 0xffff;
199 return new PhysicalProcessor(pkgId, coreId, e.getValue(), modAliasMap.getOrDefault(e.getKey(), ""));
200 }).collect(Collectors.toList());
201 List<String> featureFlags = CpuInfo.queryFeatureFlags();
202 return new Quartet<>(logProcs, physProcs, caches, featureFlags);
203 }
204
205 private static Quartet<List<LogicalProcessor>, List<ProcessorCache>, Map<Integer, Integer>, Map<Integer, String>> readTopologyFromUdev() {
206 List<LogicalProcessor> logProcs = new ArrayList<>();
207 Set<ProcessorCache> caches = new HashSet<>();
208 Map<Integer, Integer> coreEfficiencyMap = new HashMap<>();
209 Map<Integer, String> modAliasMap = new HashMap<>();
210
211 UdevContext udev = Udev.INSTANCE.udev_new();
212 try {
213 UdevEnumerate enumerate = udev.enumerateNew();
214 try {
215 enumerate.addMatchSubsystem("cpu");
216 enumerate.scanDevices();
217 for (UdevListEntry entry = enumerate.getListEntry(); entry != null; entry = entry.getNext()) {
218 String syspath = entry.getName();
219 UdevDevice device = udev.deviceNewFromSyspath(syspath);
220 String modAlias = null;
221 if (device != null) {
222 try {
223 modAlias = device.getPropertyValue("MODALIAS");
224 } finally {
225 device.unref();
226 }
227 }
228 logProcs.add(
229 getLogicalProcessorFromSyspath(syspath, caches, modAlias, coreEfficiencyMap, modAliasMap));
230 }
231 } finally {
232 enumerate.unref();
233 }
234 } finally {
235 udev.unref();
236 }
237 return new Quartet<>(logProcs, orderedProcCaches(caches), coreEfficiencyMap, modAliasMap);
238 }
239
240 private static Quartet<List<LogicalProcessor>, List<ProcessorCache>, Map<Integer, Integer>, Map<Integer, String>> readTopologyFromSysfs() {
241 List<LogicalProcessor> logProcs = new ArrayList<>();
242 Set<ProcessorCache> caches = new HashSet<>();
243 Map<Integer, Integer> coreEfficiencyMap = new HashMap<>();
244 Map<Integer, String> modAliasMap = new HashMap<>();
245 try {
246 try (Stream<Path> cpuFiles = Files.find(Paths.get(SysPath.CPU), Integer.MAX_VALUE,
247 (path, basicFileAttributes) -> path.toFile().getName().matches("cpu\\d+"))) {
248 cpuFiles.forEach(cpu -> {
249 String syspath = cpu.toString();
250 Map<String, String> uevent = FileUtil.getKeyValueMapFromFile(syspath + "/uevent", "=");
251 String modAlias = uevent.get("MODALIAS");
252
253 logProcs.add(
254 getLogicalProcessorFromSyspath(syspath, caches, modAlias, coreEfficiencyMap, modAliasMap));
255 });
256 }
257 } catch (IOException e) {
258
259 LOG.warn("Unable to find CPU information in sysfs at path {}", SysPath.CPU);
260 }
261 return new Quartet<>(logProcs, orderedProcCaches(caches), coreEfficiencyMap, modAliasMap);
262 }
263
264 private static LogicalProcessor getLogicalProcessorFromSyspath(String syspath, Set<ProcessorCache> caches,
265 String modAlias, Map<Integer, Integer> coreEfficiencyMap, Map<Integer, String> modAliasMap) {
266 int processor = ParseUtil.getFirstIntValue(syspath);
267 int coreId = FileUtil.getIntFromFile(syspath + "/topology/core_id");
268 int pkgId = FileUtil.getIntFromFile(syspath + "/topology/physical_package_id");
269 int pkgCoreKey = (pkgId << 16) + coreId;
270
271 coreEfficiencyMap.put(pkgCoreKey, FileUtil.getIntFromFile(syspath + "/cpu_capacity"));
272 if (!Util.isBlank(modAlias)) {
273 modAliasMap.put(pkgCoreKey, modAlias);
274 }
275 int nodeId = 0;
276 final String nodePrefix = syspath + "/node";
277 try (Stream<Path> path = Files.list(Paths.get(syspath))) {
278 Optional<Path> first = path.filter(p -> p.toString().startsWith(nodePrefix)).findFirst();
279 if (first.isPresent()) {
280 nodeId = ParseUtil.getFirstIntValue(first.get().getFileName().toString());
281 }
282 } catch (IOException e) {
283
284 }
285 final String cachePath = syspath + "/cache";
286 final String indexPrefix = cachePath + "/index";
287 try (Stream<Path> path = Files.list(Paths.get(cachePath))) {
288 path.filter(p -> p.toString().startsWith(indexPrefix)).forEach(c -> {
289 int level = FileUtil.getIntFromFile(c + "/level");
290 Type type = parseCacheType(FileUtil.getStringFromFile(c + "/type"));
291 int associativity = FileUtil.getIntFromFile(c + "/ways_of_associativity");
292 int lineSize = FileUtil.getIntFromFile(c + "/coherency_line_size");
293 long size = ParseUtil.parseDecimalMemorySizeToBinary(FileUtil.getStringFromFile(c + "/size"));
294 caches.add(new ProcessorCache(level, associativity, lineSize, size, type));
295 });
296 } catch (IOException e) {
297
298 }
299 return new LogicalProcessor(processor, coreId, pkgId, nodeId);
300 }
301
302 private static ProcessorCache.Type parseCacheType(String type) {
303 try {
304 return ProcessorCache.Type.valueOf(type.toUpperCase(Locale.ROOT));
305 } catch (IllegalArgumentException e) {
306 return ProcessorCache.Type.UNIFIED;
307 }
308 }
309
310 private static Quartet<List<LogicalProcessor>, List<ProcessorCache>, Map<Integer, Integer>, Map<Integer, String>> readTopologyFromCpuinfo() {
311 List<LogicalProcessor> logProcs = new ArrayList<>();
312 Set<ProcessorCache> caches = mapCachesFromLscpu();
313 Map<Integer, Integer> numaNodeMap = mapNumaNodesFromLscpu();
314 Map<Integer, Integer> coreEfficiencyMap = new HashMap<>();
315
316 List<String> procCpu = FileUtil.readFile(CPUINFO);
317 int currentProcessor = 0;
318 int currentCore = 0;
319 int currentPackage = 0;
320
321 boolean first = true;
322 for (String cpu : procCpu) {
323
324 if (cpu.startsWith("processor")) {
325 if (first) {
326 first = false;
327 } else {
328
329 logProcs.add(new LogicalProcessor(currentProcessor, currentCore, currentPackage,
330 numaNodeMap.getOrDefault(currentProcessor, 0)));
331
332 coreEfficiencyMap.put((currentPackage << 16) + currentCore, 0);
333 }
334
335 currentProcessor = ParseUtil.parseLastInt(cpu, 0);
336 } else if (cpu.startsWith("core id") || cpu.startsWith("cpu number")) {
337 currentCore = ParseUtil.parseLastInt(cpu, 0);
338 } else if (cpu.startsWith("physical id")) {
339 currentPackage = ParseUtil.parseLastInt(cpu, 0);
340 }
341 }
342 logProcs.add(new LogicalProcessor(currentProcessor, currentCore, currentPackage,
343 numaNodeMap.getOrDefault(currentProcessor, 0)));
344 coreEfficiencyMap.put((currentPackage << 16) + currentCore, 0);
345 return new Quartet<>(logProcs, orderedProcCaches(caches), coreEfficiencyMap, Collections.emptyMap());
346 }
347
348 private static Map<Integer, Integer> mapNumaNodesFromLscpu() {
349 Map<Integer, Integer> numaNodeMap = new HashMap<>();
350
351 List<String> lscpu = ExecutingCommand.runNative("lscpu -p=cpu,node");
352
353
354
355
356
357 for (String line : lscpu) {
358 if (!line.startsWith("#")) {
359 int pos = line.indexOf(',');
360 if (pos > 0 && pos < line.length()) {
361 numaNodeMap.put(ParseUtil.parseIntOrDefault(line.substring(0, pos), 0),
362 ParseUtil.parseIntOrDefault(line.substring(pos + 1), 0));
363 }
364 }
365 }
366 return numaNodeMap;
367 }
368
369 private static Set<ProcessorCache> mapCachesFromLscpu() {
370 Set<ProcessorCache> caches = new HashSet<>();
371 int level = 0;
372 Type type = null;
373 int associativity = 0;
374 int lineSize = 0;
375 long size = 0L;
376
377 List<String> lscpu = ExecutingCommand.runNative("lscpu -B -C --json");
378 for (String line : lscpu) {
379 String s = line.trim();
380 if (s.startsWith("}")) {
381
382 if (level > 0 && type != null) {
383 caches.add(new ProcessorCache(level, associativity, lineSize, size, type));
384 }
385 level = 0;
386 type = null;
387 associativity = 0;
388 lineSize = 0;
389 size = 0L;
390 } else if (s.contains("one-size")) {
391
392 String[] split = ParseUtil.notDigits.split(s);
393 if (split.length > 1) {
394 size = ParseUtil.parseLongOrDefault(split[1], 0L);
395 }
396 } else if (s.contains("ways")) {
397
398
399 String[] split = ParseUtil.notDigits.split(s);
400 if (split.length > 1) {
401 associativity = ParseUtil.parseIntOrDefault(split[1], 0);
402 }
403 } else if (s.contains("type")) {
404
405 String[] split = s.split("\"");
406 if (split.length > 2) {
407 type = parseCacheType(split[split.length - 2]);
408 }
409 } else if (s.contains("level")) {
410
411 String[] split = ParseUtil.notDigits.split(s);
412 if (split.length > 1) {
413 level = ParseUtil.parseIntOrDefault(split[1], 0);
414 }
415 } else if (s.contains("coherency-size")) {
416
417 String[] split = ParseUtil.notDigits.split(s);
418 if (split.length > 1) {
419 lineSize = ParseUtil.parseIntOrDefault(split[1], 0);
420 }
421 }
422 }
423 return caches;
424 }
425
426 @Override
427 public long[] querySystemCpuLoadTicks() {
428
429 long[] ticks = CpuStat.getSystemCpuLoadTicks();
430
431 if (LongStream.of(ticks).sum() == 0) {
432 ticks = CpuStat.getSystemCpuLoadTicks();
433 }
434 long hz = LinuxOperatingSystem.getHz();
435 for (int i = 0; i < ticks.length; i++) {
436 ticks[i] = ticks[i] * 1000L / hz;
437 }
438 return ticks;
439 }
440
441 @Override
442 public long[] queryCurrentFreq() {
443 long[] freqs = new long[getLogicalProcessorCount()];
444
445 long max = 0L;
446 UdevContext udev = Udev.INSTANCE.udev_new();
447 try {
448 UdevEnumerate enumerate = udev.enumerateNew();
449 try {
450 enumerate.addMatchSubsystem("cpu");
451 enumerate.scanDevices();
452 for (UdevListEntry entry = enumerate.getListEntry(); entry != null; entry = entry.getNext()) {
453 String syspath = entry.getName();
454 int cpu = ParseUtil.getFirstIntValue(syspath);
455 if (cpu >= 0 && cpu < freqs.length) {
456 freqs[cpu] = FileUtil.getLongFromFile(syspath + "/cpufreq/scaling_cur_freq");
457 if (freqs[cpu] == 0) {
458 freqs[cpu] = FileUtil.getLongFromFile(syspath + "/cpufreq/cpuinfo_cur_freq");
459 }
460 }
461 if (max < freqs[cpu]) {
462 max = freqs[cpu];
463 }
464 }
465 if (max > 0L) {
466
467 for (int i = 0; i < freqs.length; i++) {
468 freqs[i] *= 1000L;
469 }
470 return freqs;
471 }
472 } finally {
473 enumerate.unref();
474 }
475 } finally {
476 udev.unref();
477 }
478
479 Arrays.fill(freqs, -1);
480 List<String> cpuInfo = FileUtil.readFile(CPUINFO);
481 int proc = 0;
482 for (String s : cpuInfo) {
483 if (s.toLowerCase(Locale.ROOT).contains("cpu mhz")) {
484 freqs[proc] = Math.round(ParseUtil.parseLastDouble(s, 0d) * 1_000_000d);
485 if (++proc >= freqs.length) {
486 break;
487 }
488 }
489 }
490 return freqs;
491 }
492
493 @Override
494 public long queryMaxFreq() {
495 long policyMax = -1L;
496
497 UdevContext udev = Udev.INSTANCE.udev_new();
498 try {
499 UdevEnumerate enumerate = udev.enumerateNew();
500 try {
501 enumerate.addMatchSubsystem("cpu");
502 enumerate.scanDevices();
503
504
505 UdevListEntry entry = enumerate.getListEntry();
506 if (entry != null) {
507 String syspath = entry.getName();
508 String cpuFreqPath = syspath.substring(0, syspath.lastIndexOf(File.separatorChar)) + "/cpufreq";
509 String policyPrefix = cpuFreqPath + "/policy";
510 try (Stream<Path> path = Files.list(Paths.get(cpuFreqPath))) {
511 Optional<Long> maxPolicy = path.filter(p -> p.toString().startsWith(policyPrefix)).map(p -> {
512 long freq = FileUtil.getLongFromFile(p.toString() + "/scaling_max_freq");
513 if (freq == 0) {
514 freq = FileUtil.getLongFromFile(p.toString() + "/cpuinfo_max_freq");
515 }
516 return freq;
517 }).max(Long::compare);
518 if (maxPolicy.isPresent()) {
519
520 policyMax = maxPolicy.get() * 1000L;
521 }
522 } catch (IOException e) {
523
524 }
525 }
526 } finally {
527 enumerate.unref();
528 }
529 } finally {
530 udev.unref();
531 }
532
533 long lshwMax = Lshw.queryCpuCapacity();
534
535 return LongStream.concat(LongStream.of(policyMax, lshwMax), Arrays.stream(this.getCurrentFreq())).max()
536 .orElse(-1L);
537 }
538
539 @Override
540 public double[] getSystemLoadAverage(int nelem) {
541 if (nelem < 1 || nelem > 3) {
542 throw new IllegalArgumentException("Must include from one to three elements.");
543 }
544 double[] average = new double[nelem];
545 int retval = LinuxLibc.INSTANCE.getloadavg(average, nelem);
546 if (retval < nelem) {
547 for (int i = Math.max(retval, 0); i < average.length; i++) {
548 average[i] = -1d;
549 }
550 }
551 return average;
552 }
553
554 @Override
555 public long[][] queryProcessorCpuLoadTicks() {
556 long[][] ticks = CpuStat.getProcessorCpuLoadTicks(getLogicalProcessorCount());
557
558
559
560 if (LongStream.of(ticks[0]).sum() == 0) {
561 ticks = CpuStat.getProcessorCpuLoadTicks(getLogicalProcessorCount());
562 }
563
564 long hz = LinuxOperatingSystem.getHz();
565 for (int i = 0; i < ticks.length; i++) {
566 for (int j = 0; j < ticks[i].length; j++) {
567 ticks[i][j] = ticks[i][j] * 1000L / hz;
568 }
569 }
570 return ticks;
571 }
572
573
574
575
576
577
578
579
580
581
582
583
584 private static String getProcessorID(String vendor, String stepping, String model, String family, String[] flags) {
585 boolean procInfo = false;
586 String marker = "Processor Information";
587 for (String checkLine : ExecutingCommand.runNative("dmidecode -t 4")) {
588 if (!procInfo && checkLine.contains(marker)) {
589 marker = "ID:";
590 procInfo = true;
591 } else if (procInfo && checkLine.contains(marker)) {
592 return checkLine.split(marker)[1].trim();
593 }
594 }
595
596 marker = "eax=";
597 for (String checkLine : ExecutingCommand.runNative("cpuid -1r")) {
598 if (checkLine.contains(marker) && checkLine.trim().startsWith("0x00000001")) {
599 String eax = "";
600 String edx = "";
601 for (String register : ParseUtil.whitespaces.split(checkLine)) {
602 if (register.startsWith("eax=")) {
603 eax = ParseUtil.removeMatchingString(register, "eax=0x");
604 } else if (register.startsWith("edx=")) {
605 edx = ParseUtil.removeMatchingString(register, "edx=0x");
606 }
607 }
608 return edx + eax;
609 }
610 }
611
612 if (vendor.startsWith("0x")) {
613 return createMIDR(vendor, stepping, model, family) + "00000000";
614 }
615 return createProcessorID(stepping, model, family, flags);
616 }
617
618
619
620
621
622
623
624
625
626
627 private static String createMIDR(String vendor, String stepping, String model, String family) {
628 int midrBytes = 0;
629
630 if (stepping.startsWith("r") && stepping.contains("p")) {
631 String[] rev = stepping.substring(1).split("p");
632
633 midrBytes |= ParseUtil.parseLastInt(rev[1], 0);
634
635 midrBytes |= ParseUtil.parseLastInt(rev[0], 0) << 20;
636 }
637
638 midrBytes |= ParseUtil.parseLastInt(model, 0) << 4;
639
640 midrBytes |= ParseUtil.parseLastInt(family, 0) << 16;
641
642 midrBytes |= ParseUtil.parseLastInt(vendor, 0) << 24;
643
644 return String.format(Locale.ROOT, "%08X", midrBytes);
645 }
646
647 @Override
648 public long queryContextSwitches() {
649 return CpuStat.getContextSwitches();
650 }
651
652 @Override
653 public long queryInterrupts() {
654 return CpuStat.getInterrupts();
655 }
656 }