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