1
2
3
4
5 package oshi.hardware.platform.unix.aix;
6
7 import static oshi.util.Memoizer.defaultExpiration;
8 import static oshi.util.Memoizer.memoize;
9
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.function.Supplier;
16
17 import com.sun.jna.Native;
18 import com.sun.jna.platform.unix.aix.Perfstat.perfstat_cpu_t;
19 import com.sun.jna.platform.unix.aix.Perfstat.perfstat_cpu_total_t;
20 import com.sun.jna.platform.unix.aix.Perfstat.perfstat_partition_config_t;
21
22 import oshi.annotation.concurrent.ThreadSafe;
23 import oshi.driver.unix.aix.Lssrad;
24 import oshi.driver.unix.aix.perfstat.PerfstatConfig;
25 import oshi.driver.unix.aix.perfstat.PerfstatCpu;
26 import oshi.hardware.CentralProcessor.ProcessorCache.Type;
27 import oshi.hardware.common.AbstractCentralProcessor;
28 import oshi.util.Constants;
29 import oshi.util.ExecutingCommand;
30 import oshi.util.FileUtil;
31 import oshi.util.ParseUtil;
32 import oshi.util.tuples.Pair;
33 import oshi.util.tuples.Quartet;
34
35
36
37
38 @ThreadSafe
39 final class AixCentralProcessor extends AbstractCentralProcessor {
40
41 private final Supplier<perfstat_cpu_total_t> cpuTotal = memoize(PerfstatCpu::queryCpuTotal, defaultExpiration());
42 private final Supplier<perfstat_cpu_t[]> cpuProc = memoize(PerfstatCpu::queryCpu, defaultExpiration());
43 private static final int SBITS = querySbits();
44
45 private perfstat_partition_config_t config;
46
47
48
49
50 private static final long USER_HZ = ParseUtil.parseLongOrDefault(ExecutingCommand.getFirstAnswer("getconf CLK_TCK"),
51 100L);
52
53 @Override
54 protected ProcessorIdentifier queryProcessorId() {
55 String cpuVendor = Constants.UNKNOWN;
56 String cpuName = "";
57 String cpuFamily = "";
58 boolean cpu64bit = false;
59
60 final String nameMarker = "Processor Type:";
61 final String familyMarker = "Processor Version:";
62 final String bitnessMarker = "CPU Type:";
63 for (final String checkLine : ExecutingCommand.runNative("prtconf")) {
64 if (checkLine.startsWith(nameMarker)) {
65 cpuName = checkLine.split(nameMarker)[1].trim();
66 if (cpuName.startsWith("P")) {
67 cpuVendor = "IBM";
68 } else if (cpuName.startsWith("I")) {
69 cpuVendor = "Intel";
70 }
71 } else if (checkLine.startsWith(familyMarker)) {
72 cpuFamily = checkLine.split(familyMarker)[1].trim();
73 } else if (checkLine.startsWith(bitnessMarker)) {
74 cpu64bit = checkLine.split(bitnessMarker)[1].contains("64");
75 }
76 }
77
78 String cpuModel = "";
79 String cpuStepping = "";
80 String machineId = Native.toString(config.machineID);
81 if (machineId.isEmpty()) {
82 machineId = ExecutingCommand.getFirstAnswer("uname -m");
83 }
84
85 if (machineId.length() > 10) {
86 int m = machineId.length() - 4;
87 int s = machineId.length() - 2;
88 cpuModel = machineId.substring(m, s);
89 cpuStepping = machineId.substring(s);
90 }
91
92 return new ProcessorIdentifier(cpuVendor, cpuName, cpuFamily, cpuModel, cpuStepping, machineId, cpu64bit,
93 (long) (config.processorMHz * 1_000_000L));
94 }
95
96 @Override
97 protected Quartet<List<LogicalProcessor>, List<PhysicalProcessor>, List<ProcessorCache>, List<String>> initProcessorCounts() {
98 this.config = PerfstatConfig.queryConfig();
99
100
101 int physProcs = (int) config.numProcessors.max;
102 if (physProcs < 1) {
103 physProcs = 1;
104 }
105 int lcpus = (int) config.vcpus.max;
106 if (lcpus < 1) {
107 lcpus = 1;
108 }
109
110 if (physProcs > lcpus) {
111 physProcs = lcpus;
112 }
113 int lpPerPp = lcpus / physProcs;
114
115 Map<Integer, Pair<Integer, Integer>> nodePkgMap = Lssrad.queryNodesPackages();
116 List<LogicalProcessor> logProcs = new ArrayList<>();
117 for (int proc = 0; proc < lcpus; proc++) {
118 Pair<Integer, Integer> nodePkg = nodePkgMap.get(proc);
119 int physProc = proc / lpPerPp;
120 logProcs.add(new LogicalProcessor(proc, physProc, nodePkg == null ? 0 : nodePkg.getB(),
121 nodePkg == null ? 0 : nodePkg.getA()));
122 }
123 return new Quartet<>(logProcs, null, getCachesForModel(physProcs), Collections.emptyList());
124 }
125
126 private List<ProcessorCache> getCachesForModel(int cores) {
127
128
129 List<ProcessorCache> caches = new ArrayList<>();
130 int powerVersion = ParseUtil.getFirstIntValue(ExecutingCommand.getFirstAnswer("uname -n"));
131 switch (powerVersion) {
132 case 7:
133 caches.add(new ProcessorCache(3, 8, 128, (2 * 32) << 20, Type.UNIFIED));
134 caches.add(new ProcessorCache(2, 8, 128, 256 << 10, Type.UNIFIED));
135 caches.add(new ProcessorCache(1, 8, 128, 32 << 10, Type.DATA));
136 caches.add(new ProcessorCache(1, 4, 128, 32 << 10, Type.INSTRUCTION));
137 break;
138 case 8:
139 caches.add(new ProcessorCache(4, 8, 128, (16 * 16) << 20, Type.UNIFIED));
140 caches.add(new ProcessorCache(3, 8, 128, 40 << 20, Type.UNIFIED));
141 caches.add(new ProcessorCache(2, 8, 128, 512 << 10, Type.UNIFIED));
142 caches.add(new ProcessorCache(1, 8, 128, 64 << 10, Type.DATA));
143 caches.add(new ProcessorCache(1, 8, 128, 32 << 10, Type.INSTRUCTION));
144 break;
145 case 9:
146 caches.add(new ProcessorCache(3, 20, 128, (cores * 10) << 20, Type.UNIFIED));
147 caches.add(new ProcessorCache(2, 8, 128, 512 << 10, Type.UNIFIED));
148 caches.add(new ProcessorCache(1, 8, 128, 32 << 10, Type.DATA));
149 caches.add(new ProcessorCache(1, 8, 128, 32 << 10, Type.INSTRUCTION));
150 break;
151 default:
152
153 }
154 return caches;
155 }
156
157 @Override
158 public long[] querySystemCpuLoadTicks() {
159 perfstat_cpu_total_t perfstat = cpuTotal.get();
160 long[] ticks = new long[TickType.values().length];
161 ticks[TickType.USER.ordinal()] = perfstat.user * 1000L / USER_HZ;
162
163 ticks[TickType.SYSTEM.ordinal()] = perfstat.sys * 1000L / USER_HZ;
164 ticks[TickType.IDLE.ordinal()] = perfstat.idle * 1000L / USER_HZ;
165 ticks[TickType.IOWAIT.ordinal()] = perfstat.wait * 1000L / USER_HZ;
166 ticks[TickType.IRQ.ordinal()] = perfstat.devintrs * 1000L / USER_HZ;
167 ticks[TickType.SOFTIRQ.ordinal()] = perfstat.softintrs * 1000L / USER_HZ;
168 ticks[TickType.STEAL.ordinal()] = (perfstat.idle_stolen_purr + perfstat.busy_stolen_purr) * 1000L / USER_HZ;
169 return ticks;
170 }
171
172 @Override
173 public long[] queryCurrentFreq() {
174
175
176
177
178
179
180
181
182
183
184
185 long[] freqs = new long[getLogicalProcessorCount()];
186 Arrays.fill(freqs, -1);
187 String freqMarker = "runs at";
188 int idx = 0;
189 for (final String checkLine : ExecutingCommand.runNative("pmcycles -m")) {
190 if (checkLine.contains(freqMarker)) {
191 freqs[idx++] = ParseUtil.parseHertz(checkLine.split(freqMarker)[1].trim());
192 if (idx >= freqs.length) {
193 break;
194 }
195 }
196 }
197 return freqs;
198 }
199
200 @Override
201 protected long queryMaxFreq() {
202 perfstat_cpu_total_t perfstat = cpuTotal.get();
203 return perfstat.processorHZ;
204 }
205
206 @Override
207 public double[] getSystemLoadAverage(int nelem) {
208 if (nelem < 1 || nelem > 3) {
209 throw new IllegalArgumentException("Must include from one to three elements.");
210 }
211 double[] average = new double[nelem];
212 long[] loadavg = cpuTotal.get().loadavg;
213 for (int i = 0; i < nelem; i++) {
214 average[i] = loadavg[i] / (double) (1L << SBITS);
215 }
216 return average;
217 }
218
219 @Override
220 public long[][] queryProcessorCpuLoadTicks() {
221 perfstat_cpu_t[] cpu = cpuProc.get();
222
223 long[][] ticks = new long[cpu.length][TickType.values().length];
224 for (int i = 0; i < cpu.length; i++) {
225 ticks[i] = new long[TickType.values().length];
226 ticks[i][TickType.USER.ordinal()] = cpu[i].user * 1000L / USER_HZ;
227
228 ticks[i][TickType.SYSTEM.ordinal()] = cpu[i].sys * 1000L / USER_HZ;
229 ticks[i][TickType.IDLE.ordinal()] = cpu[i].idle * 1000L / USER_HZ;
230 ticks[i][TickType.IOWAIT.ordinal()] = cpu[i].wait * 1000L / USER_HZ;
231 ticks[i][TickType.IRQ.ordinal()] = cpu[i].devintrs * 1000L / USER_HZ;
232 ticks[i][TickType.SOFTIRQ.ordinal()] = cpu[i].softintrs * 1000L / USER_HZ;
233 ticks[i][TickType.STEAL.ordinal()] = (cpu[i].idle_stolen_purr + cpu[i].busy_stolen_purr) * 1000L / USER_HZ;
234 }
235 return ticks;
236 }
237
238 @Override
239 public long queryContextSwitches() {
240 return cpuTotal.get().pswitch;
241 }
242
243 @Override
244 public long queryInterrupts() {
245 perfstat_cpu_total_t cpu = cpuTotal.get();
246 return cpu.devintrs + cpu.softintrs;
247 }
248
249 private static int querySbits() {
250
251 for (String s : FileUtil.readFile("/usr/include/sys/proc.h")) {
252 if (s.contains("SBITS") && s.contains("#define")) {
253 return ParseUtil.parseLastInt(s, 16);
254 }
255 }
256 return 16;
257 }
258 }