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