1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 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
.lttng2
.kernel
.core
.analysis
.kernel
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
19 import org
.eclipse
.jdt
.annotation
.NonNull
;
20 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.Attributes
;
21 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.StateValues
;
22 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.trace
.layout
.IKernelAnalysisEventLayout
;
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
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
36 import com
.google
.common
.collect
.ImmutableMap
;
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.
42 * It uses the reference handler defined in CTFKernelHandler.java.
47 public class LttngKernelStateProvider
extends AbstractTmfStateProvider
{
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
54 * Version number of this state provider. Please bump this if you modify the
55 * contents of the generated state history in some way.
57 private static final int VERSION
= 5;
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;
72 // ------------------------------------------------------------------------
74 // ------------------------------------------------------------------------
76 private final Map
<String
, Integer
> fEventNames
;
77 private final @NonNull IKernelAnalysisEventLayout fLayout
;
79 // ------------------------------------------------------------------------
81 // ------------------------------------------------------------------------
84 * Instantiate a new state provider plugin.
87 * The LTTng 2.0 kernel trace directory
89 * The event layout to use for this state provider. Usually
90 * depending on the tracer implementation.
92 public LttngKernelStateProvider(@NonNull ITmfTrace trace
, @NonNull IKernelAnalysisEventLayout layout
) {
93 super(trace
, ITmfEvent
.class, "Kernel"); //$NON-NLS-1$
95 fEventNames
= buildEventNames(layout
);
98 // ------------------------------------------------------------------------
99 // Event names management
100 // ------------------------------------------------------------------------
102 private static Map
<String
, Integer
> buildEventNames(IKernelAnalysisEventLayout layout
) {
103 ImmutableMap
.Builder
<String
, Integer
> builder
= ImmutableMap
.builder();
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
);
115 if (layout
.eventStatedumpProcessState() != null) {
116 builder
.put(layout
.eventStatedumpProcessState(), STATEDUMP_PROCESS_STATE_INDEX
);
119 for (String eventSchedWakeup
: layout
.eventsSchedWakeup()) {
120 builder
.put(eventSchedWakeup
, SCHED_WAKEUP_INDEX
);
123 return builder
.build();
126 // ------------------------------------------------------------------------
128 // ------------------------------------------------------------------------
131 public int getVersion() {
136 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb
) {
137 /* We can only set up the locations once the state system is assigned */
138 super.assignTargetStateSystem(ssb
);
142 public LttngKernelStateProvider
getNewInstance() {
143 return new LttngKernelStateProvider(this.getTrace(), fLayout
);
147 protected void eventHandle(ITmfEvent event
) {
148 ITmfStateSystemBuilder ss
= checkNotNull(getStateSystemBuilder());
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
);
159 /* We couldn't find any CPU information, ignore this event */
163 final String eventName
= event
.getType().getName();
164 final long ts
= event
.getTimestamp().getValue();
167 /* Shortcut for the "current CPU" attribute node */
168 final int currentCPUNode
= ss
.getQuarkRelativeAndAdd(getNodeCPUs(ss
), cpu
.toString());
171 * Shortcut for the "current thread" attribute node. It requires
172 * querying the current CPU's current thread.
174 int quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.CURRENT_THREAD
);
175 ITmfStateValue value
= ss
.queryOngoingState(quark
);
176 int thread
= value
.isNull() ?
-1 : value
.unboxInt();
177 final int currentThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), String
.valueOf(thread
));
180 * Feed event to the history system if it's known to cause a state
183 Integer idx
= fEventNames
.get(eventName
);
184 int intval
= (idx
== null ?
-1 : idx
.intValue());
187 case IRQ_HANDLER_ENTRY_INDEX
:
189 Integer irqId
= ((Long
) event
.getContent().getField(fLayout
.fieldIrq()).getValue()).intValue();
191 /* Mark this IRQ as active in the resource tree.
192 * The state value = the CPU on which this IRQ is sitting */
193 quark
= ss
.getQuarkRelativeAndAdd(getNodeIRQs(ss
), irqId
.toString());
194 value
= TmfStateValue
.newValueInt(cpu
.intValue());
195 ss
.modifyAttribute(ts
, value
, quark
);
197 /* Change the status of the running process to interrupted */
198 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
199 value
= StateValues
.PROCESS_STATUS_INTERRUPTED_VALUE
;
200 ss
.modifyAttribute(ts
, value
, quark
);
202 /* Change the status of the CPU to interrupted */
203 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
204 value
= StateValues
.CPU_STATUS_IRQ_VALUE
;
205 ss
.modifyAttribute(ts
, value
, quark
);
209 case IRQ_HANDLER_EXIT_INDEX
:
211 Integer irqId
= ((Long
) event
.getContent().getField(fLayout
.fieldIrq()).getValue()).intValue();
213 /* Put this IRQ back to inactive in the resource tree */
214 quark
= ss
.getQuarkRelativeAndAdd(getNodeIRQs(ss
), irqId
.toString());
215 value
= TmfStateValue
.nullValue();
216 ss
.modifyAttribute(ts
, value
, quark
);
218 /* Set the previous process back to running */
219 setProcessToRunning(ss
, ts
, currentThreadNode
);
221 /* Set the CPU status back to running or "idle" */
222 cpuExitInterrupt(ss
, ts
, currentCPUNode
, currentThreadNode
);
226 case SOFT_IRQ_ENTRY_INDEX
:
228 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
230 /* Mark this SoftIRQ as active in the resource tree.
231 * The state value = the CPU on which this SoftIRQ is processed */
232 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss
), softIrqId
.toString());
233 value
= TmfStateValue
.newValueInt(cpu
.intValue());
234 ss
.modifyAttribute(ts
, value
, quark
);
236 /* Change the status of the running process to interrupted */
237 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
238 value
= StateValues
.PROCESS_STATUS_INTERRUPTED_VALUE
;
239 ss
.modifyAttribute(ts
, value
, quark
);
241 /* Change the status of the CPU to interrupted */
242 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
243 value
= StateValues
.CPU_STATUS_SOFTIRQ_VALUE
;
244 ss
.modifyAttribute(ts
, value
, quark
);
248 case SOFT_IRQ_EXIT_INDEX
:
250 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
252 /* Put this SoftIRQ back to inactive (= -1) in the resource tree */
253 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss
), softIrqId
.toString());
254 value
= TmfStateValue
.nullValue();
255 ss
.modifyAttribute(ts
, value
, quark
);
257 /* Set the previous process back to running */
258 setProcessToRunning(ss
, ts
, currentThreadNode
);
260 /* Set the CPU status back to "busy" or "idle" */
261 cpuExitInterrupt(ss
, ts
, currentCPUNode
, currentThreadNode
);
265 case SOFT_IRQ_RAISE_INDEX
:
266 /* Fields: int32 vec */
268 Integer softIrqId
= ((Long
) event
.getContent().getField(fLayout
.fieldVec()).getValue()).intValue();
270 /* Mark this SoftIRQ as *raised* in the resource tree.
271 * State value = -2 */
272 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(ss
), softIrqId
.toString());
273 value
= StateValues
.SOFT_IRQ_RAISED_VALUE
;
274 ss
.modifyAttribute(ts
, value
, quark
);
278 case SCHED_SWITCH_INDEX
:
280 ITmfEventField content
= event
.getContent();
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();
286 Integer formerThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), prevTid
.toString());
287 Integer newCurrentThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), nextTid
.toString());
289 /* Set the status of the process that got scheduled out. */
290 quark
= ss
.getQuarkRelativeAndAdd(formerThreadNode
, Attributes
.STATUS
);
291 if (prevState
!= 0) {
292 value
= StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
;
294 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
296 ss
.modifyAttribute(ts
, value
, quark
);
298 /* Set the status of the new scheduled process */
299 setProcessToRunning(ss
, ts
, newCurrentThreadNode
);
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
);
306 /* Make sure the PPID and system_call sub-attributes exist */
307 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.SYSTEM_CALL
);
308 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.PPID
);
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
);
315 /* Set the status of the CPU itself */
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()) {
320 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
322 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
325 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
327 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
328 ss
.modifyAttribute(ts
, value
, quark
);
332 case SCHED_PROCESS_FORK_INDEX
:
334 ITmfEventField content
= event
.getContent();
335 // String parentProcessName = (String) event.getFieldValue("parent_comm");
336 String childProcessName
= (String
) content
.getField(fLayout
.fieldChildComm()).getValue();
337 // assert ( parentProcessName.equals(childProcessName) );
339 Integer parentTid
= ((Long
) content
.getField(fLayout
.fieldParentTid()).getValue()).intValue();
340 Integer childTid
= ((Long
) content
.getField(fLayout
.fieldChildTid()).getValue()).intValue();
342 Integer parentTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), parentTid
.toString());
343 Integer childTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), childTid
.toString());
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
);
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
);
355 /* Set the new process' status */
356 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.STATUS
);
357 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
358 ss
.modifyAttribute(ts
, value
, quark
);
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
);
363 if (value
.isNull()) {
365 * Maybe we were missing info about the parent? At least we
366 * will set the child right. Let's suppose "sys_clone".
368 value
= TmfStateValue
.newValueString(fLayout
.eventSyscallEntryPrefix() + IKernelAnalysisEventLayout
.INITIAL_SYSCALL_NAME
);
370 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.SYSTEM_CALL
);
371 ss
.modifyAttribute(ts
, value
, quark
);
375 case SCHED_PROCESS_EXIT_INDEX
:
378 case SCHED_PROCESS_FREE_INDEX
:
380 Integer tid
= ((Long
) event
.getContent().getField(fLayout
.fieldTid()).getValue()).intValue();
382 * Remove the process and all its sub-attributes from the
385 quark
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), tid
.toString());
386 ss
.removeAttribute(ts
, quark
);
390 case STATEDUMP_PROCESS_STATE_INDEX
:
393 ITmfEventField content
= event
.getContent();
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$
400 * "mode" could be interesting too, but it doesn't seem to be
401 * populated with anything relevant for now.
404 int curThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), String
.valueOf(tid
));
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
);
414 /* Set the process' PPID */
415 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.PPID
);
416 if (ss
.queryOngoingState(quark
).isNull()) {
418 /* We have a process. Use the 'PPID' field. */
419 value
= TmfStateValue
.newValueInt(ppid
);
421 /* We have a thread, use the 'PID' field for the parent. */
422 value
= TmfStateValue
.newValueInt(pid
);
424 ss
.modifyAttribute(ts
, value
, quark
);
427 /* Set the process' status */
428 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.STATUS
);
429 if (ss
.queryOngoingState(quark
).isNull()) {
430 /* "2" here means "WAIT_FOR_CPU", and "5" "WAIT_BLOCKED" in the LTTng kernel. */
432 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
433 } else if (status
== 5) {
434 value
= StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
;
436 value
= StateValues
.PROCESS_STATUS_UNKNOWN_VALUE
;
438 ss
.modifyAttribute(ts
, value
, quark
);
443 case SCHED_WAKEUP_INDEX
:
445 final int tid
= ((Long
) event
.getContent().getField(fLayout
.fieldTid()).getValue()).intValue();
446 final int threadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(ss
), String
.valueOf(tid
));
449 * The process indicated in the event's payload is now ready to
450 * run. Assign it to the "wait for cpu" state, but only if it
451 * was not already running.
453 quark
= ss
.getQuarkRelativeAndAdd(threadNode
, Attributes
.STATUS
);
454 int status
= ss
.queryOngoingState(quark
).unboxInt();
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
);
465 /* Other event types not covered by the main switch */
467 if (eventName
.startsWith(fLayout
.eventSyscallEntryPrefix())
468 || eventName
.startsWith(fLayout
.eventCompatSyscallEntryPrefix())) {
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
);
475 /* Put the process in system call mode */
476 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
477 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
478 ss
.modifyAttribute(ts
, value
, quark
);
480 /* Put the CPU in system call (kernel) mode */
481 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
482 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
483 ss
.modifyAttribute(ts
, value
, quark
);
485 } else if (eventName
.startsWith(fLayout
.eventSyscallExitPrefix())) {
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
);
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
);
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
);
505 } // End of big switch
507 } catch (AttributeNotFoundException ae
) {
509 * This would indicate a problem with the logic of the manager here,
510 * so it shouldn't happen.
512 ae
.printStackTrace();
514 } catch (TimeRangeException tre
) {
516 * This would happen if the events in the trace aren't ordered
517 * chronologically, which should never be the case ...
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();
523 } catch (StateValueTypeException sve
) {
525 * This would happen if we were trying to push/pop attributes not of
526 * type integer. Which, once again, should never happen.
528 sve
.printStackTrace();
532 // ------------------------------------------------------------------------
533 // Convenience methods for commonly-used attribute tree locations
534 // ------------------------------------------------------------------------
536 private static int getNodeCPUs(ITmfStateSystemBuilder ssb
) {
537 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);
540 private static int getNodeThreads(ITmfStateSystemBuilder ssb
) {
541 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
);
544 private static int getNodeIRQs(ITmfStateSystemBuilder ssb
) {
545 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.IRQS
);
548 private static int getNodeSoftIRQs(ITmfStateSystemBuilder ssb
) {
549 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.SOFT_IRQS
);
552 // ------------------------------------------------------------------------
553 // Advanced state-setting methods
554 // ------------------------------------------------------------------------
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
562 private static void setProcessToRunning(ITmfStateSystemBuilder ssb
, long ts
, int currentThreadNode
)
563 throws AttributeNotFoundException
, TimeRangeException
,
564 StateValueTypeException
{
566 ITmfStateValue value
;
568 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
569 if (ssb
.queryOngoingState(quark
).isNull()) {
570 /* We were in user mode before the interruption */
571 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
573 /* We were previously in kernel mode */
574 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
576 quark
= ssb
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
577 ssb
.modifyAttribute(ts
, value
, quark
);
581 * Similar logic as above, but to set the CPU's status when it's coming out
582 * of an interruption.
584 private static void cpuExitInterrupt(ITmfStateSystemBuilder ssb
, long ts
,
585 int currentCpuNode
, int currentThreadNode
)
586 throws StateValueTypeException
, AttributeNotFoundException
,
589 ITmfStateValue value
;
591 quark
= ssb
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.CURRENT_THREAD
);
592 if (ssb
.queryOngoingState(quark
).unboxInt() > 0) {
593 /* There was a process on the CPU */
594 quark
= ssb
.getQuarkRelative(currentThreadNode
, Attributes
.SYSTEM_CALL
);
595 if (ssb
.queryOngoingState(quark
).isNull()) {
596 /* That process was in user mode */
597 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
599 /* That process was in a system call */
600 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
603 /* There was no real process scheduled, CPU was idle */
604 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
606 quark
= ssb
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.STATUS
);
607 ssb
.modifyAttribute(ts
, value
, quark
);