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>
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
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.kernelanalysis
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
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
.LinuxValues
;
22 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelanalysis
.StateValues
;
23 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
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
;
37 import com
.google
.common
.collect
.ImmutableMap
;
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.
43 * It uses the reference handler defined in CTFKernelHandler.java.
48 public class KernelStateProvider
extends AbstractTmfStateProvider
{
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
55 * Version number of this state provider. Please bump this if you modify the
56 * contents of the generated state history in some way.
58 private static final int VERSION
= 9;
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;
74 // ------------------------------------------------------------------------
76 // ------------------------------------------------------------------------
78 private final Map
<String
, Integer
> fEventNames
;
79 private final IKernelAnalysisEventLayout fLayout
;
81 // ------------------------------------------------------------------------
83 // ------------------------------------------------------------------------
86 * Instantiate a new state provider plugin.
89 * The LTTng 2.0 kernel trace directory
91 * The event layout to use for this state provider. Usually
92 * depending on the tracer implementation.
94 public KernelStateProvider(ITmfTrace trace
, IKernelAnalysisEventLayout layout
) {
95 super(trace
, "Kernel"); //$NON-NLS-1$
97 fEventNames
= buildEventNames(layout
);
100 // ------------------------------------------------------------------------
101 // Event names management
102 // ------------------------------------------------------------------------
104 private static Map
<String
, Integer
> buildEventNames(IKernelAnalysisEventLayout layout
) {
105 ImmutableMap
.Builder
<String
, Integer
> builder
= ImmutableMap
.builder();
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
);
118 final String eventStatedumpProcessState
= layout
.eventStatedumpProcessState();
119 if (eventStatedumpProcessState
!= null) {
120 builder
.put(eventStatedumpProcessState
, STATEDUMP_PROCESS_STATE_INDEX
);
123 for (String eventSchedWakeup
: layout
.eventsSchedWakeup()) {
124 builder
.put(eventSchedWakeup
, SCHED_WAKEUP_INDEX
);
127 return checkNotNull(builder
.build());
130 // ------------------------------------------------------------------------
132 // ------------------------------------------------------------------------
135 public int getVersion() {
140 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb
) {
141 /* We can only set up the locations once the state system is assigned */
142 super.assignTargetStateSystem(ssb
);
146 public KernelStateProvider
getNewInstance() {
147 return new KernelStateProvider(this.getTrace(), fLayout
);
151 protected void eventHandle(@Nullable ITmfEvent event
) {
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 */
161 Integer cpu
= (Integer
) cpuObj
;
163 final String eventName
= event
.getName();
164 final long ts
= event
.getTimestamp().getValue();
167 final ITmfStateSystemBuilder ss
= checkNotNull(getStateSystemBuilder());
169 /* Shortcut for the "current CPU" attribute node */
170 final int currentCPUNode
= ss
.getQuarkRelativeAndAdd(getNodeCPUs(ss
), cpu
.toString());
173 * Shortcut for the "current thread" attribute node. It requires
174 * querying the current CPU's current thread.
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
));
182 * Feed event to the history system if it's known to cause a state
185 Integer idx
= fEventNames
.get(eventName
);
186 int intval
= (idx
== null ?
-1 : idx
.intValue());
189 case IRQ_HANDLER_ENTRY_INDEX
:
191 Integer irqId
= ((Long
) event
.getContent().getField(fLayout
.fieldIrq()).getValue()).intValue();
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
);
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
);
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
);
211 case IRQ_HANDLER_EXIT_INDEX
:
213 Integer irqId
= ((Long
) event
.getContent().getField(fLayout
.fieldIrq()).getValue()).intValue();
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
);
220 /* Set the previous process back to running */
221 setProcessToRunning(ss
, ts
, currentThreadNode
);
223 /* Set the CPU status back to running or "idle" */
224 cpuExitInterrupt(ss
, ts
, currentCPUNode
, currentThreadNode
);
228 case SOFT_IRQ_ENTRY_INDEX
:
230 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
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
);
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
);
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
);
250 case SOFT_IRQ_EXIT_INDEX
:
252 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
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
);
259 /* Set the previous process back to running */
260 setProcessToRunning(ss
, ts
, currentThreadNode
);
262 /* Set the CPU status back to "busy" or "idle" */
263 cpuExitInterrupt(ss
, ts
, currentCPUNode
, currentThreadNode
);
267 case SOFT_IRQ_RAISE_INDEX
:
268 /* Fields: int32 vec */
270 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
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
);
280 case SCHED_SWITCH_INDEX
:
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();
289 Integer formerThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), prevTid
.toString());
290 Integer newCurrentThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), nextTid
.toString());
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.
298 prevState
= prevState
& ~
(LinuxValues
.TASK_STATE_MAX
);
300 /* Set the status of the process that got scheduled out. */
301 switch (prevState
.intValue()) {
302 case LinuxValues
.TASK_STATE_RUNNING
:
303 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
305 case LinuxValues
.TASK_INTERRUPTIBLE
:
306 case LinuxValues
.TASK_UNINTERRUPTIBLE
:
307 value
= StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
;
309 case LinuxValues
.TASK_DEAD
:
310 value
= TmfStateValue
.nullValue();
313 value
= StateValues
.PROCESS_STATUS_WAIT_UNKNOWN_VALUE
;
317 quark
= ss
.getQuarkRelativeAndAdd(formerThreadNode
, Attributes
.STATUS
);
318 ss
.modifyAttribute(ts
, value
, quark
);
320 /* Set the status of the new scheduled process */
321 setProcessToRunning(ss
, ts
, newCurrentThreadNode
);
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
);
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
);
333 /* Make sure the PPID and system_call sub-attributes exist */
334 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.SYSTEM_CALL
);
335 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.PPID
);
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
);
342 /* Set the status of the CPU itself */
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()) {
347 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
349 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
352 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
354 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
355 ss
.modifyAttribute(ts
, value
, quark
);
359 case SCHED_PI_SETPRIO_INDEX
:
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();
365 Integer updateThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), tid
.toString());
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
);
374 case SCHED_PROCESS_FORK_INDEX
:
376 ITmfEventField content
= event
.getContent();
377 // String parentProcessName = (String) event.getFieldValue("parent_comm");
378 String childProcessName
= (String
) content
.getField(fLayout
.fieldChildComm()).getValue();
379 // assert ( parentProcessName.equals(childProcessName) );
381 Integer parentTid
= ((Long
) content
.getField(fLayout
.fieldParentTid()).getValue()).intValue();
382 Integer childTid
= ((Long
) content
.getField(fLayout
.fieldChildTid()).getValue()).intValue();
384 Integer parentTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), parentTid
.toString());
385 Integer childTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), childTid
.toString());
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
);
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
);
397 /* Set the new process' status */
398 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.STATUS
);
399 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
400 ss
.modifyAttribute(ts
, value
, quark
);
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
);
405 if (value
.isNull()) {
407 * Maybe we were missing info about the parent? At least we
408 * will set the child right. Let's suppose "sys_clone".
410 value
= TmfStateValue
.newValueString(fLayout
.eventSyscallEntryPrefix() + IKernelAnalysisEventLayout
.INITIAL_SYSCALL_NAME
);
412 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.SYSTEM_CALL
);
413 ss
.modifyAttribute(ts
, value
, quark
);
417 case SCHED_PROCESS_EXIT_INDEX
:
420 case SCHED_PROCESS_FREE_INDEX
:
422 Integer tid
= ((Long
) event
.getContent().getField(fLayout
.fieldTid()).getValue()).intValue();
424 * Remove the process and all its sub-attributes from the
427 quark
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), tid
.toString());
428 ss
.removeAttribute(ts
, quark
);
432 case STATEDUMP_PROCESS_STATE_INDEX
:
435 ITmfEventField content
= event
.getContent();
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$
442 * "mode" could be interesting too, but it doesn't seem to be
443 * populated with anything relevant for now.
446 int curThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), String
.valueOf(tid
));
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
);
456 /* Set the process' PPID */
457 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.PPID
);
458 if (ss
.queryOngoingState(quark
).isNull()) {
460 /* We have a process. Use the 'PPID' field. */
461 value
= TmfStateValue
.newValueInt(ppid
);
463 /* We have a thread, use the 'PID' field for the parent. */
464 value
= TmfStateValue
.newValueInt(pid
);
466 ss
.modifyAttribute(ts
, value
, quark
);
469 /* Set the process' status */
470 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.STATUS
);
471 if (ss
.queryOngoingState(quark
).isNull()) {
473 case LinuxValues
.STATEDUMP_PROCESS_STATUS_WAIT_CPU
:
474 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
476 case LinuxValues
.STATEDUMP_PROCESS_STATUS_WAIT
:
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.
483 value
= StateValues
.PROCESS_STATUS_WAIT_UNKNOWN_VALUE
;
486 value
= StateValues
.PROCESS_STATUS_UNKNOWN_VALUE
;
488 ss
.modifyAttribute(ts
, value
, quark
);
493 case SCHED_WAKEUP_INDEX
:
495 final int tid
= ((Long
) event
.getContent().getField(fLayout
.fieldTid()).getValue()).intValue();
496 final int prio
= ((Long
) event
.getContent().getField(fLayout
.fieldPrio()).getValue()).intValue();
497 final int threadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), String
.valueOf(tid
));
500 * The process indicated in the event's payload is now ready to
501 * run. Assign it to the "wait for cpu" state, but only if it
502 * was not already running.
504 quark
= ss
.getQuarkRelativeAndAdd(threadNode
, Attributes
.STATUS
);
505 int status
= ss
.queryOngoingState(quark
).unboxInt();
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
);
514 * When a user changes a threads prio (e.g. with pthread_setschedparam),
515 * it shows in ftrace with a sched_wakeup.
517 quark
= ss
.getQuarkRelativeAndAdd(threadNode
, Attributes
.PRIO
);
518 value
= TmfStateValue
.newValueInt(prio
);
519 ss
.modifyAttribute(ts
, value
, quark
);
524 /* Other event types not covered by the main switch */
526 if (eventName
.startsWith(fLayout
.eventSyscallEntryPrefix())
527 || eventName
.startsWith(fLayout
.eventCompatSyscallEntryPrefix())) {
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
);
534 /* Put the process in system call mode */
535 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
536 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
537 ss
.modifyAttribute(ts
, value
, quark
);
539 /* Put the CPU in system call (kernel) mode */
540 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
541 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
542 ss
.modifyAttribute(ts
, value
, quark
);
544 } else if (eventName
.startsWith(fLayout
.eventSyscallExitPrefix())) {
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
);
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
);
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
);
564 } // End of big switch
566 } catch (AttributeNotFoundException ae
) {
568 * This would indicate a problem with the logic of the manager here,
569 * so it shouldn't happen.
571 ae
.printStackTrace();
573 } catch (TimeRangeException tre
) {
575 * This would happen if the events in the trace aren't ordered
576 * chronologically, which should never be the case ...
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();
582 } catch (StateValueTypeException sve
) {
584 * This would happen if we were trying to push/pop attributes not of
585 * type integer. Which, once again, should never happen.
587 sve
.printStackTrace();
591 // ------------------------------------------------------------------------
592 // Convenience methods for commonly-used attribute tree locations
593 // ------------------------------------------------------------------------
595 private static int getNodeCPUs(ITmfStateSystemBuilder ssb
) {
596 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);
599 private static int getNodeThreads(ITmfStateSystemBuilder ssb
) {
600 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
);
603 private static int getNodeIRQs(ITmfStateSystemBuilder ssb
) {
604 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.IRQS
);
607 private static int getNodeSoftIRQs(ITmfStateSystemBuilder ssb
) {
608 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.SOFT_IRQS
);
611 // ------------------------------------------------------------------------
612 // Advanced state-setting methods
613 // ------------------------------------------------------------------------
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
621 private static void setProcessToRunning(ITmfStateSystemBuilder ssb
, long ts
, int currentThreadNode
)
622 throws AttributeNotFoundException
, TimeRangeException
,
623 StateValueTypeException
{
625 ITmfStateValue value
;
627 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
628 if (ssb
.queryOngoingState(quark
).isNull()) {
629 /* We were in user mode before the interruption */
630 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
632 /* We were previously in kernel mode */
633 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
635 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
636 ssb
.modifyAttribute(ts
, value
, quark
);
640 * Similar logic as above, but to set the CPU's status when it's coming out
641 * of an interruption.
643 private static void cpuExitInterrupt(ITmfStateSystemBuilder ssb
, long ts
,
644 int currentCpuNode
, int currentThreadNode
)
645 throws StateValueTypeException
, AttributeNotFoundException
,
648 ITmfStateValue value
;
650 quark
= ssb
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.CURRENT_THREAD
);
651 if (ssb
.queryOngoingState(quark
).unboxInt() > 0) {
652 /* There was a process on the CPU */
653 quark
= ssb
.getQuarkRelative(currentThreadNode
, Attributes
.SYSTEM_CALL
);
654 if (ssb
.queryOngoingState(quark
).isNull()) {
655 /* That process was in user mode */
656 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
658 /* That process was in a system call */
659 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
662 /* There was no real process scheduled, CPU was idle */
663 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
665 quark
= ssb
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.STATUS
);
666 ssb
.modifyAttribute(ts
, value
, quark
);