1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package oshi.software.os.mac.local;
18
19 import java.lang.management.ManagementFactory;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import oshi.hardware.Processor;
24 import oshi.software.os.mac.local.SystemB.HostCpuLoadInfo;
25 import oshi.util.FormatUtil;
26 import oshi.util.ParseUtil;
27
28 import com.sun.jna.LastErrorException;
29 import com.sun.jna.Memory;
30 import com.sun.jna.Native;
31 import com.sun.jna.Pointer;
32 import com.sun.jna.ptr.IntByReference;
33 import com.sun.jna.ptr.PointerByReference;
34
35
36
37
38
39
40
41
42 @SuppressWarnings("restriction")
43 public class CentralProcessor implements Processor {
44 private static final java.lang.management.OperatingSystemMXBean OS_MXBEAN = ManagementFactory
45 .getOperatingSystemMXBean();;
46 private static boolean sunMXBean;
47 static {
48 try {
49 Class.forName("com.sun.management.OperatingSystemMXBean");
50
51 ((com.sun.management.OperatingSystemMXBean) OS_MXBEAN)
52 .getSystemCpuLoad();
53 sunMXBean = true;
54 } catch (ClassNotFoundException e) {
55 sunMXBean = false;
56 }
57 }
58
59
60
61 private static long tickTime = System.currentTimeMillis();
62 private static long[] prevTicks = new long[4];
63 private static long[] curTicks = new long[4];
64 static {
65 updateSystemTicks();
66 System.arraycopy(curTicks, 0, prevTicks, 0, curTicks.length);
67 }
68
69
70 private long procTickTime = System.currentTimeMillis();
71 private long[] prevProcTicks = new long[4];
72 private long[] curProcTicks = new long[4];
73
74
75 private static int numCPU = 0;
76 static {
77 IntByReference size = new IntByReference(SystemB.INT_SIZE);
78 Pointer p = new Memory(size.getValue());
79 if (0 != SystemB.INSTANCE.sysctlbyname("hw.logicalcpu", p, size, null,
80 0))
81 throw new LastErrorException("Error code: " + Native.getLastError());
82 numCPU = p.getInt(0);
83 }
84
85
86
87 private static long[][] allProcessorTicks = new long[numCPU][4];
88 private static long allProcTickTime = 0;
89
90 private int processorNumber;
91 private String cpuVendor;
92 private String cpuName;
93 private String cpuIdentifier = null;
94 private String cpuStepping;
95 private String cpuModel;
96 private String cpuFamily;
97 private Long cpuVendorFreq = null;
98 private Boolean cpu64;
99
100
101
102
103
104
105 public CentralProcessor(int procNo) {
106 if (procNo >= numCPU)
107 throw new IllegalArgumentException("Processor number (" + procNo
108 + ") must be less than the number of CPUs: " + numCPU);
109 this.processorNumber = procNo;
110 updateProcessorTicks();
111 System.arraycopy(allProcessorTicks[processorNumber], 0, curProcTicks,
112 0, curProcTicks.length);
113 }
114
115
116
117
118 @Override
119 public int getProcessorNumber() {
120 return processorNumber;
121 }
122
123
124
125
126
127
128 @Override
129 public String getVendor() {
130 if (this.cpuVendor == null) {
131 int[] mib = { SystemB.CTL_MACHDEP, SystemB.MACHDEP_CPU,
132 SystemB.MACHDEP_CPU_VENDOR };
133 IntByReference size = new IntByReference();
134 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, null, size, null,
135 0))
136 throw new LastErrorException("Error code: "
137 + Native.getLastError());
138 Pointer p = new Memory(size.getValue() + 1);
139 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
140 throw new LastErrorException("Error code: "
141 + Native.getLastError());
142 this.cpuVendor = p.getString(0);
143 }
144 return this.cpuVendor;
145 }
146
147
148
149
150
151
152
153 @Override
154 public void setVendor(String vendor) {
155 this.cpuVendor = vendor;
156 }
157
158
159
160
161
162
163 @Override
164 public String getName() {
165 if (this.cpuName == null) {
166 int[] mib = { SystemB.CTL_MACHDEP, SystemB.MACHDEP_CPU,
167 SystemB.MACHDEP_CPU_BRAND_STRING };
168 IntByReference size = new IntByReference();
169 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, null, size, null,
170 0))
171 throw new LastErrorException("Error code: "
172 + Native.getLastError());
173 Pointer p = new Memory(size.getValue() + 1);
174 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
175 throw new LastErrorException("Error code: "
176 + Native.getLastError());
177 this.cpuName = p.getString(0);
178 }
179 return this.cpuName;
180 }
181
182
183
184
185
186
187
188 @Override
189 public void setName(String name) {
190 this.cpuName = name;
191 }
192
193
194
195
196
197
198
199 @Override
200 public long getVendorFreq() {
201 if (this.cpuVendorFreq == null) {
202 Pattern pattern = Pattern.compile("@ (.*)$");
203 Matcher matcher = pattern.matcher(getName());
204
205 if (matcher.find()) {
206 String unit = matcher.group(1);
207 this.cpuVendorFreq = Long.valueOf(ParseUtil.parseHertz(unit));
208 } else {
209 this.cpuVendorFreq = Long.valueOf(-1L);
210 }
211 }
212
213 return this.cpuVendorFreq.longValue();
214 }
215
216
217
218
219
220
221
222 @Override
223 public void setVendorFreq(long freq) {
224 this.cpuVendorFreq = Long.valueOf(freq);
225 }
226
227
228
229
230
231
232 @Override
233 public String getIdentifier() {
234 if (this.cpuIdentifier == null) {
235 StringBuilder sb = new StringBuilder();
236 if (getVendor().contentEquals("GenuineIntel"))
237 sb.append(isCpu64bit() ? "Intel64" : "x86");
238 else
239 sb.append(getVendor());
240 sb.append(" Family ").append(getFamily());
241 sb.append(" Model ").append(getModel());
242 sb.append(" Stepping ").append(getStepping());
243 this.cpuIdentifier = sb.toString();
244 }
245 return this.cpuIdentifier;
246 }
247
248
249
250
251
252
253
254 @Override
255 public void setIdentifier(String identifier) {
256 this.cpuIdentifier = identifier;
257 }
258
259
260
261
262
263
264 @Override
265 public boolean isCpu64bit() {
266 if (this.cpu64 == null) {
267 int[] mib = { SystemB.CTL_HW, SystemB.HW_CPU64BIT_CAPABLE };
268 IntByReference size = new IntByReference(SystemB.INT_SIZE);
269 Pointer p = new Memory(size.getValue());
270 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
271 throw new LastErrorException("Error code: "
272 + Native.getLastError());
273 this.cpu64 = p.getInt(0) != 0;
274 }
275 return this.cpu64.booleanValue();
276 }
277
278
279
280
281
282
283
284 @Override
285 public void setCpu64(boolean cpu64) {
286 this.cpu64 = Boolean.valueOf(cpu64);
287 }
288
289
290
291
292 @Override
293 public String getStepping() {
294 if (this.cpuStepping == null) {
295 int[] mib = { SystemB.CTL_MACHDEP, SystemB.MACHDEP_CPU,
296 SystemB.MACHDEP_CPU_STEPPING };
297 IntByReference size = new IntByReference(SystemB.INT_SIZE);
298 Pointer p = new Memory(size.getValue());
299 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
300 throw new LastErrorException("Error code: "
301 + Native.getLastError());
302 this.cpuStepping = Integer.toString(p.getInt(0));
303 }
304 return this.cpuStepping;
305 }
306
307
308
309
310
311 @Override
312 public void setStepping(String stepping) {
313 this.cpuStepping = stepping;
314 }
315
316
317
318
319 @Override
320 public String getModel() {
321 if (this.cpuModel == null) {
322 int[] mib = { SystemB.CTL_MACHDEP, SystemB.MACHDEP_CPU,
323 SystemB.MACHDEP_CPU_MODEL };
324 IntByReference size = new IntByReference(SystemB.INT_SIZE);
325 Pointer p = new Memory(size.getValue());
326 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
327 throw new LastErrorException("Error code: "
328 + Native.getLastError());
329 this.cpuModel = Integer.toString(p.getInt(0));
330 }
331 return this.cpuModel;
332 }
333
334
335
336
337
338 @Override
339 public void setModel(String model) {
340 this.cpuModel = model;
341 }
342
343
344
345
346 @Override
347 public String getFamily() {
348 if (this.cpuFamily == null) {
349 int[] mib = { SystemB.CTL_MACHDEP, SystemB.MACHDEP_CPU,
350 SystemB.MACHDEP_CPU_FAMILY };
351 IntByReference size = new IntByReference(SystemB.INT_SIZE);
352 Pointer p = new Memory(size.getValue());
353 if (0 != SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0))
354 throw new LastErrorException("Error code: "
355 + Native.getLastError());
356 this.cpuFamily = Integer.toString(p.getInt(0));
357 }
358 return this.cpuFamily;
359 }
360
361
362
363
364
365 @Override
366 public void setFamily(String family) {
367 this.cpuFamily = family;
368 }
369
370
371
372
373 @Override
374 @Deprecated
375 public float getLoad() {
376
377 return (float) getSystemCpuLoadBetweenTicks() * 100;
378 }
379
380
381
382
383 @Override
384 public double getSystemCpuLoadBetweenTicks() {
385
386 long now = System.currentTimeMillis();
387 boolean update = (now - tickTime > 950);
388 if (update) {
389
390
391 updateSystemTicks();
392 tickTime = now;
393 }
394
395 long total = 0;
396 for (int i = 0; i < curTicks.length; i++) {
397 total += (curTicks[i] - prevTicks[i]);
398 }
399
400 long idle = curTicks[3] - prevTicks[3];
401
402
403 if (update) {
404 System.arraycopy(curTicks, 0, prevTicks, 0, curTicks.length);
405 }
406
407
408 if (total > 0 && idle >= 0) {
409 return (double) (total - idle) / total;
410 }
411 return 0d;
412 }
413
414
415
416
417 @Override
418 public long[] getSystemCpuLoadTicks() {
419 updateSystemTicks();
420
421 long[] ticks = new long[curTicks.length];
422 System.arraycopy(curTicks, 0, ticks, 0, curTicks.length);
423 return ticks;
424 }
425
426
427
428
429
430
431
432
433
434
435
436 private static void updateSystemTicks() {
437 int machPort = SystemB.INSTANCE.mach_host_self();
438 HostCpuLoadInfo cpuLoadInfo = new HostCpuLoadInfo();
439 if (0 != SystemB.INSTANCE.host_statistics(machPort,
440 SystemB.HOST_CPU_LOAD_INFO, cpuLoadInfo, new IntByReference(
441 cpuLoadInfo.size())))
442 throw new LastErrorException("Error code: " + Native.getLastError());
443
444 curTicks[0] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_USER];
445 curTicks[1] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_NICE];
446 curTicks[2] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_SYSTEM];
447 curTicks[3] = cpuLoadInfo.cpu_ticks[SystemB.CPU_STATE_IDLE];
448 }
449
450
451
452
453 @Override
454 public double getSystemCpuLoad() {
455 if (sunMXBean) {
456 return ((com.sun.management.OperatingSystemMXBean) OS_MXBEAN)
457 .getSystemCpuLoad();
458 }
459 return getSystemCpuLoadBetweenTicks();
460 }
461
462
463
464
465 @Override
466 public double getSystemLoadAverage() {
467 return OS_MXBEAN.getSystemLoadAverage();
468 }
469
470
471
472
473 @Override
474 public double getProcessorCpuLoadBetweenTicks() {
475
476 long now = System.currentTimeMillis();
477 if (now - procTickTime > 950) {
478
479 updateProcessorTicks();
480
481 System.arraycopy(curProcTicks, 0, prevProcTicks, 0,
482 curProcTicks.length);
483 System.arraycopy(allProcessorTicks[processorNumber], 0,
484 curProcTicks, 0, curProcTicks.length);
485 procTickTime = now;
486 }
487 long total = 0;
488 for (int i = 0; i < curProcTicks.length; i++) {
489 total += (curProcTicks[i] - prevProcTicks[i]);
490 }
491
492 long idle = curProcTicks[3] - prevProcTicks[3];
493
494 return (total > 0 && idle >= 0) ? (double) (total - idle) / total : 0d;
495 }
496
497
498
499
500 public long[] getProcessorCpuLoadTicks() {
501 updateProcessorTicks();
502 return allProcessorTicks[processorNumber];
503 }
504
505
506
507
508
509
510
511 private static void updateProcessorTicks() {
512
513
514 long now = System.currentTimeMillis();
515 if (now - allProcTickTime < 100)
516 return;
517
518 int machPort = SystemB.INSTANCE.mach_host_self();
519
520 IntByReference procCount = new IntByReference();
521 PointerByReference procCpuLoadInfo = new PointerByReference();
522 IntByReference procInfoCount = new IntByReference();
523 if (0 != SystemB.INSTANCE.host_processor_info(machPort,
524 SystemB.PROCESSOR_CPU_LOAD_INFO, procCount, procCpuLoadInfo,
525 procInfoCount))
526 throw new LastErrorException("Error code: " + Native.getLastError());
527
528 int[] cpuTicks = procCpuLoadInfo.getValue().getIntArray(0,
529 procInfoCount.getValue());
530 for (int cpu = 0; cpu < procCount.getValue(); cpu++) {
531 for (int j = 0; j < 4; j++) {
532 int offset = cpu * SystemB.CPU_STATE_MAX;
533 allProcessorTicks[cpu][0] = FormatUtil
534 .getUnsignedInt(cpuTicks[offset
535 + SystemB.CPU_STATE_USER]);
536 allProcessorTicks[cpu][1] = FormatUtil
537 .getUnsignedInt(cpuTicks[offset
538 + SystemB.CPU_STATE_NICE]);
539 allProcessorTicks[cpu][2] = FormatUtil
540 .getUnsignedInt(cpuTicks[offset
541 + SystemB.CPU_STATE_SYSTEM]);
542 allProcessorTicks[cpu][3] = FormatUtil
543 .getUnsignedInt(cpuTicks[offset
544 + SystemB.CPU_STATE_IDLE]);
545 }
546 }
547 allProcTickTime = now;
548 }
549
550 @Override
551 public String toString() {
552 return getName();
553 }
554 }