Commit | Line | Data |
---|---|---|
af3275f8 AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2015 Ericsson | |
3 | * | |
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 | *******************************************************************************/ | |
9 | ||
10 | package org.lttng.scope.lttng.kernel.core.analysis.os.handlers.internal; | |
11 | ||
12 | import java.util.List; | |
13 | ||
14 | import org.eclipse.jdt.annotation.Nullable; | |
15 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; | |
16 | import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect; | |
17 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
18 | import org.lttng.scope.lttng.kernel.core.analysis.os.Attributes; | |
19 | import org.lttng.scope.lttng.kernel.core.analysis.os.StateValues; | |
20 | ||
21 | import ca.polymtl.dorsal.libdelorean.ITmfStateSystemBuilder; | |
22 | import ca.polymtl.dorsal.libdelorean.exceptions.AttributeNotFoundException; | |
23 | import ca.polymtl.dorsal.libdelorean.exceptions.StateValueTypeException; | |
24 | import ca.polymtl.dorsal.libdelorean.exceptions.TimeRangeException; | |
25 | import ca.polymtl.dorsal.libdelorean.statevalue.ITmfStateValue; | |
26 | import ca.polymtl.dorsal.libdelorean.statevalue.TmfStateValue; | |
27 | ||
28 | /** | |
29 | * Kernel Event Handler Utils is a collection of static methods to be used in | |
30 | * subclasses of IKernelEventHandler. | |
31 | * | |
32 | * @author Matthew Khouzam | |
33 | * @author Francis Giraldeau | |
34 | */ | |
35 | public final class KernelEventHandlerUtils { | |
36 | ||
37 | private KernelEventHandlerUtils() { | |
38 | } | |
39 | ||
40 | /** | |
41 | * Get CPU | |
42 | * | |
43 | * @param event | |
44 | * The event containing the cpu | |
45 | * | |
46 | * @return the CPU number (null for not set) | |
47 | */ | |
48 | public static @Nullable Integer getCpu(ITmfEvent event) { | |
49 | Integer cpuObj = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); | |
50 | if (cpuObj == null) { | |
51 | /* We couldn't find any CPU information, ignore this event */ | |
52 | return null; | |
53 | } | |
54 | return cpuObj; | |
55 | } | |
56 | ||
57 | /** | |
58 | * Gets the current CPU quark | |
59 | * | |
60 | * @param cpuNumber | |
61 | * The cpu number | |
62 | * @param ss | |
63 | * the state system | |
64 | * | |
65 | * @return the current CPU quark -1 for not set | |
66 | */ | |
67 | public static int getCurrentCPUNode(Integer cpuNumber, ITmfStateSystemBuilder ss) { | |
68 | return ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpuNumber.toString()); | |
69 | } | |
70 | ||
71 | /** | |
72 | * Get the timestamp of the event | |
73 | * | |
74 | * @param event | |
75 | * the event containing the timestamp | |
76 | * | |
77 | * @return the timestamp in long format | |
78 | */ | |
79 | public static long getTimestamp(ITmfEvent event) { | |
80 | return event.getTimestamp().toNanos(); | |
81 | } | |
82 | ||
83 | /** | |
84 | * Get the current thread node | |
85 | * | |
86 | * @param cpuNumber | |
87 | * The cpu number | |
88 | * @param ss | |
89 | * the state system | |
90 | * | |
91 | * @return the current thread node quark | |
92 | */ | |
93 | public static int getCurrentThreadNode(Integer cpuNumber, ITmfStateSystemBuilder ss) { | |
94 | /* | |
95 | * Shortcut for the "current thread" attribute node. It requires | |
96 | * querying the current CPU's current thread. | |
97 | */ | |
98 | int quark = ss.getQuarkRelativeAndAdd(getCurrentCPUNode(cpuNumber, ss), Attributes.CURRENT_THREAD); | |
99 | ITmfStateValue value = ss.queryOngoingState(quark); | |
100 | int thread = value.isNull() ? -1 : value.unboxInt(); | |
101 | return ss.getQuarkRelativeAndAdd(getNodeThreads(ss), Attributes.buildThreadAttributeName(thread, cpuNumber)); | |
102 | } | |
103 | ||
104 | /** | |
105 | * When we want to set a process back to a "running" state, first check its | |
106 | * current System_call attribute. If there is a system call active, we put | |
107 | * the process back in the syscall state. If not, we put it back in user | |
108 | * mode state. | |
109 | * | |
110 | * @param timestamp | |
111 | * the time in the state system of the change | |
112 | * @param currentThreadNode | |
113 | * The current thread node | |
114 | * @param ssb | |
115 | * the state system | |
116 | * @throws TimeRangeException | |
117 | * the time is out of range | |
118 | * @throws StateValueTypeException | |
119 | * the attribute was not set with int values | |
120 | * @throws AttributeNotFoundException | |
121 | * If the attribute is invalid | |
122 | */ | |
123 | public static void setProcessToRunning(long timestamp, int currentThreadNode, ITmfStateSystemBuilder ssb) | |
124 | throws TimeRangeException, StateValueTypeException, AttributeNotFoundException { | |
125 | int quark; | |
126 | ITmfStateValue value; | |
127 | ||
128 | quark = ssb.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
129 | if (ssb.queryOngoingState(quark).isNull()) { | |
130 | /* We were in user mode before the interruption */ | |
131 | value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE; | |
132 | } else { | |
133 | /* We were previously in kernel mode */ | |
134 | value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE; | |
135 | } | |
136 | ssb.modifyAttribute(timestamp, value, currentThreadNode); | |
137 | } | |
138 | ||
139 | /** | |
140 | * Get the IRQs node | |
141 | * | |
142 | * @param cpuNumber | |
143 | * the cpu core | |
144 | * @param ss | |
145 | * the state system | |
146 | * @return the IRQ node quark | |
147 | */ | |
148 | public static int getNodeIRQs(int cpuNumber, ITmfStateSystemBuilder ss) { | |
149 | return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.IRQS); | |
150 | } | |
151 | ||
152 | /** | |
153 | * Get the CPUs node | |
154 | * | |
155 | * @param ss | |
156 | * the state system | |
157 | * @return the CPU node quark | |
158 | */ | |
159 | public static int getNodeCPUs(ITmfStateSystemBuilder ss) { | |
160 | return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS); | |
161 | } | |
162 | ||
163 | /** | |
164 | * Get the Soft IRQs node | |
165 | * | |
166 | * @param cpuNumber | |
167 | * the cpu core | |
168 | * @param ss | |
169 | * the state system | |
170 | * @return the Soft IRQ node quark | |
171 | */ | |
172 | public static int getNodeSoftIRQs(int cpuNumber, ITmfStateSystemBuilder ss) { | |
173 | return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.SOFT_IRQS); | |
174 | } | |
175 | ||
176 | /** | |
177 | * Get the threads node | |
178 | * | |
179 | * @param ss | |
180 | * the state system | |
181 | * @return the threads quark | |
182 | */ | |
183 | public static int getNodeThreads(ITmfStateSystemBuilder ss) { | |
184 | return ss.getQuarkAbsoluteAndAdd(Attributes.THREADS); | |
185 | } | |
186 | ||
187 | /** | |
188 | * Reset the CPU's status when it's coming out of an interruption. | |
189 | * | |
190 | * @param timestamp | |
191 | * the time when the status of the cpu is "leaving irq" | |
192 | * @param cpuNumber | |
193 | * the cpu returning to its previous state | |
194 | * | |
195 | * @param ssb | |
196 | * State system | |
197 | * @throws StateValueTypeException | |
198 | * the attribute is not set as an int | |
199 | * @throws TimeRangeException | |
200 | * the time is out of range | |
201 | * @throws AttributeNotFoundException | |
202 | * If the attribute is invalid | |
203 | */ | |
204 | public static void cpuExitInterrupt(long timestamp, Integer cpuNumber, ITmfStateSystemBuilder ssb) | |
205 | throws StateValueTypeException, TimeRangeException, AttributeNotFoundException { | |
206 | int currentCPUNode = getCurrentCPUNode(cpuNumber, ssb); | |
207 | ||
208 | ITmfStateValue value = getCpuStatus(ssb, currentCPUNode); | |
209 | ssb.modifyAttribute(timestamp, value, currentCPUNode); | |
210 | } | |
211 | ||
212 | /** | |
213 | * Get the ongoing Status state of a CPU. | |
214 | * | |
215 | * This will look through the states of the | |
216 | * | |
217 | * <ul> | |
218 | * <li>IRQ</li> | |
219 | * <li>Soft IRQ</li> | |
220 | * <li>Process</li> | |
221 | * </ul> | |
222 | * | |
223 | * under the CPU, giving priority to states higher in the list. If the state | |
224 | * is a null value, we continue looking down the list. | |
225 | * | |
226 | * @param ssb | |
227 | * The state system | |
228 | * @param cpuQuark | |
229 | * The *quark* of the CPU we are looking for. Careful, this is | |
230 | * NOT the CPU number (or attribute name)! | |
231 | * @return The state value that represents the status of the given CPU | |
232 | * @throws AttributeNotFoundException | |
233 | */ | |
234 | private static ITmfStateValue getCpuStatus(ITmfStateSystemBuilder ssb, int cpuQuark) | |
235 | throws AttributeNotFoundException { | |
236 | ||
237 | /* Check if there is a IRQ running */ | |
238 | int irqQuarks = ssb.getQuarkRelativeAndAdd(cpuQuark, Attributes.IRQS); | |
239 | List<Integer> irqs = ssb.getSubAttributes(irqQuarks, false); | |
240 | for (Integer quark : irqs) { | |
241 | final ITmfStateValue irqState = ssb.queryOngoingState(quark.intValue()); | |
242 | if (!irqState.isNull()) { | |
243 | return irqState; | |
244 | } | |
245 | } | |
246 | ||
247 | /* Check if there is a soft IRQ running */ | |
248 | int softIrqQuarks = ssb.getQuarkRelativeAndAdd(cpuQuark, Attributes.SOFT_IRQS); | |
249 | List<Integer> softIrqs = ssb.getSubAttributes(softIrqQuarks, false); | |
250 | for (Integer quark : softIrqs) { | |
251 | final ITmfStateValue softIrqState = ssb.queryOngoingState(quark.intValue()); | |
252 | if (!softIrqState.isNull()) { | |
253 | return softIrqState; | |
254 | } | |
255 | } | |
256 | ||
257 | /* | |
258 | * Check if there is a thread running. If not, report IDLE. If there is, | |
259 | * report the running state of the thread (usermode or system call). | |
260 | */ | |
261 | int currentThreadQuark = ssb.getQuarkRelativeAndAdd(cpuQuark, Attributes.CURRENT_THREAD); | |
262 | ITmfStateValue currentThreadState = ssb.queryOngoingState(currentThreadQuark); | |
263 | if (currentThreadState.isNull()) { | |
264 | return TmfStateValue.nullValue(); | |
265 | } | |
266 | int tid = currentThreadState.unboxInt(); | |
267 | if (tid == 0) { | |
268 | return StateValues.CPU_STATUS_IDLE_VALUE; | |
269 | } | |
270 | int threadSystemCallQuark = ssb.getQuarkAbsoluteAndAdd(Attributes.THREADS, Integer.toString(tid), Attributes.SYSTEM_CALL); | |
271 | return (ssb.queryOngoingState(threadSystemCallQuark).isNull() ? StateValues.CPU_STATUS_RUN_USERMODE_VALUE : StateValues.CPU_STATUS_RUN_SYSCALL_VALUE); | |
272 | } | |
273 | } |