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
.StateValueTypeException
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
22 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
27 * Kernel Event Handler Utils is a collection of static methods to be used in
28 * subclasses of IKernelEventHandler.
30 * @author Matthew Khouzam
31 * @author Francis Giraldeau
33 public final class KernelEventHandlerUtils
{
35 private KernelEventHandlerUtils() {
42 * The event containing the cpu
44 * @return the CPU number (null for not set)
46 public static @Nullable Integer
getCpu(ITmfEvent event
) {
47 Integer cpuObj
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
);
49 /* We couldn't find any CPU information, ignore this event */
56 * Gets the current CPU quark
63 * @return the current CPU quark -1 for not set
65 public static int getCurrentCPUNode(Integer cpuNumber
, ITmfStateSystemBuilder ss
) {
66 return ss
.getQuarkRelativeAndAdd(getNodeCPUs(ss
), cpuNumber
.toString());
70 * Get the timestamp of the event
73 * the event containing the timestamp
75 * @return the timestamp in long format
77 public static long getTimestamp(ITmfEvent event
) {
78 return event
.getTimestamp().toNanos();
82 * Get the current thread node
89 * @return the current thread node quark
91 public static int getCurrentThreadNode(Integer cpuNumber
, ITmfStateSystemBuilder ss
) {
93 * Shortcut for the "current thread" attribute node. It requires
94 * querying the current CPU's current thread.
96 int quark
= ss
.getQuarkRelativeAndAdd(getCurrentCPUNode(cpuNumber
, ss
), Attributes
.CURRENT_THREAD
);
97 ITmfStateValue value
= ss
.queryOngoingState(quark
);
98 int thread
= value
.isNull() ?
-1 : value
.unboxInt();
99 return ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), Attributes
.buildThreadAttributeName(thread
, cpuNumber
));
103 * When we want to set a process back to a "running" state, first check its
104 * current System_call attribute. If there is a system call active, we put
105 * the process back in the syscall state. If not, we put it back in user
109 * the time in the state system of the change
110 * @param currentThreadNode
111 * The current thread node
114 * @throws TimeRangeException
115 * the time is out of range
116 * @throws StateValueTypeException
117 * the attribute was not set with int values
119 public static void setProcessToRunning(long timestamp
, int currentThreadNode
, ITmfStateSystemBuilder ssb
)
120 throws TimeRangeException
,
121 StateValueTypeException
{
123 ITmfStateValue value
;
125 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
126 if (ssb
.queryOngoingState(quark
).isNull()) {
127 /* We were in user mode before the interruption */
128 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
130 /* We were previously in kernel mode */
131 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
133 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
134 ssb
.modifyAttribute(timestamp
, value
, quark
);
144 * @return the IRQ node quark
146 public static int getNodeIRQs(int cpuNumber
, ITmfStateSystemBuilder ss
) {
147 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
, Integer
.toString(cpuNumber
), Attributes
.IRQS
);
155 * @return the CPU node quark
157 public static int getNodeCPUs(ITmfStateSystemBuilder ss
) {
158 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);
162 * Get the Soft IRQs node
168 * @return the Soft IRQ node quark
170 public static int getNodeSoftIRQs(int cpuNumber
, ITmfStateSystemBuilder ss
) {
171 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
, Integer
.toString(cpuNumber
), Attributes
.SOFT_IRQS
);
175 * Get the threads node
179 * @return the threads quark
181 public static int getNodeThreads(ITmfStateSystemBuilder ss
) {
182 return ss
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
);
186 * Reset the CPU's status when it's coming out of an interruption.
189 * the time when the status of the cpu is "leaving irq"
191 * the cpu returning to its previous state
195 * @throws StateValueTypeException
196 * the attribute is not set as an int
197 * @throws TimeRangeException
198 * the time is out of range
200 public static void cpuExitInterrupt(long timestamp
, Integer cpuNumber
, ITmfStateSystemBuilder ssb
)
201 throws StateValueTypeException
, TimeRangeException
{
203 int currentCPUNode
= getCurrentCPUNode(cpuNumber
, ssb
);
205 quark
= ssb
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
206 ITmfStateValue value
= getCpuStatus(ssb
, currentCPUNode
);
207 ssb
.modifyAttribute(timestamp
, value
, quark
);
211 * Get the ongoing Status state of a CPU.
213 * This will look through the states of the
221 * under the CPU, giving priority to states higher in the list. If the state
222 * is a null value, we continue looking down the list.
227 * The *quark* of the CPU we are looking for. Careful, this is
228 * NOT the CPU number (or attribute name)!
229 * @return The state value that represents the status of the given CPU
231 private static ITmfStateValue
getCpuStatus(ITmfStateSystemBuilder ssb
, int cpuQuark
) {
233 /* Check if there is a IRQ running */
234 int irqQuarks
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.IRQS
);
235 List
<Integer
> irqs
= ssb
.getSubAttributes(irqQuarks
, false);
236 for (Integer quark
: irqs
) {
237 final ITmfStateValue irqState
= ssb
.queryOngoingState(quark
.intValue());
238 if (!irqState
.isNull()) {
243 /* Check if there is a soft IRQ running */
244 int softIrqQuarks
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.SOFT_IRQS
);
245 List
<Integer
> softIrqs
= ssb
.getSubAttributes(softIrqQuarks
, false);
246 for (Integer quark
: softIrqs
) {
247 final ITmfStateValue softIrqState
= ssb
.queryOngoingState(quark
.intValue());
248 if (!softIrqState
.isNull()) {
254 * Check if there is a thread running. If not, report IDLE. If there is,
255 * report the running state of the thread (usermode or system call).
257 int currentThreadQuark
= ssb
.getQuarkRelativeAndAdd(cpuQuark
, Attributes
.CURRENT_THREAD
);
258 ITmfStateValue currentThreadState
= ssb
.queryOngoingState(currentThreadQuark
);
259 if (currentThreadState
.isNull()) {
260 return TmfStateValue
.nullValue();
262 int tid
= currentThreadState
.unboxInt();
264 return StateValues
.CPU_STATUS_IDLE_VALUE
;
266 int threadSystemCallQuark
= ssb
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
, Integer
.toString(tid
), Attributes
.SYSTEM_CALL
);
267 return (ssb
.queryOngoingState(threadSystemCallQuark
).isNull() ? StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
: StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
);