Commit | Line | Data |
---|---|---|
50a47aa6 | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2014, 2015 École Polytechnique de Montréal |
50a47aa6 GB |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * Geneviève Bastien - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
e363eae1 | 13 | package org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis; |
50a47aa6 GB |
14 | |
15 | import java.util.Collection; | |
16 | import java.util.Collections; | |
17 | import java.util.List; | |
18 | import java.util.Set; | |
19 | import java.util.TreeSet; | |
20 | ||
21 | import org.eclipse.core.runtime.IProgressMonitor; | |
50a47aa6 GB |
22 | import org.eclipse.jdt.annotation.Nullable; |
23 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
50a47aa6 GB |
24 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; |
25 | import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; | |
26 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
27 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
28 | import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | |
29 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
30 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
31 | ||
32 | /** | |
33 | * Information provider utility class that retrieves thread-related information | |
34 | * from a Linux Kernel Analysis | |
35 | * | |
36 | * @author Geneviève Bastien | |
37 | */ | |
e363eae1 | 38 | public final class KernelThreadInformationProvider { |
50a47aa6 | 39 | |
e363eae1 | 40 | private KernelThreadInformationProvider() { |
50a47aa6 GB |
41 | } |
42 | ||
43 | /** | |
44 | * Get the ID of the thread running on the CPU at time ts | |
45 | * | |
46 | * TODO: This method may later be replaced by an aspect, when the aspect can | |
47 | * resolve to something that is not an event | |
48 | * | |
49 | * @param module | |
50 | * The lttng kernel analysis instance to run this method on | |
51 | * @param cpuId | |
52 | * The CPU number the process is running on | |
53 | * @param ts | |
54 | * The timestamp at which we want the running process | |
55 | * @return The TID of the thread running on CPU cpuId at time ts or | |
56 | * {@code null} if either no thread is running or we do not know. | |
6d16f5a9 | 57 | * @since 1.0 |
50a47aa6 | 58 | */ |
6d16f5a9 | 59 | public static @Nullable Integer getThreadOnCpu(KernelAnalysisModule module, long cpuId, long ts) { |
50a47aa6 GB |
60 | ITmfStateSystem ss = module.getStateSystem(); |
61 | if (ss == null) { | |
62 | return null; | |
63 | } | |
64 | try { | |
65 | int cpuQuark = ss.getQuarkAbsolute(Attributes.CPUS, Long.toString(cpuId), Attributes.CURRENT_THREAD); | |
66 | ITmfStateInterval interval = ss.querySingleState(ts, cpuQuark); | |
67 | ITmfStateValue val = interval.getStateValue(); | |
68 | switch (val.getType()) { | |
69 | case INTEGER: | |
70 | return val.unboxInt(); | |
71 | case LONG: | |
72 | case DOUBLE: | |
73 | case NULL: | |
74 | case STRING: | |
75 | default: | |
76 | break; | |
77 | } | |
78 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
79 | } | |
80 | return null; | |
81 | } | |
82 | ||
83 | /** | |
84 | * Get the TIDs of the threads from an analysis | |
85 | * | |
86 | * @param module | |
87 | * The lttng kernel analysis instance to run this method on | |
88 | * @return The set of TIDs corresponding to the threads | |
6d16f5a9 | 89 | * @since 1.0 |
50a47aa6 | 90 | */ |
6d16f5a9 | 91 | public static Collection<Integer> getThreadIds(KernelAnalysisModule module) { |
50a47aa6 GB |
92 | ITmfStateSystem ss = module.getStateSystem(); |
93 | if (ss == null) { | |
94 | return NonNullUtils.checkNotNull(Collections.EMPTY_SET); | |
95 | } | |
96 | int threadQuark; | |
97 | try { | |
98 | threadQuark = ss.getQuarkAbsolute(Attributes.THREADS); | |
99 | Set<Integer> tids = new TreeSet<>(); | |
100 | for (Integer quark : ss.getSubAttributes(threadQuark, false)) { | |
101 | tids.add(Integer.parseInt(ss.getAttributeName(quark))); | |
102 | } | |
103 | return tids; | |
104 | } catch (AttributeNotFoundException e) { | |
105 | } | |
106 | return NonNullUtils.checkNotNull(Collections.EMPTY_SET); | |
107 | } | |
108 | ||
109 | /** | |
110 | * Get the parent process ID of a thread | |
111 | * | |
112 | * @param module | |
113 | * The lttng kernel analysis instance to run this method on | |
114 | * @param threadId | |
115 | * The thread ID of the process for which to get the parent | |
116 | * @param ts | |
117 | * The timestamp at which to get the parent | |
118 | * @return The parent PID or {@code null} if the PPID is not found. | |
6d16f5a9 | 119 | * @since 1.0 |
50a47aa6 | 120 | */ |
6d16f5a9 | 121 | public static @Nullable Integer getParentPid(KernelAnalysisModule module, Integer threadId, long ts) { |
50a47aa6 GB |
122 | Integer ppid = null; |
123 | ITmfStateSystem ss = module.getStateSystem(); | |
124 | if (ss == null) { | |
125 | return ppid; | |
126 | } | |
127 | Integer ppidNode; | |
128 | try { | |
129 | ppidNode = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.PPID); | |
130 | ITmfStateInterval ppidInterval = ss.querySingleState(ts, ppidNode); | |
131 | ITmfStateValue ppidValue = ppidInterval.getStateValue(); | |
132 | ||
133 | switch (ppidValue.getType()) { | |
134 | case INTEGER: | |
135 | ppid = NonNullUtils.checkNotNull(Integer.valueOf(ppidValue.unboxInt())); | |
136 | break; | |
137 | case DOUBLE: | |
138 | case LONG: | |
139 | case NULL: | |
140 | case STRING: | |
141 | default: | |
142 | break; | |
143 | } | |
144 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
145 | } | |
146 | return ppid; | |
147 | } | |
148 | ||
149 | /** | |
150 | * Get the executable name of the thread ID. If the thread ID was used | |
151 | * multiple time or the name changed in between, it will return the last | |
152 | * name the thread has taken, or {@code null} if no name is found | |
153 | * | |
154 | * @param module | |
155 | * The lttng kernel analysis instance to run this method on | |
156 | * @param threadId | |
157 | * The thread ID of the process for which to get the name | |
158 | * @return The last executable name of this process, or {@code null} if not | |
159 | * found | |
6d16f5a9 | 160 | * @since 1.0 |
50a47aa6 | 161 | */ |
6d16f5a9 | 162 | public static @Nullable String getExecutableName(KernelAnalysisModule module, Integer threadId) { |
50a47aa6 GB |
163 | String execName = null; |
164 | ITmfStateSystem ss = module.getStateSystem(); | |
165 | if (ss == null) { | |
166 | return execName; | |
167 | } | |
168 | Integer execNameNode; | |
169 | try { | |
170 | execNameNode = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.EXEC_NAME); | |
171 | List<ITmfStateInterval> execNameIntervals = StateSystemUtils.queryHistoryRange(ss, execNameNode, ss.getStartTime(), ss.getCurrentEndTime()); | |
172 | ||
173 | ITmfStateValue execNameValue; | |
174 | for (ITmfStateInterval interval : execNameIntervals) { | |
175 | execNameValue = interval.getStateValue(); | |
176 | switch (execNameValue.getType()) { | |
177 | case STRING: | |
178 | execName = NonNullUtils.checkNotNull(execNameValue.unboxStr()); | |
179 | break; | |
180 | case DOUBLE: | |
181 | case LONG: | |
182 | case NULL: | |
183 | case INTEGER: | |
184 | default: | |
185 | break; | |
186 | } | |
187 | } | |
188 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
189 | } | |
190 | return execName; | |
191 | } | |
192 | ||
3bf563da CM |
193 | /** |
194 | * Get the priority of a thread running at a time ts. | |
195 | * | |
196 | * @param module | |
197 | * The kernel analysis instance to run this method on | |
198 | * @param threadId | |
199 | * The thread ID of the target thread | |
200 | * @param ts | |
201 | * The timestamp at which to get the priority | |
202 | * @return The priority of this thread, or {@code null} if not found | |
dbc7991d | 203 | * @since 1.0 |
3bf563da | 204 | */ |
6d16f5a9 | 205 | public static @Nullable Integer getThreadPrio(KernelAnalysisModule module, Integer threadId, long ts) { |
3bf563da CM |
206 | Integer execPrio = null; |
207 | ITmfStateSystem ss = module.getStateSystem(); | |
208 | if (ss == null) { | |
209 | return execPrio; | |
210 | } | |
211 | try { | |
212 | int execPrioQuark = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.PRIO); | |
213 | ITmfStateInterval interval = ss.querySingleState(ts, execPrioQuark); | |
214 | ITmfStateValue prioValue = interval.getStateValue(); | |
215 | /* We know the prio must be an Integer */ | |
216 | execPrio = prioValue.unboxInt(); | |
217 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
218 | } | |
219 | return execPrio; | |
220 | } | |
221 | ||
50a47aa6 GB |
222 | /** |
223 | * Get the status intervals for a given thread with a resolution | |
224 | * | |
225 | * @param module | |
226 | * The lttng kernel analysis instance to run this method on | |
227 | * @param threadId | |
228 | * The ID of the thread to get the intervals for | |
229 | * @param start | |
230 | * The start time of the requested range | |
231 | * @param end | |
232 | * The end time of the requested range | |
233 | * @param resolution | |
234 | * The resolution or the minimal time between the requested | |
235 | * intervals. If interval times are smaller than resolution, only | |
236 | * the first interval is returned, the others are ignored. | |
237 | * @param monitor | |
238 | * A progress monitor for this task | |
239 | * @return The list of status intervals for this thread, an empty list is | |
240 | * returned if either the state system is {@code null} or the quark | |
241 | * is not found | |
6d16f5a9 | 242 | * @since 1.0 |
50a47aa6 | 243 | */ |
6d16f5a9 | 244 | public static List<ITmfStateInterval> getStatusIntervalsForThread(KernelAnalysisModule module, Integer threadId, long start, long end, long resolution, IProgressMonitor monitor) { |
50a47aa6 GB |
245 | ITmfStateSystem ss = module.getStateSystem(); |
246 | if (ss == null) { | |
247 | return NonNullUtils.checkNotNull(Collections.EMPTY_LIST); | |
248 | } | |
249 | ||
250 | try { | |
251 | int threadQuark = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString()); | |
252 | int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS); | |
253 | List<ITmfStateInterval> statusIntervals = StateSystemUtils.queryHistoryRange(ss, statusQuark, Math.max(start, ss.getStartTime()), Math.min(end - 1, ss.getCurrentEndTime()), resolution, monitor); | |
254 | return statusIntervals; | |
255 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
256 | } | |
257 | return NonNullUtils.checkNotNull(Collections.EMPTY_LIST); | |
258 | } | |
259 | ||
260 | } |