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