1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 École Polytechnique de Montréal
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
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
13 package org
.lttng
.scope
.lttng
.kernel
.core
.analysis
.os
;
15 import java
.util
.Collection
;
16 import java
.util
.Collections
;
17 import java
.util
.List
;
19 import java
.util
.TreeSet
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.jdt
.annotation
.NonNull
;
23 import org
.eclipse
.jdt
.annotation
.Nullable
;
25 import ca
.polymtl
.dorsal
.libdelorean
.ITmfStateSystem
;
26 import ca
.polymtl
.dorsal
.libdelorean
.StateSystemUtils
;
27 import ca
.polymtl
.dorsal
.libdelorean
.exceptions
.AttributeNotFoundException
;
28 import ca
.polymtl
.dorsal
.libdelorean
.exceptions
.StateSystemDisposedException
;
29 import ca
.polymtl
.dorsal
.libdelorean
.exceptions
.TimeRangeException
;
30 import ca
.polymtl
.dorsal
.libdelorean
.interval
.ITmfStateInterval
;
31 import ca
.polymtl
.dorsal
.libdelorean
.statevalue
.ITmfStateValue
;
32 import ca
.polymtl
.dorsal
.libdelorean
.statevalue
.ITmfStateValue
.Type
;
35 * Information provider utility class that retrieves thread-related information
36 * from a Linux Kernel Analysis
38 * @author Geneviève Bastien
40 public final class KernelThreadInformationProvider
{
42 private KernelThreadInformationProvider() {
46 * Get the ID of the thread running on the CPU at time ts
48 * TODO: This method may later be replaced by an aspect, when the aspect can
49 * resolve to something that is not an event
52 * The kernel analysis instance to run this method on
54 * The CPU number the process is running on
56 * The timestamp at which we want the running process
57 * @return The TID of the thread running on CPU cpuId at time ts or
58 * {@code null} if either no thread is running or we do not know.
60 public static @Nullable Integer
getThreadOnCpu(KernelAnalysisModule module
, long cpuId
, long ts
) {
61 ITmfStateSystem ss
= module
.getStateSystem();
66 int cpuQuark
= ss
.getQuarkAbsolute(Attributes
.CPUS
, Long
.toString(cpuId
), Attributes
.CURRENT_THREAD
);
67 ITmfStateInterval interval
= ss
.querySingleState(ts
, cpuQuark
);
68 ITmfStateValue val
= interval
.getStateValue();
69 if (val
.getType().equals(Type
.INTEGER
)) {
70 return val
.unboxInt();
72 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {
78 * Get the TIDs of the threads from an analysis
81 * The kernel analysis instance to run this method on
82 * @return The set of TIDs corresponding to the threads
84 public static Collection
<Integer
> getThreadIds(KernelAnalysisModule module
) {
85 ITmfStateSystem ss
= module
.getStateSystem();
87 return Collections
.EMPTY_SET
;
91 threadQuark
= ss
.getQuarkAbsolute(Attributes
.THREADS
);
92 Set
<@NonNull Integer
> tids
= new TreeSet
<>();
93 for (Integer quark
: ss
.getSubAttributes(threadQuark
, false)) {
94 final @NonNull String attributeName
= ss
.getAttributeName(quark
);
95 tids
.add(attributeName
.startsWith(Attributes
.THREAD_0_PREFIX
) ?
0 : Integer
.parseInt(attributeName
));
98 } catch (AttributeNotFoundException e
) {
100 return Collections
.EMPTY_SET
;
104 * Get the parent process ID of a thread
107 * The kernel analysis instance to run this method on
109 * The thread ID of the process for which to get the parent
111 * The timestamp at which to get the parent
112 * @return The parent PID or {@code null} if the PPID is not found.
114 public static @Nullable Integer
getParentPid(KernelAnalysisModule module
, Integer threadId
, long ts
) {
115 ITmfStateSystem ss
= module
.getStateSystem();
121 ppidNode
= ss
.getQuarkAbsolute(Attributes
.THREADS
, threadId
.toString(), Attributes
.PPID
);
122 ITmfStateInterval ppidInterval
= ss
.querySingleState(ts
, ppidNode
);
123 ITmfStateValue ppidValue
= ppidInterval
.getStateValue();
125 if (ppidValue
.getType().equals(Type
.INTEGER
)) {
126 return Integer
.valueOf(ppidValue
.unboxInt());
128 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {
134 * Get the executable name of the thread ID. If the thread ID was used
135 * multiple time or the name changed in between, it will return the last
136 * name the thread has taken, or {@code null} if no name is found
139 * The kernel analysis instance to run this method on
141 * The thread ID of the process for which to get the name
142 * @return The last executable name of this process, or {@code null} if not
145 public static @Nullable String
getExecutableName(KernelAnalysisModule module
, Integer threadId
) {
146 ITmfStateSystem ss
= module
.getStateSystem();
151 Integer execNameNode
= ss
.getQuarkAbsolute(Attributes
.THREADS
, threadId
.toString(), Attributes
.EXEC_NAME
);
152 List
<ITmfStateInterval
> execNameIntervals
= StateSystemUtils
.queryHistoryRange(ss
, execNameNode
, ss
.getStartTime(), ss
.getCurrentEndTime());
154 ITmfStateValue execNameValue
;
155 String execName
= null;
156 for (ITmfStateInterval interval
: execNameIntervals
) {
157 execNameValue
= interval
.getStateValue();
158 if (execNameValue
.getType().equals(Type
.STRING
)) {
159 execName
= execNameValue
.unboxStr();
163 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {
169 * Get the priority of this thread at time ts
172 * The kernel analysis instance to run this method on
174 * The ID of the thread to query
176 * The timestamp at which to query
177 * @return The priority of the thread or <code>-1</code> if not available
179 public static int getThreadPriority(KernelAnalysisModule module
, int threadId
, long ts
) {
180 ITmfStateSystem ss
= module
.getStateSystem();
185 int prioQuark
= ss
.getQuarkAbsolute(Attributes
.THREADS
, String
.valueOf(threadId
), Attributes
.PRIO
);
186 return ss
.querySingleState(ts
, prioQuark
).getStateValue().unboxInt();
187 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
192 * Get the status intervals for a given thread with a resolution
195 * The kernel analysis instance to run this method on
197 * The ID of the thread to get the intervals for
199 * The start time of the requested range
201 * The end time of the requested range
203 * The resolution or the minimal time between the requested
204 * intervals. If interval times are smaller than resolution, only
205 * the first interval is returned, the others are ignored.
207 * A progress monitor for this task
208 * @return The list of status intervals for this thread, an empty list is
209 * returned if either the state system is {@code null} or the quark
212 public static List
<ITmfStateInterval
> getStatusIntervalsForThread(KernelAnalysisModule module
, Integer threadId
, long start
, long end
, long resolution
, IProgressMonitor monitor
) {
213 ITmfStateSystem ss
= module
.getStateSystem();
215 return Collections
.EMPTY_LIST
;
219 int threadQuark
= ss
.getQuarkAbsolute(Attributes
.THREADS
, threadId
.toString());
220 List
<ITmfStateInterval
> statusIntervals
= StateSystemUtils
.queryHistoryRange(ss
, threadQuark
,
221 Math
.max(start
, ss
.getStartTime()), Math
.min(end
- 1, ss
.getCurrentEndTime()), resolution
, null);
222 return statusIntervals
;
223 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {
225 return Collections
.EMPTY_LIST
;