View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.software.os.unix.solaris;
6   
7   import static oshi.software.os.OSProcess.State.INVALID;
8   import static oshi.util.Memoizer.defaultExpiration;
9   import static oshi.util.Memoizer.memoize;
10  
11  import java.util.function.Supplier;
12  
13  import com.sun.jna.Pointer;
14  
15  import oshi.annotation.concurrent.ThreadSafe;
16  import oshi.driver.unix.solaris.PsInfo;
17  import oshi.jna.platform.unix.SolarisLibc.SolarisLwpsInfo;
18  import oshi.jna.platform.unix.SolarisLibc.SolarisPrUsage;
19  import oshi.software.common.AbstractOSThread;
20  import oshi.software.os.OSProcess;
21  import oshi.util.Util;
22  
23  /**
24   * OSThread implementation
25   */
26  @ThreadSafe
27  public class SolarisOSThread extends AbstractOSThread {
28  
29      private Supplier<SolarisLwpsInfo> lwpsinfo = memoize(this::queryLwpsInfo, defaultExpiration());
30      private Supplier<SolarisPrUsage> prusage = memoize(this::queryPrUsage, defaultExpiration());
31  
32      private String name;
33      private int threadId;
34      private OSProcess.State state = OSProcess.State.INVALID;
35      private long startMemoryAddress;
36      private long contextSwitches;
37      private long kernelTime;
38      private long userTime;
39      private long startTime;
40      private long upTime;
41      private int priority;
42  
43      public SolarisOSThread(int pid, int lwpid) {
44          super(pid);
45          this.threadId = lwpid;
46          updateAttributes();
47      }
48  
49      private SolarisLwpsInfo queryLwpsInfo() {
50          return PsInfo.queryLwpsInfo(this.getOwningProcessId(), this.getThreadId());
51      }
52  
53      private SolarisPrUsage queryPrUsage() {
54          return PsInfo.queryPrUsage(this.getOwningProcessId(), this.getThreadId());
55      }
56  
57      @Override
58      public String getName() {
59          return this.name != null ? name : "";
60      }
61  
62      @Override
63      public int getThreadId() {
64          return this.threadId;
65      }
66  
67      @Override
68      public OSProcess.State getState() {
69          return this.state;
70      }
71  
72      @Override
73      public long getStartMemoryAddress() {
74          return this.startMemoryAddress;
75      }
76  
77      @Override
78      public long getContextSwitches() {
79          return this.contextSwitches;
80      }
81  
82      @Override
83      public long getKernelTime() {
84          return this.kernelTime;
85      }
86  
87      @Override
88      public long getUserTime() {
89          return this.userTime;
90      }
91  
92      @Override
93      public long getUpTime() {
94          return this.upTime;
95      }
96  
97      @Override
98      public long getStartTime() {
99          return this.startTime;
100     }
101 
102     @Override
103     public int getPriority() {
104         return this.priority;
105     }
106 
107     @Override
108     public boolean updateAttributes() {
109         SolarisLwpsInfo info = lwpsinfo.get();
110         if (info == null) {
111             this.state = INVALID;
112             return false;
113         }
114         SolarisPrUsage usage = prusage.get();
115         long now = System.currentTimeMillis();
116         this.state = SolarisOSProcess.getStateFromOutput((char) info.pr_sname);
117         this.startTime = info.pr_start.tv_sec.longValue() * 1000L + info.pr_start.tv_nsec.longValue() / 1_000_000L;
118         // Avoid divide by zero for processes up less than a millisecond
119         long elapsedTime = now - this.startTime;
120         this.upTime = elapsedTime < 1L ? 1L : elapsedTime;
121         this.kernelTime = 0L;
122         this.userTime = info.pr_time.tv_sec.longValue() * 1000L + info.pr_time.tv_nsec.longValue() / 1_000_000L;
123         this.startMemoryAddress = Pointer.nativeValue(info.pr_addr);
124         this.priority = info.pr_pri;
125         if (usage != null) {
126             this.userTime = usage.pr_utime.tv_sec.longValue() * 1000L + usage.pr_utime.tv_nsec.longValue() / 1_000_000L;
127             this.kernelTime = usage.pr_stime.tv_sec.longValue() * 1000L
128                     + usage.pr_stime.tv_nsec.longValue() / 1_000_000L;
129             this.contextSwitches = usage.pr_ictx.longValue() + usage.pr_vctx.longValue();
130         }
131         this.name = com.sun.jna.Native.toString(info.pr_name);
132         if (Util.isBlank(name)) {
133             this.name = com.sun.jna.Native.toString(info.pr_oldname);
134         }
135         return true;
136     }
137 }