1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.kernel
.handlers
;
12 import java
.util
.List
;
14 import org
.eclipse
.jdt
.annotation
.Nullable
;
15 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.StateValues
;
16 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.kernel
.Attributes
;
17 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
18 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.util
.Pair
;
29 * Kernel Event Handler Utils is a collection of static methods to be used in
30 * subclasses of IKernelEventHandler.
32 * @author Matthew Khouzam
33 * @author Francis Giraldeau
35 public final class KernelEventHandlerUtils
{
37 private KernelEventHandlerUtils() {
44 * The event containing the cpu
46 * @return the CPU number (null for not set)
48 public static @Nullable Integer
getCpu(ITmfEvent event
) {
49 Integer cpuObj
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
);
51 /* We couldn't find any CPU information, ignore this event */
58 * Gets the current CPU quark
65 * @return the current CPU quark -1 for not set
67 public static int getCurrentCPUNode(Integer cpuNumber
, ITmfStateSystemBuilder ss
) {
68 return ss
.getQuarkRelativeAndAdd(getNodeCPUs(ss
), cpuNumber
.toString());
72 * Get the timestamp of the event
75 * the event containing the timestamp
77 * @return the timestamp in long format
79 public static long getTimestamp(ITmfEvent event
) {
80 return event
.getTimestamp().toNanos();
84 * Get the current thread node
91 * @return the current thread node quark
92 * @throws AttributeNotFoundException
93 * current cpu node not found
95 public static int getCurrentThreadNode(Integer cpuNumber
, ITmfStateSystemBuilder ss
) throws AttributeNotFoundException
{
97 * Shortcut for the "current thread" attribute node. It requires
98 * querying the current CPU's current thread.
100 int quark
= ss
.getQuarkRelativeAndAdd(getCurrentCPUNode(cpuNumber
, ss
), Attributes
.CURRENT_THREAD
);
101 ITmfStateValue value
= ss
.queryOngoingState(quark
);
102 int thread
= value
.isNull() ?
-1 : value
.unboxInt();
103 return ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), buildThreadAttributeName(thread
, cpuNumber
));
107 * When we want to set a process back to a "running" state, first check its
108 * current System_call attribute. If there is a system call active, we put
109 * the process back in the syscall state. If not, we put it back in user
113 * the time in the state system of the change
114 * @param currentThreadNode
115 * The current thread node
118 * @throws AttributeNotFoundException
119 * an attribute does not exists yet
120 * @throws TimeRangeException
121 * the time is out of range
122 * @throws StateValueTypeException
123 * the attribute was not set with int values
125 public static void setProcessToRunning(long timestamp
, int currentThreadNode
, ITmfStateSystemBuilder ssb
)
126 throws AttributeNotFoundException
, TimeRangeException
,
127 StateValueTypeException
{
129 ITmfStateValue value
;
131 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
132 if (ssb
.queryOngoingState(quark
).isNull()) {
133 /* We were in user mode before the interruption */
134 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
136 /* We were previously in kernel mode */
137 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
139 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
140 ssb
.modifyAttribute(timestamp
, value
, quark
);
150 * @return the IRQ node quark
152 public static int getNodeIRQs(int cpuNumber
, ITmfStateSystemBuilder ss
) {
153 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
, Integer
.toString(cpuNumber
), Attributes
.IRQS
);
161 * @return the CPU node quark
163 public static int getNodeCPUs(ITmfStateSystemBuilder ss
) {
164 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);
168 * Get the Soft IRQs node
174 * @return the Soft IRQ node quark
176 public static int getNodeSoftIRQs(int cpuNumber
, ITmfStateSystemBuilder ss
) {
177 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
, Integer
.toString(cpuNumber
), Attributes
.SOFT_IRQS
);
181 * Get the threads node
185 * @return the threads quark
187 public static int getNodeThreads(ITmfStateSystemBuilder ss
) {
188 return ss
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
);
192 * Reset the CPU's status when it's coming out of an interruption.
195 * the time when the status of the cpu is "leaving irq"
197 * the cpu returning to its previous state
201 * @throws StateValueTypeException
202 * the attribute is not set as an int
203 * @throws AttributeNotFoundException
204 * the attribute was not created yet
205 * @throws TimeRangeException
206 * the time is out of range
208 public static void cpuExitInterrupt(long timestamp
, Integer cpuNumber
, ITmfStateSystemBuilder ssb
)
209 throws StateValueTypeException
, AttributeNotFoundException
,
212 int currentCPUNode
= getCurrentCPUNode(cpuNumber
, ssb
);
214 quark
= ssb
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
215 ITmfStateValue value
= getCpuStatus(ssb
, currentCPUNode
);
216 ssb
.modifyAttribute(timestamp
, value
, quark
);
220 * Get the ongoing Status state of a CPU.
222 * This will look through the states of the
230 * under the CPU, giving priority to states higher in the list. If the state
231 * is a null value, we continue looking down the list.
236 * The *quark* of the CPU we are looking for. Careful, this is
237 * NOT the CPU number (or attribute name)!
238 * @return The state value that represents the status of the given CPU
239 * @throws AttributeNotFoundException
241 private static ITmfStateValue
getCpuStatus(ITmfStateSystemBuilder ssb
, int cpuQuark
)
242 throws AttributeNotFoundException
{
244 /* Check if there is a IRQ running */
245 int irqQuarks
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.IRQS
);
246 List
<Integer
> irqs
= ssb
.getSubAttributes(irqQuarks
, false);
247 for (Integer quark
: irqs
) {
248 final ITmfStateValue irqState
= ssb
.queryOngoingState(quark
.intValue());
249 if (!irqState
.isNull()) {
254 /* Check if there is a soft IRQ running */
255 int softIrqQuarks
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.SOFT_IRQS
);
256 List
<Integer
> softIrqs
= ssb
.getSubAttributes(softIrqQuarks
, false);
257 for (Integer quark
: softIrqs
) {
258 final ITmfStateValue softIrqState
= ssb
.queryOngoingState(quark
.intValue());
259 if (!softIrqState
.isNull()) {
265 * Check if there is a thread running. If not, report IDLE. If there is,
266 * report the running state of the thread (usermode or system call).
268 int currentThreadQuark
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.CURRENT_THREAD
);
269 ITmfStateValue currentThreadState
= ssb
.queryOngoingState(currentThreadQuark
);
270 if (currentThreadState
.isNull()) {
271 return TmfStateValue
.nullValue();
273 int tid
= currentThreadState
.unboxInt();
275 return StateValues
.CPU_STATUS_IDLE_VALUE
;
277 int threadSystemCallQuark
= ssb
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
, Integer
.toString(tid
), Attributes
.SYSTEM_CALL
);
278 return (ssb
.queryOngoingState(threadSystemCallQuark
).isNull() ?
279 StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
:
280 StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
);
284 * Build the thread attribute name.
286 * For all threads except "0" this is the string representation of the threadId.
287 * For thread "0" which is the idle thread and can be running concurrently on multiple
288 * CPUs, append "_cpuId".
295 * @return the thread attribute name
296 * null if the threadId is zero and the cpuId is null
298 public static @Nullable String
buildThreadAttributeName(int threadId
, @Nullable Integer cpuId
) {
304 return Attributes
.THREAD_0_PREFIX
+ String
.valueOf(cpuId
);
307 return String
.valueOf(threadId
);
311 * Parse the thread id and CPU id from the thread attribute name string
313 * For thread "0" the attribute name is in the form "threadId_cpuId", extract both
314 * values from the string.
316 * For all other threads, the attribute name is the string representation of the
317 * threadId and there is no cpuId.
319 * @param threadAttributeName
320 * the thread attribute name
321 * @return the thread id and cpu id
323 public static Pair
<Integer
, Integer
> parseThreadAttributeName(String threadAttributeName
) {
324 Integer threadId
= -1;
328 if (threadAttributeName
.startsWith(Attributes
.THREAD_0_PREFIX
)) {
330 String
[] tokens
= threadAttributeName
.split(Attributes
.THREAD_0_SEPARATOR
);
331 cpuId
= Integer
.parseInt(tokens
[1]);
333 threadId
= Integer
.parseInt(threadAttributeName
);
335 } catch (NumberFormatException e1
) {
339 return new Pair
<>(threadId
, cpuId
);