1
2
3
4
5 package oshi.driver.windows;
6
7 import static oshi.hardware.common.AbstractCentralProcessor.orderedProcCaches;
8
9 import java.util.ArrayList;
10 import java.util.Comparator;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import com.sun.jna.platform.win32.Kernel32Util;
18 import com.sun.jna.platform.win32.VersionHelpers;
19 import com.sun.jna.platform.win32.WinNT;
20 import com.sun.jna.platform.win32.WinNT.CACHE_RELATIONSHIP;
21 import com.sun.jna.platform.win32.WinNT.GROUP_AFFINITY;
22 import com.sun.jna.platform.win32.WinNT.LOGICAL_PROCESSOR_RELATIONSHIP;
23 import com.sun.jna.platform.win32.WinNT.NUMA_NODE_RELATIONSHIP;
24 import com.sun.jna.platform.win32.WinNT.PROCESSOR_RELATIONSHIP;
25 import com.sun.jna.platform.win32.WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
26 import com.sun.jna.platform.win32.WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
27 import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
28
29 import oshi.annotation.concurrent.ThreadSafe;
30 import oshi.driver.windows.wmi.Win32Processor;
31 import oshi.driver.windows.wmi.Win32Processor.ProcessorIdProperty;
32 import oshi.hardware.CentralProcessor.LogicalProcessor;
33 import oshi.hardware.CentralProcessor.PhysicalProcessor;
34 import oshi.hardware.CentralProcessor.ProcessorCache;
35 import oshi.hardware.CentralProcessor.ProcessorCache.Type;
36 import oshi.util.platform.windows.WmiUtil;
37 import oshi.util.tuples.Triplet;
38
39
40
41
42 @ThreadSafe
43 public final class LogicalProcessorInformation {
44
45 private static final boolean IS_WIN10_OR_GREATER = VersionHelpers.IsWindows10OrGreater();
46
47 private LogicalProcessorInformation() {
48 }
49
50
51
52
53
54
55 public static Triplet<List<LogicalProcessor>, List<PhysicalProcessor>, List<ProcessorCache>> getLogicalProcessorInformationEx() {
56
57
58 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX[] procInfo = Kernel32Util
59 .getLogicalProcessorInformationEx(WinNT.LOGICAL_PROCESSOR_RELATIONSHIP.RelationAll);
60
61 List<GROUP_AFFINITY[]> packages = new ArrayList<>();
62 Set<ProcessorCache> caches = new HashSet<>();
63 List<GROUP_AFFINITY> cores = new ArrayList<>();
64
65 List<NUMA_NODE_RELATIONSHIP> numaNodes = new ArrayList<>();
66
67 Map<GROUP_AFFINITY, Integer> coreEfficiencyMap = new HashMap<>();
68
69 for (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info : procInfo) {
70 switch (info.relationship) {
71 case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorPackage:
72
73 packages.add(((PROCESSOR_RELATIONSHIP) info).groupMask);
74 break;
75 case LOGICAL_PROCESSOR_RELATIONSHIP.RelationCache:
76 CACHE_RELATIONSHIP cache = (CACHE_RELATIONSHIP) info;
77 caches.add(new ProcessorCache(cache.level, cache.associativity, cache.lineSize, cache.size,
78 Type.values()[cache.type]));
79 break;
80 case LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore:
81 PROCESSOR_RELATIONSHIP core = ((PROCESSOR_RELATIONSHIP) info);
82
83 cores.add(core.groupMask[0]);
84 if (IS_WIN10_OR_GREATER) {
85 coreEfficiencyMap.put(core.groupMask[0], (int) core.efficiencyClass);
86 }
87 break;
88 case LOGICAL_PROCESSOR_RELATIONSHIP.RelationNumaNode:
89 numaNodes.add((NUMA_NODE_RELATIONSHIP) info);
90 break;
91 default:
92
93 break;
94 }
95 }
96
97
98
99
100 cores.sort(Comparator.comparing(c -> c.group * 64L + Long.numberOfTrailingZeros(c.mask.longValue())));
101
102
103 packages.sort(Comparator.comparing(p -> p[0].group * 64L + Long.numberOfTrailingZeros(p[0].mask.longValue())));
104
105
106
107
108
109 numaNodes.sort(Comparator.comparing(n -> n.nodeNumber));
110
111
112 Map<Integer, String> processorIdMap = new HashMap<>();
113 WmiResult<ProcessorIdProperty> processorId = Win32Processor.queryProcessorId();
114
115 for (int pkg = 0; pkg < processorId.getResultCount(); pkg++) {
116 processorIdMap.put(pkg, WmiUtil.getString(processorId, ProcessorIdProperty.PROCESSORID, pkg));
117 }
118
119 List<LogicalProcessor> logProcs = new ArrayList<>();
120 Map<Integer, Integer> corePkgMap = new HashMap<>();
121 Map<Integer, String> pkgCpuidMap = new HashMap<>();
122 for (NUMA_NODE_RELATIONSHIP node : numaNodes) {
123 int nodeNum = node.nodeNumber;
124 int group = node.groupMask.group;
125 long mask = node.groupMask.mask.longValue();
126
127
128 int lowBit = Long.numberOfTrailingZeros(mask);
129 int hiBit = 63 - Long.numberOfLeadingZeros(mask);
130 for (int lp = lowBit; lp <= hiBit; lp++) {
131 if ((mask & (1L << lp)) != 0) {
132 int coreId = getMatchingCore(cores, group, lp);
133 int pkgId = getMatchingPackage(packages, group, lp);
134 corePkgMap.put(coreId, pkgId);
135 pkgCpuidMap.put(coreId, processorIdMap.getOrDefault(pkgId, ""));
136 LogicalProcessor logProc = new LogicalProcessor(lp, coreId, pkgId, nodeNum, group);
137 logProcs.add(logProc);
138 }
139 }
140 }
141 List<PhysicalProcessor> physProcs = getPhysProcs(cores, coreEfficiencyMap, corePkgMap, pkgCpuidMap);
142 return new Triplet<>(logProcs, physProcs, orderedProcCaches(caches));
143 }
144
145 private static List<PhysicalProcessor> getPhysProcs(List<GROUP_AFFINITY> cores,
146 Map<GROUP_AFFINITY, Integer> coreEfficiencyMap, Map<Integer, Integer> corePkgMap,
147 Map<Integer, String> coreCpuidMap) {
148 List<PhysicalProcessor> physProcs = new ArrayList<>();
149 for (int coreId = 0; coreId < cores.size(); coreId++) {
150 int efficiency = coreEfficiencyMap.getOrDefault(cores.get(coreId), 0);
151 String cpuid = coreCpuidMap.getOrDefault(coreId, "");
152 int pkgId = corePkgMap.getOrDefault(coreId, 0);
153 physProcs.add(new PhysicalProcessor(pkgId, coreId, efficiency, cpuid));
154 }
155 return physProcs;
156 }
157
158 private static int getMatchingPackage(List<GROUP_AFFINITY[]> packages, int g, int lp) {
159 for (int i = 0; i < packages.size(); i++) {
160 for (int j = 0; j < packages.get(i).length; j++) {
161 if ((packages.get(i)[j].mask.longValue() & (1L << lp)) != 0 && packages.get(i)[j].group == g) {
162 return i;
163 }
164 }
165 }
166 return 0;
167 }
168
169 private static int getMatchingCore(List<GROUP_AFFINITY> cores, int g, int lp) {
170 for (int j = 0; j < cores.size(); j++) {
171 if ((cores.get(j).mask.longValue() & (1L << lp)) != 0 && cores.get(j).group == g) {
172 return j;
173 }
174 }
175 return 0;
176 }
177
178
179
180
181
182
183
184
185
186
187 public static Triplet<List<LogicalProcessor>, List<PhysicalProcessor>, List<ProcessorCache>> getLogicalProcessorInformation() {
188
189 List<Long> packageMaskList = new ArrayList<>();
190 List<Long> coreMaskList = new ArrayList<>();
191 WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] processors = Kernel32Util.getLogicalProcessorInformation();
192 for (SYSTEM_LOGICAL_PROCESSOR_INFORMATION proc : processors) {
193 if (proc.relationship == WinNT.LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorPackage) {
194 packageMaskList.add(proc.processorMask.longValue());
195 } else if (proc.relationship == WinNT.LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore) {
196 coreMaskList.add(proc.processorMask.longValue());
197 }
198 }
199
200
201 coreMaskList.sort(null);
202 packageMaskList.sort(null);
203
204
205 List<LogicalProcessor> logProcs = new ArrayList<>();
206 for (int core = 0; core < coreMaskList.size(); core++) {
207 long coreMask = coreMaskList.get(core);
208
209 int lowBit = Long.numberOfTrailingZeros(coreMask);
210 int hiBit = 63 - Long.numberOfLeadingZeros(coreMask);
211
212 for (int i = lowBit; i <= hiBit; i++) {
213 if ((coreMask & (1L << i)) != 0) {
214 LogicalProcessor logProc = new LogicalProcessor(i, core,
215 LogicalProcessorInformation.getBitMatchingPackageNumber(packageMaskList, i));
216 logProcs.add(logProc);
217 }
218 }
219 }
220 return new Triplet<>(logProcs, null, null);
221 }
222
223
224
225
226
227
228
229
230 private static int getBitMatchingPackageNumber(List<Long> packageMaskList, int logProc) {
231 for (int i = 0; i < packageMaskList.size(); i++) {
232 if ((packageMaskList.get(i).longValue() & (1L << logProc)) != 0) {
233 return i;
234 }
235 }
236 return 0;
237 }
238 }