* Copyright (c) 2012 Ericsson
* Copyright (c) 2010, 2011 École Polytechnique de Montréal
* Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
- *
+ *
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
+ *
*******************************************************************************/
package org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.concurrent.BlockingQueue;
import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.LttngStrings;
import org.eclipse.linuxtools.internal.lttng2.kernel.core.StateValues;
-import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngStrings;
import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
/**
* This is the reference "state provider" for LTTng 2.0 kernel traces.
- *
+ *
* @author alexmont
- *
+ *
*/
class CtfKernelHandler implements Runnable {
private CtfTmfEvent currentEvent;
- /*
- * We can keep handles to some Attribute Nodes so these don't need to be
- * re-found (re-hashed Strings etc.) every new event
- */
- List<Integer> currentCPUNodes;
- List<Integer> currentThreadNodes;
-
/* Event names HashMap. TODO: This can be discarded once we move to Java 7 */
private final HashMap<String, Integer> knownEventNames;
CtfKernelHandler(BlockingQueue<CtfTmfEvent> eventsQueue) {
assert (eventsQueue != null);
this.inQueue = eventsQueue;
- currentCPUNodes = new ArrayList<Integer>();
- currentThreadNodes = new ArrayList<Integer>();
knownEventNames = fillEventNames();
}
}
private void processEvent(CtfTmfEvent event) {
- currentEvent = event;
- ITmfEventField content = event.getContent();
- String eventName = event.getEventName();
-
- long ts = event.getTimestamp().getValue();
int quark;
ITmfStateValue value;
- Integer eventCpu = event.getCPU();
- Integer currentCPUNode, currentThreadNode, tidNode;
-
- /* Adjust the current nodes Vectors if we see a new CPU in an event */
- if (eventCpu >= currentCPUNodes.size()) {
- /* We need to add this node to the vector */
- for (Integer i = currentCPUNodes.size(); i < eventCpu + 1; i++) {
- quark = ss.getQuarkRelativeAndAdd(cpusNode, i.toString());
- currentCPUNodes.add(quark);
-
- quark = ss.getQuarkRelativeAndAdd(threadsNode, Attributes.UNKNOWN);
- currentThreadNodes.add(quark);
- }
- }
- currentCPUNode = currentCPUNodes.get(eventCpu);
- currentThreadNode = currentThreadNodes.get(eventCpu);
- assert (currentCPUNode != null);
- assert (currentThreadNode != null);
+ currentEvent = event;
+
+ final ITmfEventField content = event.getContent();
+ final String eventName = event.getEventName();
+ final long ts = event.getTimestamp().getValue();
try {
+ /* Shortcut for the "current CPU" attribute node */
+ final Integer currentCPUNode = ss.getQuarkRelativeAndAdd(cpusNode, String.valueOf(event.getCPU()));
+
+ /*
+ * Shortcut for the "current thread" attribute node. It requires
+ * querying the current CPU's current thread.
+ */
+ quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
+ value = ss.queryOngoingState(quark);
+ int thread = value.unboxInt();
+ final Integer currentThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, String.valueOf(thread));
+
/*
* Feed event to the history system if it's known to cause a state
* transition.
quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_INTERRUPTED);
ss.modifyAttribute(ts, value, quark);
-\r
- /* Change the status of the CPU to interrupted */\r
- quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);\r
- value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IRQ);\r
- ss.modifyAttribute(ts, value, quark);\r
+
+ /* Change the status of the CPU to interrupted */
+ quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
+ value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IRQ);
+ ss.modifyAttribute(ts, value, quark);
}
break;
/* Set the previous process back to running */
setProcessToRunning(ts, currentThreadNode);
-\r
- /* Set the CPU status back to running or "idle" */\r
- cpuExitInterrupt(ts, currentCPUNode, currentThreadNode);\r
+
+ /* Set the CPU status back to running or "idle" */
+ cpuExitInterrupt(ts, currentCPUNode, currentThreadNode);
}
break;
quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_INTERRUPTED);
ss.modifyAttribute(ts, value, quark);
-\r
- /* Change the status of the CPU to interrupted */\r
- quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);\r
- value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_SOFTIRQ);\r
- ss.modifyAttribute(ts, value, quark);\r
+
+ /* Change the status of the CPU to interrupted */
+ quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
+ value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_SOFTIRQ);
+ ss.modifyAttribute(ts, value, quark);
}
break;
/* Set the previous process back to running */
setProcessToRunning(ts, currentThreadNode);
-\r
- /* Set the CPU status back to "busy" or "idle" */\r
- cpuExitInterrupt(ts, currentCPUNode, currentThreadNode);\r
+
+ /* Set the CPU status back to "busy" or "idle" */
+ cpuExitInterrupt(ts, currentCPUNode, currentThreadNode);
}
break;
Integer formerThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, prevTid.toString());
Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, nextTid.toString());
- /* Update the currentThreadNodes pointer */
- currentThreadNodes.set(eventCpu, newCurrentThreadNode);
-
/* Set the status of the process that got scheduled out. */
quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS);
value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_WAIT);
quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
value = TmfStateValue.newValueInt(nextTid);
ss.modifyAttribute(ts, value, quark);
-\r
+
/* Set the status of the CPU itself */
if (nextTid > 0) {
/* Check if the entering process is in kernel or user mode */
value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_RUN_USERMODE);
} else {
value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_RUN_SYSCALL);
- }\r
- } else {\r
- value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IDLE);\r
+ }
+ } else {
+ value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IDLE);
}
quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
- ss.modifyAttribute(ts, value, quark);\r
+ ss.modifyAttribute(ts, value, quark);
}
break;
Integer parentTid = ((Long) content.getField(LttngStrings.PARENT_TID).getValue()).intValue();
Integer childTid = ((Long) content.getField(LttngStrings.CHILD_TID).getValue()).intValue();
- tidNode = ss.getQuarkRelativeAndAdd(threadsNode, childTid.toString());
+ Integer parentTidNode = ss.getQuarkRelativeAndAdd(threadsNode, parentTid.toString());
+ Integer childTidNode = ss.getQuarkRelativeAndAdd(threadsNode, childTid.toString());
/* Assign the PPID to the new process */
- quark = ss.getQuarkRelativeAndAdd(tidNode, Attributes.PPID);
+ quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.PPID);
value = TmfStateValue.newValueInt(parentTid);
ss.modifyAttribute(ts, value, quark);
/* Set the new process' exec_name */
- quark = ss.getQuarkRelativeAndAdd(tidNode, Attributes.EXEC_NAME);
+ quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.EXEC_NAME);
value = TmfStateValue.newValueString(childProcessName);
ss.modifyAttribute(ts, value, quark);
/* Set the new process' status */
- quark = ss.getQuarkRelativeAndAdd(tidNode, Attributes.STATUS);
+ quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.STATUS);
value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_WAIT);
ss.modifyAttribute(ts, value, quark);
- /* Set the process' syscall state */
- quark = ss.getQuarkRelativeAndAdd(tidNode, Attributes.SYSTEM_CALL);
- value = TmfStateValue.nullValue();
+ /* Set the process' syscall name, to be the same as the parent's */
+ quark = ss.getQuarkRelativeAndAdd(parentTidNode, Attributes.SYSTEM_CALL);
+ value = ss.queryOngoingState(quark);
+ quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.SYSTEM_CALL);
ss.modifyAttribute(ts, value, quark);
}
break;
}
break;
- // FIXME In CTF it's as "syscall_exec". Will have to be adapted.
- // case LTT_EVENT_EXEC:
- // filename = new String((byte[]) event.getField(0));
- //
- // /* Change the Exec_name of the process */
- // quark = ss.getQuarkRelativePath(true, currentThreadNode,
- // "Exec_name");
- // ss.modifyAttribute(ts, filename, quark);
- // break;
+ case 11: // "lttng_statedump_process_state":
+ /* Fields:
+ * int32 type, int32 mode, int32 pid, int32 submode, int32 vpid,
+ * int32 ppid, int32 tid, string name, int32 status, int32 vtid */
+ {
+ Integer tid = ((Long) content.getField(LttngStrings.TID).getValue()).intValue();
+ int ppid = ((Long) content.getField(LttngStrings.PPID).getValue()).intValue();
+ int status = ((Long) content.getField(LttngStrings.STATUS).getValue()).intValue();
+ String name = (String) content.getField(LttngStrings.NAME).getValue();
+ /*
+ * "mode" could be interesting too, but it doesn't seem to be
+ * populated with anything relevant for now.
+ */
+
+ int curThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, tid.toString());
+
+ /* Set the process' name */
+ quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.EXEC_NAME);
+ if (ss.queryOngoingState(quark).isNull()) {
+ /* If the value didn't exist previously, set it */
+ value = TmfStateValue.newValueString(name);
+ ss.modifyAttribute(ts, value, quark);
+ }
+
+ /* Set the process' PPID */
+ quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.PPID);
+ if (ss.queryOngoingState(quark).isNull()) {
+ value = TmfStateValue.newValueInt(ppid);
+ ss.modifyAttribute(ts, value, quark);
+ }
+
+ /* Set the process' status */
+ quark = ss.getQuarkRelativeAndAdd(curThreadNode, Attributes.STATUS);
+ if (ss.queryOngoingState(quark).isNull()) {
+ /*"5" here means "LTTNG_WAIT" in the LTTng kernel tracer */
+ if (status == 5) {
+ value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_WAIT);
+ } else {
+ value = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_UNKNOWN);
+ }
+ ss.modifyAttribute(ts, value, quark);
+ }
+ }
+ break;
default:
/* Other event types not covered by the main switch */
map.put(LttngStrings.SCHED_PROCESS_FORK, 8);
map.put(LttngStrings.SCHED_PROCESS_EXIT, 9);
map.put(LttngStrings.SCHED_PROCESS_FREE, 10);
+ map.put(LttngStrings.STATEDUMP_PROCESS_STATE, 11);
return map;
}
quark = ss.getQuarkRelativeAndAdd(currentThreadNode, Attributes.STATUS);
ss.modifyAttribute(ts, value, quark);
}
-\r
- /**\r
- * Similar logic as above, but to set the CPU's status when it's coming out\r
- * of an interruption.\r
- * @throws AttributeNotFoundException \r
- * @throws StateValueTypeException \r
- * @throws TimeRangeException \r
- */\r
- private void cpuExitInterrupt(long ts, int currentCpuNode, int currentThreadNode)\r
- throws StateValueTypeException, AttributeNotFoundException,\r
- TimeRangeException {\r
- int quark;\r
- ITmfStateValue value;\r
-\r
- quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.CURRENT_THREAD);\r
- if (ss.queryOngoingState(quark).unboxInt() > 0) {\r
+
+ /**
+ * Similar logic as above, but to set the CPU's status when it's coming out
+ * of an interruption.
+ * @throws AttributeNotFoundException
+ * @throws StateValueTypeException
+ * @throws TimeRangeException
+ */
+ private void cpuExitInterrupt(long ts, int currentCpuNode, int currentThreadNode)
+ throws StateValueTypeException, AttributeNotFoundException,
+ TimeRangeException {
+ int quark;
+ ITmfStateValue value;
+
+ quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.CURRENT_THREAD);
+ if (ss.queryOngoingState(quark).unboxInt() > 0) {
/* There was a process on the CPU */
quark = ss.getQuarkRelative(currentThreadNode, Attributes.SYSTEM_CALL);
if (ss.queryOngoingState(quark).isNull()) {
/* That process was in a system call */
value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_RUN_SYSCALL);
}
- } else {\r
- /* There was no real process scheduled, CPU was idle */\r
- value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IDLE);\r
- }\r
- quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.STATUS);\r
- ss.modifyAttribute(ts, value, quark);\r
- }\r
+ } else {
+ /* There was no real process scheduled, CPU was idle */
+ value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IDLE);
+ }
+ quark = ss.getQuarkRelativeAndAdd(currentCpuNode, Attributes.STATUS);
+ ss.modifyAttribute(ts, value, quark);
+ }
}