Commit | Line | Data |
---|---|---|
efc403bb | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2012, 2014 Ericsson |
efc403bb AM |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
d85d2a6d | 5 | * |
efc403bb AM |
6 | * All rights reserved. This program and the accompanying materials are |
7 | * made available under the terms of the Eclipse Public License v1.0 which | |
8 | * accompanies this distribution, and is available at | |
9 | * http://www.eclipse.org/legal/epl-v10.html | |
d85d2a6d | 10 | * |
efc403bb AM |
11 | *******************************************************************************/ |
12 | ||
42d5b5f2 | 13 | package org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel; |
efc403bb | 14 | |
d0c7e4ba AM |
15 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
16 | ||
7411cd67 AM |
17 | import java.util.Map; |
18 | ||
19 | import org.eclipse.jdt.annotation.NonNull; | |
9bc60be7 | 20 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.Attributes; |
9bc60be7 | 21 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.StateValues; |
7411cd67 | 22 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.IKernelAnalysisEventLayout; |
e894a508 AM |
23 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; |
24 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
25 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; | |
26 | import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | |
27 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
28 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
2bdf0193 AM |
29 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; |
30 | import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; | |
1786026d | 31 | import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect; |
2bdf0193 AM |
32 | import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider; |
33 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
1786026d | 34 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; |
efc403bb | 35 | |
7411cd67 AM |
36 | import com.google.common.collect.ImmutableMap; |
37 | ||
efc403bb AM |
38 | /** |
39 | * This is the state change input plugin for TMF's state system which handles | |
40 | * the LTTng 2.0 kernel traces in CTF format. | |
d85d2a6d | 41 | * |
efc403bb | 42 | * It uses the reference handler defined in CTFKernelHandler.java. |
d85d2a6d | 43 | * |
efc403bb | 44 | * @author alexmont |
d85d2a6d | 45 | * |
efc403bb | 46 | */ |
d3ba47d4 | 47 | public class LttngKernelStateProvider extends AbstractTmfStateProvider { |
efc403bb | 48 | |
7411cd67 AM |
49 | // ------------------------------------------------------------------------ |
50 | // Static fields | |
51 | // ------------------------------------------------------------------------ | |
52 | ||
a96cc6be AM |
53 | /** |
54 | * Version number of this state provider. Please bump this if you modify the | |
55 | * contents of the generated state history in some way. | |
56 | */ | |
acba092b | 57 | private static final int VERSION = 5; |
a96cc6be | 58 | |
7411cd67 AM |
59 | private static final int IRQ_HANDLER_ENTRY_INDEX = 1; |
60 | private static final int IRQ_HANDLER_EXIT_INDEX = 2; | |
61 | private static final int SOFT_IRQ_ENTRY_INDEX = 3; | |
62 | private static final int SOFT_IRQ_EXIT_INDEX = 4; | |
63 | private static final int SOFT_IRQ_RAISE_INDEX = 5; | |
64 | private static final int SCHED_SWITCH_INDEX = 6; | |
65 | private static final int SCHED_PROCESS_FORK_INDEX = 7; | |
66 | private static final int SCHED_PROCESS_EXIT_INDEX = 8; | |
67 | private static final int SCHED_PROCESS_FREE_INDEX = 9; | |
68 | private static final int STATEDUMP_PROCESS_STATE_INDEX = 10; | |
69 | private static final int SCHED_WAKEUP_INDEX = 11; | |
70 | ||
71 | ||
72 | // ------------------------------------------------------------------------ | |
73 | // Fields | |
74 | // ------------------------------------------------------------------------ | |
75 | ||
76 | private final Map<String, Integer> fEventNames; | |
77 | private final @NonNull IKernelAnalysisEventLayout fLayout; | |
78 | ||
6383e95d AM |
79 | // ------------------------------------------------------------------------ |
80 | // Constructor | |
81 | // ------------------------------------------------------------------------ | |
efc403bb AM |
82 | |
83 | /** | |
84 | * Instantiate a new state provider plugin. | |
d85d2a6d AM |
85 | * |
86 | * @param trace | |
efc403bb | 87 | * The LTTng 2.0 kernel trace directory |
7411cd67 AM |
88 | * @param layout |
89 | * The event layout to use for this state provider. Usually | |
90 | * depending on the tracer implementation. | |
efc403bb | 91 | */ |
d0c7e4ba | 92 | public LttngKernelStateProvider(@NonNull ITmfTrace trace, @NonNull IKernelAnalysisEventLayout layout) { |
7411cd67 AM |
93 | super(trace, ITmfEvent.class, "Kernel"); //$NON-NLS-1$ |
94 | fLayout = layout; | |
95 | fEventNames = buildEventNames(layout); | |
96 | } | |
97 | ||
98 | // ------------------------------------------------------------------------ | |
99 | // Event names management | |
100 | // ------------------------------------------------------------------------ | |
101 | ||
102 | private static Map<String, Integer> buildEventNames(IKernelAnalysisEventLayout layout) { | |
103 | ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder(); | |
104 | ||
7411cd67 AM |
105 | builder.put(layout.eventIrqHandlerEntry(), IRQ_HANDLER_ENTRY_INDEX); |
106 | builder.put(layout.eventIrqHandlerExit(), IRQ_HANDLER_EXIT_INDEX); | |
107 | builder.put(layout.eventSoftIrqEntry(), SOFT_IRQ_ENTRY_INDEX); | |
108 | builder.put(layout.eventSoftIrqExit(), SOFT_IRQ_EXIT_INDEX); | |
109 | builder.put(layout.eventSoftIrqRaise(), SOFT_IRQ_RAISE_INDEX); | |
110 | builder.put(layout.eventSchedSwitch(), SCHED_SWITCH_INDEX); | |
111 | builder.put(layout.eventSchedProcessFork(), SCHED_PROCESS_FORK_INDEX); | |
112 | builder.put(layout.eventSchedProcessExit(), SCHED_PROCESS_EXIT_INDEX); | |
113 | builder.put(layout.eventSchedProcessFree(), SCHED_PROCESS_FREE_INDEX); | |
bd0e2f70 AM |
114 | |
115 | if (layout.eventStatedumpProcessState() != null) { | |
116 | builder.put(layout.eventStatedumpProcessState(), STATEDUMP_PROCESS_STATE_INDEX); | |
117 | } | |
7411cd67 AM |
118 | |
119 | for (String eventSchedWakeup : layout.eventsSchedWakeup()) { | |
120 | builder.put(eventSchedWakeup, SCHED_WAKEUP_INDEX); | |
121 | } | |
122 | ||
123 | return builder.build(); | |
2c2f900e | 124 | } |
efc403bb | 125 | |
6383e95d AM |
126 | // ------------------------------------------------------------------------ |
127 | // IStateChangeInput | |
128 | // ------------------------------------------------------------------------ | |
129 | ||
a96cc6be AM |
130 | @Override |
131 | public int getVersion() { | |
132 | return VERSION; | |
133 | } | |
134 | ||
2c2f900e | 135 | @Override |
f1f86dfb | 136 | public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) { |
79e0a1df AM |
137 | /* We can only set up the locations once the state system is assigned */ |
138 | super.assignTargetStateSystem(ssb); | |
2c2f900e | 139 | } |
efc403bb | 140 | |
e96ab5c4 | 141 | @Override |
d3ba47d4 | 142 | public LttngKernelStateProvider getNewInstance() { |
7411cd67 | 143 | return new LttngKernelStateProvider(this.getTrace(), fLayout); |
e96ab5c4 AM |
144 | } |
145 | ||
efc403bb | 146 | @Override |
1786026d | 147 | protected void eventHandle(ITmfEvent event) { |
d0c7e4ba AM |
148 | ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder()); |
149 | ||
1786026d GB |
150 | Integer cpu = null; |
151 | Iterable<TmfCpuAspect> aspects = TmfTraceUtils.getEventAspectsOfClass(event.getTrace(), TmfCpuAspect.class); | |
152 | for (TmfCpuAspect aspect : aspects) { | |
153 | if (!aspect.resolve(event).equals(TmfCpuAspect.CPU_UNAVAILABLE)) { | |
154 | cpu = aspect.resolve(event); | |
155 | break; | |
156 | } | |
157 | } | |
158 | if (cpu == null) { | |
159 | /* We couldn't find any CPU information, ignore this event */ | |
e1de2fd4 AM |
160 | return; |
161 | } | |
79e0a1df | 162 | |
33803b9b | 163 | final String eventName = event.getType().getName(); |
79e0a1df AM |
164 | final long ts = event.getTimestamp().getValue(); |
165 | ||
2c2f900e | 166 | try { |
79e0a1df | 167 | /* Shortcut for the "current CPU" attribute node */ |
d0c7e4ba | 168 | final int currentCPUNode = ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpu.toString()); |
79e0a1df AM |
169 | |
170 | /* | |
171 | * Shortcut for the "current thread" attribute node. It requires | |
172 | * querying the current CPU's current thread. | |
173 | */ | |
3ae73cfa AM |
174 | int quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD); |
175 | ITmfStateValue value = ss.queryOngoingState(quark); | |
359eeba0 | 176 | int thread = value.isNull() ? -1 : value.unboxInt(); |
d0c7e4ba | 177 | final int currentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(thread)); |
79e0a1df AM |
178 | |
179 | /* | |
180 | * Feed event to the history system if it's known to cause a state | |
181 | * transition. | |
182 | */ | |
7411cd67 AM |
183 | Integer idx = fEventNames.get(eventName); |
184 | int intval = (idx == null ? -1 : idx.intValue()); | |
185 | switch (intval) { | |
79e0a1df | 186 | |
7411cd67 | 187 | case IRQ_HANDLER_ENTRY_INDEX: |
79e0a1df | 188 | { |
7411cd67 | 189 | Integer irqId = ((Long) event.getContent().getField(fLayout.fieldIrq()).getValue()).intValue(); |
79e0a1df AM |
190 | |
191 | /* Mark this IRQ as active in the resource tree. | |
192 | * The state value = the CPU on which this IRQ is sitting */ | |
d0c7e4ba | 193 | quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(ss), irqId.toString()); |
1786026d | 194 | value = TmfStateValue.newValueInt(cpu.intValue()); |
79e0a1df AM |
195 | ss.modifyAttribute(ts, value, quark); |
196 | ||
197 | /* Change the status of the running process to interrupted */ | |
198 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 199 | value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE; |
79e0a1df AM |
200 | ss.modifyAttribute(ts, value, quark); |
201 | ||
202 | /* Change the status of the CPU to interrupted */ | |
203 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 204 | value = StateValues.CPU_STATUS_IRQ_VALUE; |
79e0a1df AM |
205 | ss.modifyAttribute(ts, value, quark); |
206 | } | |
207 | break; | |
208 | ||
7411cd67 | 209 | case IRQ_HANDLER_EXIT_INDEX: |
79e0a1df | 210 | { |
7411cd67 | 211 | Integer irqId = ((Long) event.getContent().getField(fLayout.fieldIrq()).getValue()).intValue(); |
79e0a1df AM |
212 | |
213 | /* Put this IRQ back to inactive in the resource tree */ | |
d0c7e4ba | 214 | quark = ss.getQuarkRelativeAndAdd(getNodeIRQs(ss), irqId.toString()); |
79e0a1df AM |
215 | value = TmfStateValue.nullValue(); |
216 | ss.modifyAttribute(ts, value, quark); | |
217 | ||
218 | /* Set the previous process back to running */ | |
d0c7e4ba | 219 | setProcessToRunning(ss, ts, currentThreadNode); |
79e0a1df AM |
220 | |
221 | /* Set the CPU status back to running or "idle" */ | |
d0c7e4ba | 222 | cpuExitInterrupt(ss, ts, currentCPUNode, currentThreadNode); |
79e0a1df AM |
223 | } |
224 | break; | |
225 | ||
7411cd67 | 226 | case SOFT_IRQ_ENTRY_INDEX: |
79e0a1df | 227 | { |
7411cd67 | 228 | Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue(); |
79e0a1df AM |
229 | |
230 | /* Mark this SoftIRQ as active in the resource tree. | |
231 | * The state value = the CPU on which this SoftIRQ is processed */ | |
d0c7e4ba | 232 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString()); |
1786026d | 233 | value = TmfStateValue.newValueInt(cpu.intValue()); |
79e0a1df AM |
234 | ss.modifyAttribute(ts, value, quark); |
235 | ||
236 | /* Change the status of the running process to interrupted */ | |
237 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 238 | value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE; |
79e0a1df AM |
239 | ss.modifyAttribute(ts, value, quark); |
240 | ||
241 | /* Change the status of the CPU to interrupted */ | |
242 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 243 | value = StateValues.CPU_STATUS_SOFTIRQ_VALUE; |
79e0a1df AM |
244 | ss.modifyAttribute(ts, value, quark); |
245 | } | |
246 | break; | |
247 | ||
7411cd67 | 248 | case SOFT_IRQ_EXIT_INDEX: |
79e0a1df | 249 | { |
7411cd67 | 250 | Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue(); |
79e0a1df AM |
251 | |
252 | /* Put this SoftIRQ back to inactive (= -1) in the resource tree */ | |
d0c7e4ba | 253 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString()); |
79e0a1df AM |
254 | value = TmfStateValue.nullValue(); |
255 | ss.modifyAttribute(ts, value, quark); | |
256 | ||
257 | /* Set the previous process back to running */ | |
d0c7e4ba | 258 | setProcessToRunning(ss, ts, currentThreadNode); |
79e0a1df AM |
259 | |
260 | /* Set the CPU status back to "busy" or "idle" */ | |
d0c7e4ba | 261 | cpuExitInterrupt(ss, ts, currentCPUNode, currentThreadNode); |
79e0a1df AM |
262 | } |
263 | break; | |
264 | ||
7411cd67 | 265 | case SOFT_IRQ_RAISE_INDEX: |
79e0a1df AM |
266 | /* Fields: int32 vec */ |
267 | { | |
7411cd67 | 268 | Integer softIrqId = ((Long) event.getContent().getField(fLayout.fieldVec()).getValue()).intValue(); |
79e0a1df AM |
269 | |
270 | /* Mark this SoftIRQ as *raised* in the resource tree. | |
271 | * State value = -2 */ | |
d0c7e4ba | 272 | quark = ss.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss), softIrqId.toString()); |
dfb27cee | 273 | value = StateValues.SOFT_IRQ_RAISED_VALUE; |
79e0a1df AM |
274 | ss.modifyAttribute(ts, value, quark); |
275 | } | |
276 | break; | |
277 | ||
7411cd67 | 278 | case SCHED_SWITCH_INDEX: |
79e0a1df | 279 | { |
7a2f04a6 | 280 | ITmfEventField content = event.getContent(); |
7411cd67 AM |
281 | Integer prevTid = ((Long) content.getField(fLayout.fieldPrevTid()).getValue()).intValue(); |
282 | Long prevState = (Long) content.getField(fLayout.fieldPrevState()).getValue(); | |
283 | String nextProcessName = (String) content.getField(fLayout.fieldNextComm()).getValue(); | |
284 | Integer nextTid = ((Long) content.getField(fLayout.fieldNextTid()).getValue()).intValue(); | |
79e0a1df | 285 | |
d0c7e4ba AM |
286 | Integer formerThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), prevTid.toString()); |
287 | Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), nextTid.toString()); | |
79e0a1df AM |
288 | |
289 | /* Set the status of the process that got scheduled out. */ | |
290 | quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS); | |
f2338178 | 291 | if (prevState != 0) { |
dfb27cee | 292 | value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE; |
f2338178 | 293 | } else { |
dfb27cee | 294 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
f2338178 | 295 | } |
79e0a1df AM |
296 | ss.modifyAttribute(ts, value, quark); |
297 | ||
298 | /* Set the status of the new scheduled process */ | |
d0c7e4ba | 299 | setProcessToRunning(ss, ts, newCurrentThreadNode); |
79e0a1df AM |
300 | |
301 | /* Set the exec name of the new process */ | |
302 | quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.EXEC_NAME); | |
303 | value = TmfStateValue.newValueString(nextProcessName); | |
304 | ss.modifyAttribute(ts, value, quark); | |
305 | ||
25e43749 AM |
306 | /* Make sure the PPID and system_call sub-attributes exist */ |
307 | ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL); | |
308 | ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.PPID); | |
79e0a1df AM |
309 | |
310 | /* Set the current scheduled process on the relevant CPU */ | |
311 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD); | |
312 | value = TmfStateValue.newValueInt(nextTid); | |
313 | ss.modifyAttribute(ts, value, quark); | |
314 | ||
315 | /* Set the status of the CPU itself */ | |
316 | if (nextTid > 0) { | |
317 | /* Check if the entering process is in kernel or user mode */ | |
318 | quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL); | |
319 | if (ss.queryOngoingState(quark).isNull()) { | |
dfb27cee | 320 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; |
79e0a1df | 321 | } else { |
dfb27cee | 322 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
323 | } |
324 | } else { | |
dfb27cee | 325 | value = StateValues.CPU_STATUS_IDLE_VALUE; |
79e0a1df AM |
326 | } |
327 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
328 | ss.modifyAttribute(ts, value, quark); | |
329 | } | |
330 | break; | |
331 | ||
7411cd67 | 332 | case SCHED_PROCESS_FORK_INDEX: |
79e0a1df | 333 | { |
7a2f04a6 | 334 | ITmfEventField content = event.getContent(); |
79e0a1df | 335 | // String parentProcessName = (String) event.getFieldValue("parent_comm"); |
7411cd67 | 336 | String childProcessName = (String) content.getField(fLayout.fieldChildComm()).getValue(); |
79e0a1df AM |
337 | // assert ( parentProcessName.equals(childProcessName) ); |
338 | ||
7411cd67 AM |
339 | Integer parentTid = ((Long) content.getField(fLayout.fieldParentTid()).getValue()).intValue(); |
340 | Integer childTid = ((Long) content.getField(fLayout.fieldChildTid()).getValue()).intValue(); | |
79e0a1df | 341 | |
d0c7e4ba AM |
342 | Integer parentTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), parentTid.toString()); |
343 | Integer childTidNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), childTid.toString()); | |
79e0a1df AM |
344 | |
345 | /* Assign the PPID to the new process */ | |
346 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.PPID); | |
347 | value = TmfStateValue.newValueInt(parentTid); | |
348 | ss.modifyAttribute(ts, value, quark); | |
349 | ||
350 | /* Set the new process' exec_name */ | |
351 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.EXEC_NAME); | |
352 | value = TmfStateValue.newValueString(childProcessName); | |
353 | ss.modifyAttribute(ts, value, quark); | |
354 | ||
355 | /* Set the new process' status */ | |
356 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.STATUS); | |
dfb27cee | 357 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
79e0a1df AM |
358 | ss.modifyAttribute(ts, value, quark); |
359 | ||
360 | /* Set the process' syscall name, to be the same as the parent's */ | |
361 | quark = ss.getQuarkRelativeAndAdd(parentTidNode, Attributes.SYSTEM_CALL); | |
362 | value = ss.queryOngoingState(quark); | |
b46ea93c AM |
363 | if (value.isNull()) { |
364 | /* | |
365 | * Maybe we were missing info about the parent? At least we | |
366 | * will set the child right. Let's suppose "sys_clone". | |
367 | */ | |
7411cd67 | 368 | value = TmfStateValue.newValueString(fLayout.eventSyscallEntryPrefix() + IKernelAnalysisEventLayout.INITIAL_SYSCALL_NAME); |
b46ea93c | 369 | } |
79e0a1df AM |
370 | quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.SYSTEM_CALL); |
371 | ss.modifyAttribute(ts, value, quark); | |
372 | } | |
373 | break; | |
374 | ||
7411cd67 | 375 | case SCHED_PROCESS_EXIT_INDEX: |
79e0a1df AM |
376 | break; |
377 | ||
7411cd67 | 378 | case SCHED_PROCESS_FREE_INDEX: |
79e0a1df | 379 | { |
7411cd67 | 380 | Integer tid = ((Long) event.getContent().getField(fLayout.fieldTid()).getValue()).intValue(); |
79e0a1df AM |
381 | /* |
382 | * Remove the process and all its sub-attributes from the | |
383 | * current state | |
384 | */ | |
d0c7e4ba | 385 | quark = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), tid.toString()); |
79e0a1df AM |
386 | ss.removeAttribute(ts, quark); |
387 | } | |
388 | break; | |
389 | ||
7411cd67 AM |
390 | case STATEDUMP_PROCESS_STATE_INDEX: |
391 | /* LTTng-specific */ | |
79e0a1df | 392 | { |
7a2f04a6 | 393 | ITmfEventField content = event.getContent(); |
7411cd67 AM |
394 | int tid = ((Long) content.getField("tid").getValue()).intValue(); //$NON-NLS-1$ |
395 | int pid = ((Long) content.getField("pid").getValue()).intValue(); //$NON-NLS-1$ | |
396 | int ppid = ((Long) content.getField("ppid").getValue()).intValue(); //$NON-NLS-1$ | |
397 | int status = ((Long) content.getField("status").getValue()).intValue(); //$NON-NLS-1$ | |
398 | String name = (String) content.getField("name").getValue(); //$NON-NLS-1$ | |
79e0a1df AM |
399 | /* |
400 | * "mode" could be interesting too, but it doesn't seem to be | |
401 | * populated with anything relevant for now. | |
402 | */ | |
403 | ||
d0c7e4ba | 404 | int curThreadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(tid)); |
79e0a1df AM |
405 | |
406 | /* Set the process' name */ | |
407 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.EXEC_NAME); | |
408 | if (ss.queryOngoingState(quark).isNull()) { | |
409 | /* If the value didn't exist previously, set it */ | |
410 | value = TmfStateValue.newValueString(name); | |
411 | ss.modifyAttribute(ts, value, quark); | |
412 | } | |
413 | ||
414 | /* Set the process' PPID */ | |
415 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.PPID); | |
416 | if (ss.queryOngoingState(quark).isNull()) { | |
bc19bff3 AM |
417 | if (pid == tid) { |
418 | /* We have a process. Use the 'PPID' field. */ | |
419 | value = TmfStateValue.newValueInt(ppid); | |
420 | } else { | |
421 | /* We have a thread, use the 'PID' field for the parent. */ | |
422 | value = TmfStateValue.newValueInt(pid); | |
423 | } | |
79e0a1df AM |
424 | ss.modifyAttribute(ts, value, quark); |
425 | } | |
426 | ||
427 | /* Set the process' status */ | |
428 | quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.STATUS); | |
429 | if (ss.queryOngoingState(quark).isNull()) { | |
f2338178 MD |
430 | /* "2" here means "WAIT_FOR_CPU", and "5" "WAIT_BLOCKED" in the LTTng kernel. */ |
431 | if (status == 2) { | |
dfb27cee | 432 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; |
f2338178 | 433 | } else if (status == 5) { |
dfb27cee | 434 | value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE; |
79e0a1df | 435 | } else { |
dfb27cee | 436 | value = StateValues.PROCESS_STATUS_UNKNOWN_VALUE; |
79e0a1df AM |
437 | } |
438 | ss.modifyAttribute(ts, value, quark); | |
439 | } | |
440 | } | |
441 | break; | |
442 | ||
7411cd67 | 443 | case SCHED_WAKEUP_INDEX: |
d1b933e7 | 444 | { |
7411cd67 | 445 | final int tid = ((Long) event.getContent().getField(fLayout.fieldTid()).getValue()).intValue(); |
d0c7e4ba | 446 | final int threadNode = ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(tid)); |
d1b933e7 AM |
447 | |
448 | /* | |
449 | * The process indicated in the event's payload is now ready to | |
3d6e6112 FR |
450 | * run. Assign it to the "wait for cpu" state, but only if it |
451 | * was not already running. | |
d1b933e7 AM |
452 | */ |
453 | quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.STATUS); | |
3d6e6112 FR |
454 | int status = ss.queryOngoingState(quark).unboxInt(); |
455 | ||
456 | if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL && | |
457 | status != StateValues.PROCESS_STATUS_RUN_USERMODE) { | |
458 | value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE; | |
459 | ss.modifyAttribute(ts, value, quark); | |
460 | } | |
d1b933e7 AM |
461 | } |
462 | break; | |
463 | ||
79e0a1df AM |
464 | default: |
465 | /* Other event types not covered by the main switch */ | |
466 | { | |
7411cd67 AM |
467 | if (eventName.startsWith(fLayout.eventSyscallEntryPrefix()) |
468 | || eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix())) { | |
79e0a1df AM |
469 | |
470 | /* Assign the new system call to the process */ | |
471 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
472 | value = TmfStateValue.newValueString(eventName); | |
473 | ss.modifyAttribute(ts, value, quark); | |
474 | ||
475 | /* Put the process in system call mode */ | |
476 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
dfb27cee | 477 | value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
478 | ss.modifyAttribute(ts, value, quark); |
479 | ||
480 | /* Put the CPU in system call (kernel) mode */ | |
481 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
dfb27cee | 482 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df | 483 | ss.modifyAttribute(ts, value, quark); |
acba092b AM |
484 | |
485 | } else if (eventName.startsWith(fLayout.eventSyscallExitPrefix())) { | |
486 | ||
487 | /* Clear the current system call on the process */ | |
488 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); | |
489 | value = TmfStateValue.nullValue(); | |
490 | ss.modifyAttribute(ts, value, quark); | |
491 | ||
492 | /* Put the process' status back to user mode */ | |
493 | quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); | |
494 | value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE; | |
495 | ss.modifyAttribute(ts, value, quark); | |
496 | ||
497 | /* Put the CPU's status back to user mode */ | |
498 | quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS); | |
499 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; | |
500 | ss.modifyAttribute(ts, value, quark); | |
79e0a1df | 501 | } |
acba092b | 502 | |
79e0a1df AM |
503 | } |
504 | break; | |
505 | } // End of big switch | |
506 | ||
79e0a1df AM |
507 | } catch (AttributeNotFoundException ae) { |
508 | /* | |
509 | * This would indicate a problem with the logic of the manager here, | |
510 | * so it shouldn't happen. | |
511 | */ | |
512 | ae.printStackTrace(); | |
513 | ||
514 | } catch (TimeRangeException tre) { | |
515 | /* | |
516 | * This would happen if the events in the trace aren't ordered | |
517 | * chronologically, which should never be the case ... | |
518 | */ | |
519 | System.err.println("TimeRangeExcpetion caught in the state system's event manager."); //$NON-NLS-1$ | |
520 | System.err.println("Are the events in the trace correctly ordered?"); //$NON-NLS-1$ | |
521 | tre.printStackTrace(); | |
522 | ||
523 | } catch (StateValueTypeException sve) { | |
524 | /* | |
525 | * This would happen if we were trying to push/pop attributes not of | |
526 | * type integer. Which, once again, should never happen. | |
527 | */ | |
528 | sve.printStackTrace(); | |
2c2f900e AM |
529 | } |
530 | } | |
531 | ||
6383e95d AM |
532 | // ------------------------------------------------------------------------ |
533 | // Convenience methods for commonly-used attribute tree locations | |
534 | // ------------------------------------------------------------------------ | |
535 | ||
d0c7e4ba AM |
536 | private static int getNodeCPUs(ITmfStateSystemBuilder ssb) { |
537 | return ssb.getQuarkAbsoluteAndAdd(Attributes.CPUS); | |
79e0a1df AM |
538 | } |
539 | ||
d0c7e4ba AM |
540 | private static int getNodeThreads(ITmfStateSystemBuilder ssb) { |
541 | return ssb.getQuarkAbsoluteAndAdd(Attributes.THREADS); | |
6383e95d AM |
542 | } |
543 | ||
d0c7e4ba AM |
544 | private static int getNodeIRQs(ITmfStateSystemBuilder ssb) { |
545 | return ssb.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS); | |
6383e95d AM |
546 | } |
547 | ||
d0c7e4ba AM |
548 | private static int getNodeSoftIRQs(ITmfStateSystemBuilder ssb) { |
549 | return ssb.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS); | |
6383e95d AM |
550 | } |
551 | ||
6383e95d AM |
552 | // ------------------------------------------------------------------------ |
553 | // Advanced state-setting methods | |
554 | // ------------------------------------------------------------------------ | |
555 | ||
79e0a1df AM |
556 | /** |
557 | * When we want to set a process back to a "running" state, first check | |
558 | * its current System_call attribute. If there is a system call active, we | |
559 | * put the process back in the syscall state. If not, we put it back in | |
560 | * user mode state. | |
561 | */ | |
d0c7e4ba | 562 | private static void setProcessToRunning(ITmfStateSystemBuilder ssb, long ts, int currentThreadNode) |
79e0a1df AM |
563 | throws AttributeNotFoundException, TimeRangeException, |
564 | StateValueTypeException { | |
565 | int quark; | |
566 | ITmfStateValue value; | |
567 | ||
d0c7e4ba AM |
568 | quark = ssb.getQuarkRelativeAndAdd(currentThreadNode, Attributes.SYSTEM_CALL); |
569 | if (ssb.queryOngoingState(quark).isNull()) { | |
79e0a1df | 570 | /* We were in user mode before the interruption */ |
dfb27cee | 571 | value = StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
572 | } else { |
573 | /* We were previously in kernel mode */ | |
dfb27cee | 574 | value = StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df | 575 | } |
d0c7e4ba AM |
576 | quark = ssb.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS); |
577 | ssb.modifyAttribute(ts, value, quark); | |
79e0a1df AM |
578 | } |
579 | ||
580 | /** | |
581 | * Similar logic as above, but to set the CPU's status when it's coming out | |
582 | * of an interruption. | |
583 | */ | |
d0c7e4ba AM |
584 | private static void cpuExitInterrupt(ITmfStateSystemBuilder ssb, long ts, |
585 | int currentCpuNode, int currentThreadNode) | |
79e0a1df AM |
586 | throws StateValueTypeException, AttributeNotFoundException, |
587 | TimeRangeException { | |
588 | int quark; | |
589 | ITmfStateValue value; | |
590 | ||
d0c7e4ba AM |
591 | quark = ssb.getQuarkRelativeAndAdd(currentCpuNode, Attributes.CURRENT_THREAD); |
592 | if (ssb.queryOngoingState(quark).unboxInt() > 0) { | |
79e0a1df | 593 | /* There was a process on the CPU */ |
d0c7e4ba AM |
594 | quark = ssb.getQuarkRelative(currentThreadNode, Attributes.SYSTEM_CALL); |
595 | if (ssb.queryOngoingState(quark).isNull()) { | |
79e0a1df | 596 | /* That process was in user mode */ |
dfb27cee | 597 | value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE; |
79e0a1df AM |
598 | } else { |
599 | /* That process was in a system call */ | |
dfb27cee | 600 | value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE; |
79e0a1df AM |
601 | } |
602 | } else { | |
603 | /* There was no real process scheduled, CPU was idle */ | |
dfb27cee | 604 | value = StateValues.CPU_STATUS_IDLE_VALUE; |
2c2f900e | 605 | } |
d0c7e4ba AM |
606 | quark = ssb.getQuarkRelativeAndAdd(currentCpuNode, Attributes.STATUS); |
607 | ssb.modifyAttribute(ts, value, quark); | |
efc403bb AM |
608 | } |
609 | } |