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 | ||
0f7a12d3 | 13 | package org.eclipse.tracecompass.analysis.os.linux.core.kernel; |
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; | |
4c4e2816 | 22 | import org.eclipse.jdt.annotation.NonNull; |
50a47aa6 | 23 | import org.eclipse.jdt.annotation.Nullable; |
f69045e2 | 24 | import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; |
50a47aa6 GB |
25 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; |
26 | import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; | |
27 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
28 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
29 | import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | |
30 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
31 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
f20f0966 | 32 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type; |
50a47aa6 GB |
33 | |
34 | /** | |
35 | * Information provider utility class that retrieves thread-related information | |
36 | * from a Linux Kernel Analysis | |
37 | * | |
38 | * @author Geneviève Bastien | |
0f7a12d3 | 39 | * @since 2.0 |
50a47aa6 | 40 | */ |
e363eae1 | 41 | public final class KernelThreadInformationProvider { |
50a47aa6 | 42 | |
e363eae1 | 43 | private KernelThreadInformationProvider() { |
50a47aa6 GB |
44 | } |
45 | ||
46 | /** | |
47 | * Get the ID of the thread running on the CPU at time ts | |
48 | * | |
49 | * TODO: This method may later be replaced by an aspect, when the aspect can | |
50 | * resolve to something that is not an event | |
51 | * | |
52 | * @param module | |
1add07ef | 53 | * The kernel analysis instance to run this method on |
50a47aa6 GB |
54 | * @param cpuId |
55 | * The CPU number the process is running on | |
56 | * @param ts | |
57 | * The timestamp at which we want the running process | |
58 | * @return The TID of the thread running on CPU cpuId at time ts or | |
59 | * {@code null} if either no thread is running or we do not know. | |
60 | */ | |
6d16f5a9 | 61 | public static @Nullable Integer getThreadOnCpu(KernelAnalysisModule module, long cpuId, long ts) { |
50a47aa6 GB |
62 | ITmfStateSystem ss = module.getStateSystem(); |
63 | if (ss == null) { | |
64 | return null; | |
65 | } | |
66 | try { | |
67 | int cpuQuark = ss.getQuarkAbsolute(Attributes.CPUS, Long.toString(cpuId), Attributes.CURRENT_THREAD); | |
68 | ITmfStateInterval interval = ss.querySingleState(ts, cpuQuark); | |
69 | ITmfStateValue val = interval.getStateValue(); | |
f20f0966 | 70 | if (val.getType().equals(Type.INTEGER)) { |
50a47aa6 | 71 | return val.unboxInt(); |
50a47aa6 GB |
72 | } |
73 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
74 | } | |
75 | return null; | |
76 | } | |
77 | ||
78 | /** | |
79 | * Get the TIDs of the threads from an analysis | |
80 | * | |
81 | * @param module | |
1add07ef | 82 | * The kernel analysis instance to run this method on |
50a47aa6 GB |
83 | * @return The set of TIDs corresponding to the threads |
84 | */ | |
6d16f5a9 | 85 | public static Collection<Integer> getThreadIds(KernelAnalysisModule module) { |
50a47aa6 GB |
86 | ITmfStateSystem ss = module.getStateSystem(); |
87 | if (ss == null) { | |
aa353506 | 88 | return Collections.EMPTY_SET; |
50a47aa6 GB |
89 | } |
90 | int threadQuark; | |
91 | try { | |
92 | threadQuark = ss.getQuarkAbsolute(Attributes.THREADS); | |
4c4e2816 | 93 | Set<@NonNull Integer> tids = new TreeSet<>(); |
50a47aa6 | 94 | for (Integer quark : ss.getSubAttributes(threadQuark, false)) { |
02b08403 MK |
95 | final @NonNull String attributeName = ss.getAttributeName(quark); |
96 | tids.add(attributeName.startsWith(Attributes.THREAD_0_PREFIX) ? 0 : Integer.parseInt(attributeName)); | |
50a47aa6 GB |
97 | } |
98 | return tids; | |
99 | } catch (AttributeNotFoundException e) { | |
100 | } | |
aa353506 | 101 | return Collections.EMPTY_SET; |
50a47aa6 GB |
102 | } |
103 | ||
104 | /** | |
105 | * Get the parent process ID of a thread | |
106 | * | |
107 | * @param module | |
1add07ef | 108 | * The kernel analysis instance to run this method on |
50a47aa6 GB |
109 | * @param threadId |
110 | * The thread ID of the process for which to get the parent | |
111 | * @param ts | |
112 | * The timestamp at which to get the parent | |
113 | * @return The parent PID or {@code null} if the PPID is not found. | |
114 | */ | |
6d16f5a9 | 115 | public static @Nullable Integer getParentPid(KernelAnalysisModule module, Integer threadId, long ts) { |
50a47aa6 GB |
116 | ITmfStateSystem ss = module.getStateSystem(); |
117 | if (ss == null) { | |
f20f0966 | 118 | return null; |
50a47aa6 GB |
119 | } |
120 | Integer ppidNode; | |
121 | try { | |
122 | ppidNode = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.PPID); | |
123 | ITmfStateInterval ppidInterval = ss.querySingleState(ts, ppidNode); | |
124 | ITmfStateValue ppidValue = ppidInterval.getStateValue(); | |
125 | ||
f20f0966 MK |
126 | if (ppidValue.getType().equals(Type.INTEGER)) { |
127 | return Integer.valueOf(ppidValue.unboxInt()); | |
50a47aa6 GB |
128 | } |
129 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
130 | } | |
f20f0966 | 131 | return null; |
50a47aa6 GB |
132 | } |
133 | ||
134 | /** | |
135 | * Get the executable name of the thread ID. If the thread ID was used | |
136 | * multiple time or the name changed in between, it will return the last | |
137 | * name the thread has taken, or {@code null} if no name is found | |
138 | * | |
139 | * @param module | |
1add07ef | 140 | * The kernel analysis instance to run this method on |
50a47aa6 GB |
141 | * @param threadId |
142 | * The thread ID of the process for which to get the name | |
143 | * @return The last executable name of this process, or {@code null} if not | |
144 | * found | |
145 | */ | |
6d16f5a9 | 146 | public static @Nullable String getExecutableName(KernelAnalysisModule module, Integer threadId) { |
50a47aa6 GB |
147 | ITmfStateSystem ss = module.getStateSystem(); |
148 | if (ss == null) { | |
f20f0966 | 149 | return null; |
50a47aa6 GB |
150 | } |
151 | Integer execNameNode; | |
152 | try { | |
153 | execNameNode = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.EXEC_NAME); | |
154 | List<ITmfStateInterval> execNameIntervals = StateSystemUtils.queryHistoryRange(ss, execNameNode, ss.getStartTime(), ss.getCurrentEndTime()); | |
155 | ||
156 | ITmfStateValue execNameValue; | |
f20f0966 | 157 | String execName = null; |
50a47aa6 GB |
158 | for (ITmfStateInterval interval : execNameIntervals) { |
159 | execNameValue = interval.getStateValue(); | |
f20f0966 | 160 | if (execNameValue.getType().equals(Type.STRING)) { |
0e4f957e | 161 | execName = execNameValue.unboxStr(); |
50a47aa6 GB |
162 | } |
163 | } | |
f20f0966 | 164 | return execName; |
50a47aa6 GB |
165 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { |
166 | } | |
f20f0966 | 167 | return null; |
50a47aa6 GB |
168 | } |
169 | ||
1add07ef GB |
170 | /** |
171 | * Get the priority of this thread at time ts | |
172 | * | |
173 | * @param module | |
174 | * The kernel analysis instance to run this method on | |
175 | * @param threadId | |
176 | * The ID of the thread to query | |
177 | * @param ts | |
178 | * The timestamp at which to query | |
179 | * @return The priority of the thread or <code>-1</code> if not available | |
180 | */ | |
181 | public static int getThreadPriority(KernelAnalysisModule module, int threadId, long ts) { | |
182 | ITmfStateSystem ss = module.getStateSystem(); | |
183 | if (ss == null) { | |
184 | return -1; | |
185 | } | |
186 | int prioQuark = ss.optQuarkAbsolute(Attributes.THREADS, String.valueOf(threadId), Attributes.PRIO); | |
187 | if (prioQuark == ITmfStateSystem.INVALID_ATTRIBUTE) { | |
188 | return -1; | |
189 | } | |
190 | try { | |
191 | return ss.querySingleState(ts, prioQuark).getStateValue().unboxInt(); | |
192 | } catch (AttributeNotFoundException | StateSystemDisposedException e) { | |
193 | return -1; | |
194 | } | |
195 | } | |
196 | ||
50a47aa6 GB |
197 | /** |
198 | * Get the status intervals for a given thread with a resolution | |
199 | * | |
200 | * @param module | |
1add07ef | 201 | * The kernel analysis instance to run this method on |
50a47aa6 GB |
202 | * @param threadId |
203 | * The ID of the thread to get the intervals for | |
204 | * @param start | |
205 | * The start time of the requested range | |
206 | * @param end | |
207 | * The end time of the requested range | |
208 | * @param resolution | |
209 | * The resolution or the minimal time between the requested | |
210 | * intervals. If interval times are smaller than resolution, only | |
211 | * the first interval is returned, the others are ignored. | |
212 | * @param monitor | |
213 | * A progress monitor for this task | |
214 | * @return The list of status intervals for this thread, an empty list is | |
215 | * returned if either the state system is {@code null} or the quark | |
216 | * is not found | |
217 | */ | |
6d16f5a9 | 218 | public static List<ITmfStateInterval> getStatusIntervalsForThread(KernelAnalysisModule module, Integer threadId, long start, long end, long resolution, IProgressMonitor monitor) { |
50a47aa6 GB |
219 | ITmfStateSystem ss = module.getStateSystem(); |
220 | if (ss == null) { | |
aa353506 | 221 | return Collections.EMPTY_LIST; |
50a47aa6 GB |
222 | } |
223 | ||
224 | try { | |
225 | int threadQuark = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString()); | |
226 | int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS); | |
227 | List<ITmfStateInterval> statusIntervals = StateSystemUtils.queryHistoryRange(ss, statusQuark, Math.max(start, ss.getStartTime()), Math.min(end - 1, ss.getCurrentEndTime()), resolution, monitor); | |
228 | return statusIntervals; | |
229 | } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) { | |
230 | } | |
aa353506 | 231 | return Collections.EMPTY_LIST; |
50a47aa6 GB |
232 | } |
233 | ||
234 | } |