View Javadoc
1   /*
2    * Copyright 2020-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.driver.windows.perfmon;
6   
7   import static oshi.driver.windows.perfmon.PerfmonConstants.THREAD;
8   import static oshi.driver.windows.perfmon.PerfmonConstants.WIN32_PERF_RAW_DATA_PERF_PROC_THREAD;
9   import static oshi.driver.windows.perfmon.PerfmonConstants.WIN32_PERF_RAW_DATA_PERF_PROC_THREAD_WHERE_NOT_NAME_LIKE_TOTAL;
10  
11  import java.util.List;
12  import java.util.Locale;
13  import java.util.Map;
14  
15  import oshi.annotation.concurrent.ThreadSafe;
16  import oshi.util.platform.windows.PerfCounterQuery;
17  import oshi.util.platform.windows.PerfCounterWildcardQuery;
18  import oshi.util.platform.windows.PerfCounterWildcardQuery.PdhCounterWildcardProperty;
19  import oshi.util.tuples.Pair;
20  
21  /**
22   * Utility to query Thread Information performance counter
23   */
24  @ThreadSafe
25  public final class ThreadInformation {
26  
27      /**
28       * Thread performance counters
29       */
30      public enum ThreadPerformanceProperty implements PdhCounterWildcardProperty {
31          // First element defines WMI instance name field and PDH instance filter
32          NAME(PerfCounterQuery.NOT_TOTAL_INSTANCES),
33          // Remaining elements define counters
34          PERCENTUSERTIME("% User Time"), //
35          PERCENTPRIVILEGEDTIME("% Privileged Time"), //
36          ELAPSEDTIME("Elapsed Time"), //
37          PRIORITYCURRENT("Priority Current"), //
38          STARTADDRESS("Start Address"), //
39          THREADSTATE("Thread State"), //
40          THREADWAITREASON("Thread Wait Reason"), // 5 is SUSPENDED
41          IDPROCESS("ID Process"), //
42          IDTHREAD("ID Thread"), //
43          CONTEXTSWITCHESPERSEC("Context Switches/sec");
44  
45          private final String counter;
46  
47          ThreadPerformanceProperty(String counter) {
48              this.counter = counter;
49          }
50  
51          @Override
52          public String getCounter() {
53              return counter;
54          }
55      }
56  
57      private ThreadInformation() {
58      }
59  
60      /**
61       * Returns thread counters.
62       *
63       * @return Thread counters for each thread.
64       */
65      public static Pair<List<String>, Map<ThreadPerformanceProperty, List<Long>>> queryThreadCounters() {
66          return PerfCounterWildcardQuery.queryInstancesAndValues(ThreadPerformanceProperty.class, THREAD,
67                  WIN32_PERF_RAW_DATA_PERF_PROC_THREAD_WHERE_NOT_NAME_LIKE_TOTAL);
68      }
69  
70      /**
71       * Returns thread counters filtered to the specified process name and thread.
72       *
73       * @param name      The process name to filter
74       * @param threadNum The thread number to match. -1 matches all threads.
75       *
76       * @return Thread counters for each thread.
77       */
78      public static Pair<List<String>, Map<ThreadPerformanceProperty, List<Long>>> queryThreadCounters(String name,
79              int threadNum) {
80          String procName = name.toLowerCase(Locale.ROOT);
81          if (threadNum >= 0) {
82              return PerfCounterWildcardQuery.queryInstancesAndValues(
83                      ThreadPerformanceProperty.class, THREAD, WIN32_PERF_RAW_DATA_PERF_PROC_THREAD
84                              + " WHERE Name LIKE \\\"" + procName + "\\\" AND IDThread=" + threadNum,
85                      procName + "/" + threadNum);
86          }
87          return PerfCounterWildcardQuery.queryInstancesAndValues(ThreadPerformanceProperty.class, THREAD,
88                  WIN32_PERF_RAW_DATA_PERF_PROC_THREAD + " WHERE Name LIKE \\\"" + procName + "\\\"", procName + "/*");
89      }
90  }