1
2
3
4
5 package oshi.driver.windows.registry;
6
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 import com.sun.jna.platform.win32.WinBase.FILETIME;
14
15 import oshi.annotation.concurrent.Immutable;
16 import oshi.annotation.concurrent.ThreadSafe;
17 import oshi.driver.windows.perfmon.PerfmonDisabled;
18 import oshi.driver.windows.perfmon.ThreadInformation;
19 import oshi.driver.windows.perfmon.ThreadInformation.ThreadPerformanceProperty;
20 import oshi.util.Util;
21 import oshi.util.tuples.Pair;
22 import oshi.util.tuples.Triplet;
23
24
25
26
27 @ThreadSafe
28 public final class ThreadPerformanceData {
29
30 private static final String THREAD = "Thread";
31
32 private ThreadPerformanceData() {
33 }
34
35
36
37
38
39
40
41
42 public static Map<Integer, PerfCounterBlock> buildThreadMapFromRegistry(Collection<Integer> pids) {
43
44 Triplet<List<Map<ThreadPerformanceProperty, Object>>, Long, Long> threadData = HkeyPerformanceDataUtil
45 .readPerfDataFromRegistry(THREAD, ThreadPerformanceProperty.class);
46 if (threadData == null) {
47 return null;
48 }
49 List<Map<ThreadPerformanceProperty, Object>> threadInstanceMaps = threadData.getA();
50 long perfTime100nSec = threadData.getB();
51 long now = threadData.getC();
52
53
54 Map<Integer, PerfCounterBlock> threadMap = new HashMap<>();
55
56 for (Map<ThreadPerformanceProperty, Object> threadInstanceMap : threadInstanceMaps) {
57 int pid = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.IDPROCESS)).intValue();
58 if ((pids == null || pids.contains(pid)) && pid > 0) {
59 int tid = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.IDTHREAD)).intValue();
60 String name = (String) threadInstanceMap.get(ThreadPerformanceProperty.NAME);
61 long upTime = (perfTime100nSec - (Long) threadInstanceMap.get(ThreadPerformanceProperty.ELAPSEDTIME))
62 / 10_000L;
63 if (upTime < 1) {
64 upTime = 1;
65 }
66 long user = ((Long) threadInstanceMap.get(ThreadPerformanceProperty.PERCENTUSERTIME)).longValue()
67 / 10_000L;
68 long kernel = ((Long) threadInstanceMap.get(ThreadPerformanceProperty.PERCENTPRIVILEGEDTIME))
69 .longValue() / 10_000L;
70 int priority = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.PRIORITYCURRENT)).intValue();
71 int threadState = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.THREADSTATE)).intValue();
72 int threadWaitReason = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.THREADWAITREASON))
73 .intValue();
74
75
76 Object addr = threadInstanceMap.get(ThreadPerformanceProperty.STARTADDRESS);
77 long startAddr = addr.getClass().equals(Long.class) ? (Long) addr
78 : Integer.toUnsignedLong((Integer) addr);
79 int contextSwitches = ((Integer) threadInstanceMap.get(ThreadPerformanceProperty.CONTEXTSWITCHESPERSEC))
80 .intValue();
81 threadMap.put(tid, new PerfCounterBlock(name, tid, pid, now - upTime, user, kernel, priority,
82 threadState, threadWaitReason, startAddr, contextSwitches));
83 }
84 }
85 return threadMap;
86 }
87
88
89
90
91
92
93
94
95 public static Map<Integer, PerfCounterBlock> buildThreadMapFromPerfCounters(Collection<Integer> pids) {
96 return buildThreadMapFromPerfCounters(pids, null, -1);
97 }
98
99
100
101
102
103
104
105
106
107
108 public static Map<Integer, PerfCounterBlock> buildThreadMapFromPerfCounters(Collection<Integer> pids,
109 String procName, int threadNum) {
110 if (PerfmonDisabled.PERF_PROC_DISABLED) {
111 return Collections.emptyMap();
112 }
113 Map<Integer, PerfCounterBlock> threadMap = new HashMap<>();
114 Pair<List<String>, Map<ThreadPerformanceProperty, List<Long>>> instanceValues = Util.isBlank(procName)
115 ? ThreadInformation.queryThreadCounters()
116 : ThreadInformation.queryThreadCounters(procName, threadNum);
117 long now = System.currentTimeMillis();
118 List<String> instances = instanceValues.getA();
119 Map<ThreadPerformanceProperty, List<Long>> valueMap = instanceValues.getB();
120 List<Long> tidList = valueMap.get(ThreadPerformanceProperty.IDTHREAD);
121 List<Long> pidList = valueMap.get(ThreadPerformanceProperty.IDPROCESS);
122 List<Long> userList = valueMap.get(ThreadPerformanceProperty.PERCENTUSERTIME);
123 List<Long> kernelList = valueMap.get(ThreadPerformanceProperty.PERCENTPRIVILEGEDTIME);
124 List<Long> startTimeList = valueMap.get(ThreadPerformanceProperty.ELAPSEDTIME);
125 List<Long> priorityList = valueMap.get(ThreadPerformanceProperty.PRIORITYCURRENT);
126 List<Long> stateList = valueMap.get(ThreadPerformanceProperty.THREADSTATE);
127 List<Long> waitReasonList = valueMap.get(ThreadPerformanceProperty.THREADWAITREASON);
128 List<Long> startAddrList = valueMap.get(ThreadPerformanceProperty.STARTADDRESS);
129 List<Long> contextSwitchesList = valueMap.get(ThreadPerformanceProperty.CONTEXTSWITCHESPERSEC);
130
131 int nameIndex = 0;
132 for (int inst = 0; inst < instances.size(); inst++) {
133 int pid = pidList.get(inst).intValue();
134 if (pids == null || pids.contains(pid)) {
135 int tid = tidList.get(inst).intValue();
136 String name = Integer.toString(nameIndex++);
137 long startTime = startTimeList.get(inst);
138 int lowerStartTimeLimit = (int) (startTime >> 32);
139 int higherStartTimeLimit = (int) (startTime & 0xffffffffL);
140 startTime = FILETIME.filetimeToDate(lowerStartTimeLimit, higherStartTimeLimit).getTime();
141 if (startTime > now) {
142 startTime = now - 1;
143 }
144 long user = userList.get(inst) / 10_000L;
145 long kernel = kernelList.get(inst) / 10_000L;
146 int priority = priorityList.get(inst).intValue();
147 int threadState = stateList.get(inst).intValue();
148 int threadWaitReason = waitReasonList.get(inst).intValue();
149 long startAddr = startAddrList.get(inst).longValue();
150 int contextSwitches = contextSwitchesList.get(inst).intValue();
151
152
153
154 threadMap.put(tid, new PerfCounterBlock(name, tid, pid, startTime, user, kernel, priority, threadState,
155 threadWaitReason, startAddr, contextSwitches));
156 }
157 }
158 return threadMap;
159 }
160
161
162
163
164 @Immutable
165 public static class PerfCounterBlock {
166 private final String name;
167 private final int threadID;
168 private final int owningProcessID;
169 private final long startTime;
170 private final long userTime;
171 private final long kernelTime;
172 private final int priority;
173 private final int threadState;
174 private final int threadWaitReason;
175 private final long startAddress;
176 private final int contextSwitches;
177
178 public PerfCounterBlock(String name, int threadID, int owningProcessID, long startTime, long userTime,
179 long kernelTime, int priority, int threadState, int threadWaitReason, long startAddress,
180 int contextSwitches) {
181 this.name = name;
182 this.threadID = threadID;
183 this.owningProcessID = owningProcessID;
184 this.startTime = startTime;
185 this.userTime = userTime;
186 this.kernelTime = kernelTime;
187 this.priority = priority;
188 this.threadState = threadState;
189 this.threadWaitReason = threadWaitReason;
190 this.startAddress = startAddress;
191 this.contextSwitches = contextSwitches;
192 }
193
194
195
196
197 public String getName() {
198 return name;
199 }
200
201
202
203
204 public int getThreadID() {
205 return threadID;
206 }
207
208
209
210
211 public int getOwningProcessID() {
212 return owningProcessID;
213 }
214
215
216
217
218 public long getStartTime() {
219 return startTime;
220 }
221
222
223
224
225 public long getUserTime() {
226 return userTime;
227 }
228
229
230
231
232 public long getKernelTime() {
233 return kernelTime;
234 }
235
236
237
238
239 public int getPriority() {
240 return priority;
241 }
242
243
244
245
246 public int getThreadState() {
247 return threadState;
248 }
249
250
251
252
253 public int getThreadWaitReason() {
254 return threadWaitReason;
255 }
256
257
258
259
260 public long getStartAddress() {
261 return startAddress;
262 }
263
264
265
266
267 public int getContextSwitches() {
268 return contextSwitches;
269 }
270 }
271 }