1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 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
.linuxtools
.internal
.lttng2
.kernel
.core
.stateprovider
;
15 import java
.util
.HashMap
;
17 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.Attributes
;
18 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.LttngStrings
;
19 import org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.core
.StateValues
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfEvent
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfTrace
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEventField
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystemBuilder
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.TmfStateValue
;
33 * This is the state change input plugin for TMF's state system which handles
34 * the LTTng 2.0 kernel traces in CTF format.
36 * It uses the reference handler defined in CTFKernelHandler.java.
41 public class LttngKernelStateProvider
extends AbstractTmfStateProvider
{
44 * Version number of this state provider. Please bump this if you modify the
45 * contents of the generated state history in some way.
47 private static final int VERSION
= 4;
49 /* Event names HashMap. TODO: This can be discarded once we move to Java 7 */
50 private final HashMap
<String
, Integer
> knownEventNames
;
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
57 * Instantiate a new state provider plugin.
60 * The LTTng 2.0 kernel trace directory
62 public LttngKernelStateProvider(CtfTmfTrace trace
) {
63 super(trace
, CtfTmfEvent
.class, "LTTng Kernel"); //$NON-NLS-1$
64 knownEventNames
= fillEventNames();
67 // ------------------------------------------------------------------------
69 // ------------------------------------------------------------------------
72 public int getVersion() {
77 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb
) {
78 /* We can only set up the locations once the state system is assigned */
79 super.assignTargetStateSystem(ssb
);
83 public LttngKernelStateProvider
getNewInstance() {
84 return new LttngKernelStateProvider((CtfTmfTrace
) this.getTrace());
88 protected void eventHandle(ITmfEvent ev
) {
90 * AbstractStateChangeInput should have already checked for the correct
93 CtfTmfEvent event
= (CtfTmfEvent
) ev
;
98 final ITmfEventField content
= event
.getContent();
99 final String eventName
= event
.getType().getName();
100 final long ts
= event
.getTimestamp().getValue();
103 /* Shortcut for the "current CPU" attribute node */
104 final Integer currentCPUNode
= ss
.getQuarkRelativeAndAdd(getNodeCPUs(), String
.valueOf(event
.getCPU()));
107 * Shortcut for the "current thread" attribute node. It requires
108 * querying the current CPU's current thread.
110 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.CURRENT_THREAD
);
111 value
= ss
.queryOngoingState(quark
);
112 int thread
= value
.isNull() ?
-1 : value
.unboxInt();
113 final Integer currentThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), String
.valueOf(thread
));
116 * Feed event to the history system if it's known to cause a state
119 switch (getEventIndex(eventName
)) {
121 case 1: // "exit_syscall":
122 /* Fields: int64 ret */
124 /* Clear the current system call on the process */
125 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
126 value
= TmfStateValue
.nullValue();
127 ss
.modifyAttribute(ts
, value
, quark
);
129 /* Put the process' status back to user mode */
130 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
131 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
132 ss
.modifyAttribute(ts
, value
, quark
);
134 /* Put the CPU's status back to user mode */
135 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
136 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
137 ss
.modifyAttribute(ts
, value
, quark
);
141 case 2: // "irq_handler_entry":
142 /* Fields: int32 irq, string name */
144 Integer irqId
= ((Long
) content
.getField(LttngStrings
.IRQ
).getValue()).intValue();
146 /* Mark this IRQ as active in the resource tree.
147 * The state value = the CPU on which this IRQ is sitting */
148 quark
= ss
.getQuarkRelativeAndAdd(getNodeIRQs(), irqId
.toString());
149 value
= TmfStateValue
.newValueInt(event
.getCPU());
150 ss
.modifyAttribute(ts
, value
, quark
);
152 /* Change the status of the running process to interrupted */
153 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
154 value
= StateValues
.PROCESS_STATUS_INTERRUPTED_VALUE
;
155 ss
.modifyAttribute(ts
, value
, quark
);
157 /* Change the status of the CPU to interrupted */
158 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
159 value
= StateValues
.CPU_STATUS_IRQ_VALUE
;
160 ss
.modifyAttribute(ts
, value
, quark
);
164 case 3: // "irq_handler_exit":
165 /* Fields: int32 irq, int32 ret */
167 Integer irqId
= ((Long
) content
.getField(LttngStrings
.IRQ
).getValue()).intValue();
169 /* Put this IRQ back to inactive in the resource tree */
170 quark
= ss
.getQuarkRelativeAndAdd(getNodeIRQs(), irqId
.toString());
171 value
= TmfStateValue
.nullValue();
172 ss
.modifyAttribute(ts
, value
, quark
);
174 /* Set the previous process back to running */
175 setProcessToRunning(ts
, currentThreadNode
);
177 /* Set the CPU status back to running or "idle" */
178 cpuExitInterrupt(ts
, currentCPUNode
, currentThreadNode
);
182 case 4: // "softirq_entry":
183 /* Fields: int32 vec */
185 Integer softIrqId
= ((Long
) content
.getField(LttngStrings
.VEC
).getValue()).intValue();
187 /* Mark this SoftIRQ as active in the resource tree.
188 * The state value = the CPU on which this SoftIRQ is processed */
189 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId
.toString());
190 value
= TmfStateValue
.newValueInt(event
.getCPU());
191 ss
.modifyAttribute(ts
, value
, quark
);
193 /* Change the status of the running process to interrupted */
194 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
195 value
= StateValues
.PROCESS_STATUS_INTERRUPTED_VALUE
;
196 ss
.modifyAttribute(ts
, value
, quark
);
198 /* Change the status of the CPU to interrupted */
199 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
200 value
= StateValues
.CPU_STATUS_SOFTIRQ_VALUE
;
201 ss
.modifyAttribute(ts
, value
, quark
);
205 case 5: // "softirq_exit":
206 /* Fields: int32 vec */
208 Integer softIrqId
= ((Long
) content
.getField(LttngStrings
.VEC
).getValue()).intValue();
210 /* Put this SoftIRQ back to inactive (= -1) in the resource tree */
211 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId
.toString());
212 value
= TmfStateValue
.nullValue();
213 ss
.modifyAttribute(ts
, value
, quark
);
215 /* Set the previous process back to running */
216 setProcessToRunning(ts
, currentThreadNode
);
218 /* Set the CPU status back to "busy" or "idle" */
219 cpuExitInterrupt(ts
, currentCPUNode
, currentThreadNode
);
223 case 6: // "softirq_raise":
224 /* Fields: int32 vec */
226 Integer softIrqId
= ((Long
) content
.getField(LttngStrings
.VEC
).getValue()).intValue();
228 /* Mark this SoftIRQ as *raised* in the resource tree.
229 * State value = -2 */
230 quark
= ss
.getQuarkRelativeAndAdd(getNodeSoftIRQs(), softIrqId
.toString());
231 value
= StateValues
.SOFT_IRQ_RAISED_VALUE
;
232 ss
.modifyAttribute(ts
, value
, quark
);
236 case 7: // "sched_switch":
238 * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64 prev_state,
239 * string next_comm, int32 next_tid, int32 next_prio
242 Integer prevTid
= ((Long
) content
.getField(LttngStrings
.PREV_TID
).getValue()).intValue();
243 Long prevState
= (Long
) content
.getField(LttngStrings
.PREV_STATE
).getValue();
244 String nextProcessName
= (String
) content
.getField(LttngStrings
.NEXT_COMM
).getValue();
245 Integer nextTid
= ((Long
) content
.getField(LttngStrings
.NEXT_TID
).getValue()).intValue();
247 Integer formerThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), prevTid
.toString());
248 Integer newCurrentThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), nextTid
.toString());
250 /* Set the status of the process that got scheduled out. */
251 quark
= ss
.getQuarkRelativeAndAdd(formerThreadNode
, Attributes
.STATUS
);
252 if (prevState
!= 0) {
253 value
= StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
;
255 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
257 ss
.modifyAttribute(ts
, value
, quark
);
259 /* Set the status of the new scheduled process */
260 setProcessToRunning(ts
, newCurrentThreadNode
);
262 /* Set the exec name of the new process */
263 quark
= ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.EXEC_NAME
);
264 value
= TmfStateValue
.newValueString(nextProcessName
);
265 ss
.modifyAttribute(ts
, value
, quark
);
267 /* Make sure the PPID and system_call sub-attributes exist */
268 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.SYSTEM_CALL
);
269 ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.PPID
);
271 /* Set the current scheduled process on the relevant CPU */
272 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.CURRENT_THREAD
);
273 value
= TmfStateValue
.newValueInt(nextTid
);
274 ss
.modifyAttribute(ts
, value
, quark
);
276 /* Set the status of the CPU itself */
278 /* Check if the entering process is in kernel or user mode */
279 quark
= ss
.getQuarkRelativeAndAdd(newCurrentThreadNode
, Attributes
.SYSTEM_CALL
);
280 if (ss
.queryOngoingState(quark
).isNull()) {
281 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
283 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
286 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
288 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
289 ss
.modifyAttribute(ts
, value
, quark
);
293 case 8: // "sched_process_fork":
294 /* Fields: string parent_comm, int32 parent_tid,
295 * string child_comm, int32 child_tid */
297 // String parentProcessName = (String) event.getFieldValue("parent_comm");
298 String childProcessName
= (String
) content
.getField(LttngStrings
.CHILD_COMM
).getValue();
299 // assert ( parentProcessName.equals(childProcessName) );
301 Integer parentTid
= ((Long
) content
.getField(LttngStrings
.PARENT_TID
).getValue()).intValue();
302 Integer childTid
= ((Long
) content
.getField(LttngStrings
.CHILD_TID
).getValue()).intValue();
304 Integer parentTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), parentTid
.toString());
305 Integer childTidNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), childTid
.toString());
307 /* Assign the PPID to the new process */
308 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.PPID
);
309 value
= TmfStateValue
.newValueInt(parentTid
);
310 ss
.modifyAttribute(ts
, value
, quark
);
312 /* Set the new process' exec_name */
313 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.EXEC_NAME
);
314 value
= TmfStateValue
.newValueString(childProcessName
);
315 ss
.modifyAttribute(ts
, value
, quark
);
317 /* Set the new process' status */
318 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.STATUS
);
319 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
320 ss
.modifyAttribute(ts
, value
, quark
);
322 /* Set the process' syscall name, to be the same as the parent's */
323 quark
= ss
.getQuarkRelativeAndAdd(parentTidNode
, Attributes
.SYSTEM_CALL
);
324 value
= ss
.queryOngoingState(quark
);
325 if (value
.isNull()) {
327 * Maybe we were missing info about the parent? At least we
328 * will set the child right. Let's suppose "sys_clone".
330 value
= TmfStateValue
.newValueString(LttngStrings
.SYS_CLONE
);
332 quark
= ss
.getQuarkRelativeAndAdd(childTidNode
, Attributes
.SYSTEM_CALL
);
333 ss
.modifyAttribute(ts
, value
, quark
);
337 case 9: // "sched_process_exit":
338 /* Fields: string comm, int32 tid, int32 prio */
341 case 10: // "sched_process_free":
342 /* Fields: string comm, int32 tid, int32 prio */
344 * A sched_process_free will always happen after the sched_switch
345 * that will remove the process from the cpu for the last time. So
346 * this is when we should delete everything wrt to the process.
349 Integer tid
= ((Long
) content
.getField(LttngStrings
.TID
).getValue()).intValue();
351 * Remove the process and all its sub-attributes from the
354 quark
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), tid
.toString());
355 ss
.removeAttribute(ts
, quark
);
359 case 11: // "lttng_statedump_process_state":
361 * int32 type, int32 mode, int32 pid, int32 submode, int32 vpid,
362 * int32 ppid, int32 tid, string name, int32 status, int32 vtid */
364 int tid
= ((Long
) content
.getField(LttngStrings
.TID
).getValue()).intValue();
365 int pid
= ((Long
) content
.getField(LttngStrings
.PID
).getValue()).intValue();
366 int ppid
= ((Long
) content
.getField(LttngStrings
.PPID
).getValue()).intValue();
367 int status
= ((Long
) content
.getField(LttngStrings
.STATUS
).getValue()).intValue();
368 String name
= (String
) content
.getField(LttngStrings
.NAME
).getValue();
370 * "mode" could be interesting too, but it doesn't seem to be
371 * populated with anything relevant for now.
374 int curThreadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), String
.valueOf(tid
));
376 /* Set the process' name */
377 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.EXEC_NAME
);
378 if (ss
.queryOngoingState(quark
).isNull()) {
379 /* If the value didn't exist previously, set it */
380 value
= TmfStateValue
.newValueString(name
);
381 ss
.modifyAttribute(ts
, value
, quark
);
384 /* Set the process' PPID */
385 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.PPID
);
386 if (ss
.queryOngoingState(quark
).isNull()) {
388 /* We have a process. Use the 'PPID' field. */
389 value
= TmfStateValue
.newValueInt(ppid
);
391 /* We have a thread, use the 'PID' field for the parent. */
392 value
= TmfStateValue
.newValueInt(pid
);
394 ss
.modifyAttribute(ts
, value
, quark
);
397 /* Set the process' status */
398 quark
= ss
.getQuarkRelativeAndAdd(curThreadNode
, Attributes
.STATUS
);
399 if (ss
.queryOngoingState(quark
).isNull()) {
400 /* "2" here means "WAIT_FOR_CPU", and "5" "WAIT_BLOCKED" in the LTTng kernel. */
402 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
403 } else if (status
== 5) {
404 value
= StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
;
406 value
= StateValues
.PROCESS_STATUS_UNKNOWN_VALUE
;
408 ss
.modifyAttribute(ts
, value
, quark
);
413 case 12: // "sched_wakeup":
414 case 13: // "sched_wakeup_new":
415 /* Fields (same fields for both types):
416 * string comm, int32 pid, int32 prio, int32 success,
417 * int32 target_cpu */
419 final int tid
= ((Long
) content
.getField(LttngStrings
.TID
).getValue()).intValue();
420 final int threadNode
= ss
.getQuarkRelativeAndAdd(getNodeThreads(), String
.valueOf(tid
));
423 * The process indicated in the event's payload is now ready to
424 * run. Assign it to the "wait for cpu" state, but only if it
425 * was not already running.
427 quark
= ss
.getQuarkRelativeAndAdd(threadNode
, Attributes
.STATUS
);
428 int status
= ss
.queryOngoingState(quark
).unboxInt();
430 if (status
!= StateValues
.PROCESS_STATUS_RUN_SYSCALL
&&
431 status
!= StateValues
.PROCESS_STATUS_RUN_USERMODE
) {
432 value
= StateValues
.PROCESS_STATUS_WAIT_FOR_CPU_VALUE
;
433 ss
.modifyAttribute(ts
, value
, quark
);
439 /* Other event types not covered by the main switch */
441 if (eventName
.startsWith(LttngStrings
.SYSCALL_PREFIX
)
442 || eventName
.startsWith(LttngStrings
.COMPAT_SYSCALL_PREFIX
)) {
444 * This is a replacement for the old sys_enter event. Now
445 * syscall names are listed into the event type
448 /* Assign the new system call to the process */
449 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
450 value
= TmfStateValue
.newValueString(eventName
);
451 ss
.modifyAttribute(ts
, value
, quark
);
453 /* Put the process in system call mode */
454 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
455 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
456 ss
.modifyAttribute(ts
, value
, quark
);
458 /* Put the CPU in system call (kernel) mode */
459 quark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, Attributes
.STATUS
);
460 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
461 ss
.modifyAttribute(ts
, value
, quark
);
465 } // End of big switch
467 } catch (AttributeNotFoundException ae
) {
469 * This would indicate a problem with the logic of the manager here,
470 * so it shouldn't happen.
472 ae
.printStackTrace();
474 } catch (TimeRangeException tre
) {
476 * This would happen if the events in the trace aren't ordered
477 * chronologically, which should never be the case ...
479 System
.err
.println("TimeRangeExcpetion caught in the state system's event manager."); //$NON-NLS-1$
480 System
.err
.println("Are the events in the trace correctly ordered?"); //$NON-NLS-1$
481 tre
.printStackTrace();
483 } catch (StateValueTypeException sve
) {
485 * This would happen if we were trying to push/pop attributes not of
486 * type integer. Which, once again, should never happen.
488 sve
.printStackTrace();
492 // ------------------------------------------------------------------------
493 // Convenience methods for commonly-used attribute tree locations
494 // ------------------------------------------------------------------------
496 private int getNodeCPUs() {
497 return ss
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);
500 private int getNodeThreads() {
501 return ss
.getQuarkAbsoluteAndAdd(Attributes
.THREADS
);
504 private int getNodeIRQs() {
505 return ss
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.IRQS
);
508 private int getNodeSoftIRQs() {
509 return ss
.getQuarkAbsoluteAndAdd(Attributes
.RESOURCES
, Attributes
.SOFT_IRQS
);
512 // ------------------------------------------------------------------------
513 // Workaround for the lack of switch-on-strings in Java < 7
514 // ------------------------------------------------------------------------
516 private static HashMap
<String
, Integer
> fillEventNames() {
518 * TODO Replace with straight strings in the switch/case once we move to
521 HashMap
<String
, Integer
> map
= new HashMap
<>();
523 map
.put(LttngStrings
.EXIT_SYSCALL
, 1);
524 map
.put(LttngStrings
.IRQ_HANDLER_ENTRY
, 2);
525 map
.put(LttngStrings
.IRQ_HANDLER_EXIT
, 3);
526 map
.put(LttngStrings
.SOFTIRQ_ENTRY
, 4);
527 map
.put(LttngStrings
.SOFTIRQ_EXIT
, 5);
528 map
.put(LttngStrings
.SOFTIRQ_RAISE
, 6);
529 map
.put(LttngStrings
.SCHED_SWITCH
, 7);
530 map
.put(LttngStrings
.SCHED_PROCESS_FORK
, 8);
531 map
.put(LttngStrings
.SCHED_PROCESS_EXIT
, 9);
532 map
.put(LttngStrings
.SCHED_PROCESS_FREE
, 10);
533 map
.put(LttngStrings
.STATEDUMP_PROCESS_STATE
, 11);
534 map
.put(LttngStrings
.SCHED_WAKEUP
, 12);
535 map
.put(LttngStrings
.SCHED_WAKEUP_NEW
, 13);
540 private int getEventIndex(String eventName
) {
541 Integer ret
= knownEventNames
.get(eventName
);
542 return (ret
!= null) ? ret
: -1;
545 // ------------------------------------------------------------------------
546 // Advanced state-setting methods
547 // ------------------------------------------------------------------------
550 * When we want to set a process back to a "running" state, first check
551 * its current System_call attribute. If there is a system call active, we
552 * put the process back in the syscall state. If not, we put it back in
555 private void setProcessToRunning(long ts
, int currentThreadNode
)
556 throws AttributeNotFoundException
, TimeRangeException
,
557 StateValueTypeException
{
559 ITmfStateValue value
;
561 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.SYSTEM_CALL
);
562 if (ss
.queryOngoingState(quark
).isNull()) {
563 /* We were in user mode before the interruption */
564 value
= StateValues
.PROCESS_STATUS_RUN_USERMODE_VALUE
;
566 /* We were previously in kernel mode */
567 value
= StateValues
.PROCESS_STATUS_RUN_SYSCALL_VALUE
;
569 quark
= ss
.getQuarkRelativeAndAdd(currentThreadNode
, Attributes
.STATUS
);
570 ss
.modifyAttribute(ts
, value
, quark
);
574 * Similar logic as above, but to set the CPU's status when it's coming out
575 * of an interruption.
577 private void cpuExitInterrupt(long ts
, int currentCpuNode
, int currentThreadNode
)
578 throws StateValueTypeException
, AttributeNotFoundException
,
581 ITmfStateValue value
;
583 quark
= ss
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.CURRENT_THREAD
);
584 if (ss
.queryOngoingState(quark
).unboxInt() > 0) {
585 /* There was a process on the CPU */
586 quark
= ss
.getQuarkRelative(currentThreadNode
, Attributes
.SYSTEM_CALL
);
587 if (ss
.queryOngoingState(quark
).isNull()) {
588 /* That process was in user mode */
589 value
= StateValues
.CPU_STATUS_RUN_USERMODE_VALUE
;
591 /* That process was in a system call */
592 value
= StateValues
.CPU_STATUS_RUN_SYSCALL_VALUE
;
595 /* There was no real process scheduled, CPU was idle */
596 value
= StateValues
.CPU_STATUS_IDLE_VALUE
;
598 quark
= ss
.getQuarkRelativeAndAdd(currentCpuNode
, Attributes
.STATUS
);
599 ss
.modifyAttribute(ts
, value
, quark
);