/* Misc stuff */
String UNKNOWN = "Unknown";
+ String THREAD_0_PREFIX = "0_";
+ String THREAD_0_SEPARATOR = "_";
}
* Version number of this state provider. Please bump this if you modify the
* contents of the generated state history in some way.
*/
- private static final int VERSION = 15;
+ private static final int VERSION = 16;
// ------------------------------------------------------------------------
// Fields
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
/**
* Kernel Event Handler Utils is a collection of static methods to be used in
int quark = ss.getQuarkRelativeAndAdd(getCurrentCPUNode(cpuNumber, ss), Attributes.CURRENT_THREAD);
ITmfStateValue value = ss.queryOngoingState(quark);
int thread = value.isNull() ? -1 : value.unboxInt();
- return ss.getQuarkRelativeAndAdd(getNodeThreads(ss), String.valueOf(thread));
+ return ss.getQuarkRelativeAndAdd(getNodeThreads(ss), buildThreadAttributeName(thread, cpuNumber));
}
/**
StateValues.CPU_STATUS_RUN_SYSCALL_VALUE);
}
+ /**
+ * Build the thread attribute name.
+ *
+ * For all threads except "0" this is the string representation of the threadId.
+ * For thread "0" which is the idle thread and can be running concurrently on multiple
+ * CPUs, append "_cpuId".
+ *
+ * @param threadId
+ * the thread id
+ * @param cpuId
+ * the cpu id
+ *
+ * @return the thread attribute name
+ * null if the threadId is zero and the cpuId is null
+ */
+ public static @Nullable String buildThreadAttributeName(int threadId, @Nullable Integer cpuId) {
+
+ if (threadId == 0) {
+ if (cpuId == null) {
+ return null;
+ }
+ return Attributes.THREAD_0_PREFIX + String.valueOf(cpuId);
+ }
+
+ return String.valueOf(threadId);
+ }
+
+ /**
+ * Parse the thread id and CPU id from the thread attribute name string
+ *
+ * For thread "0" the attribute name is in the form "threadId_cpuId", extract both
+ * values from the string.
+ *
+ * For all other threads, the attribute name is the string representation of the
+ * threadId and there is no cpuId.
+ *
+ * @param threadAttributeName
+ * the thread attribute name
+ * @return the thread id and cpu id
+ */
+ public static Pair<Integer, Integer> parseThreadAttributeName(String threadAttributeName) {
+ Integer threadId = -1;
+ Integer cpuId = -1;
+
+ try {
+ if (threadAttributeName.startsWith(Attributes.THREAD_0_PREFIX)) {
+ threadId = 0;
+ String[] tokens = threadAttributeName.split(Attributes.THREAD_0_SEPARATOR);
+ cpuId = Integer.parseInt(tokens[1]);
+ } else {
+ threadId = Integer.parseInt(threadAttributeName);
+ }
+ } catch (NumberFormatException e1) {
+ //pass
+ }
+
+ return new Pair<>(threadId, cpuId);
+ }
}
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
ITmfEventField content = event.getContent();
+ Integer cpu = KernelEventHandlerUtils.getCpu(event);
Integer tid = ((Long) content.getField(getLayout().fieldTid()).getValue()).intValue();
Integer prio = ((Long) content.getField(getLayout().fieldNewPrio()).getValue()).intValue();
- Integer updateThreadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), tid.toString());
+ String threadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(tid, cpu);
+ if (threadAttributeName == null) {
+ return;
+ }
+
+ Integer updateThreadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), threadAttributeName);
/* Set the current prio for the new process */
int quark = ss.getQuarkRelativeAndAdd(updateThreadNode, Attributes.PRIO);
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
ITmfEventField content = event.getContent();
+ Integer cpu = KernelEventHandlerUtils.getCpu(event);
String childProcessName = (String) content.getField(getLayout().fieldChildComm()).getValue();
Integer parentTid = ((Long) content.getField(getLayout().fieldParentTid()).getValue()).intValue();
Integer childTid = ((Long) content.getField(getLayout().fieldChildTid()).getValue()).intValue();
+ String parentThreadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(parentTid, cpu);
+ if (parentThreadAttributeName == null) {
+ return;
+ }
+
+ String childThreadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(childTid, cpu);
+ if (childThreadAttributeName == null) {
+ return;
+ }
+
final int threadsNode = KernelEventHandlerUtils.getNodeThreads(ss);
- Integer parentTidNode = ss.getQuarkRelativeAndAdd(threadsNode, parentTid.toString());
- Integer childTidNode = ss.getQuarkRelativeAndAdd(threadsNode, childTid.toString());
+ Integer parentTidNode = ss.getQuarkRelativeAndAdd(threadsNode, parentThreadAttributeName);
+ Integer childTidNode = ss.getQuarkRelativeAndAdd(threadsNode, childThreadAttributeName);
+
/* Assign the PPID to the new process */
int quark = ss.getQuarkRelativeAndAdd(childTidNode, Attributes.PPID);
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+ Integer cpu = KernelEventHandlerUtils.getCpu(event);
Integer tid = ((Long) event.getContent().getField(getLayout().fieldTid()).getValue()).intValue();
+
+ String threadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(tid, cpu);
+ if (threadAttributeName == null) {
+ return;
+ }
+
/*
* Remove the process and all its sub-attributes from the current state
*/
- int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), tid.toString());
+ int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), threadAttributeName);
ss.removeAttribute(KernelEventHandlerUtils.getTimestamp(event), quark);
}
}
Integer nextTid = ((Long) content.getField(getLayout().fieldNextTid()).getValue()).intValue();
Integer nextPrio = ((Long) content.getField(getLayout().fieldNextPrio()).getValue()).intValue();
+ /* Will never return null since "cpu" is null checked */
+ String formerThreadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(prevTid, cpu);
+ String currenThreadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(nextTid, cpu);
+
int nodeThreads = KernelEventHandlerUtils.getNodeThreads(ss);
- int formerThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, prevTid.toString());
- int newCurrentThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, nextTid.toString());
+ int formerThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, formerThreadAttributeName);
+ int newCurrentThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, currenThreadAttributeName);
long timestamp = KernelEventHandlerUtils.getTimestamp(event);
/* Set the status of the process that got scheduled out. */
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+ Integer cpu = KernelEventHandlerUtils.getCpu(event);
final int tid = ((Long) event.getContent().getField(getLayout().fieldTid()).getValue()).intValue();
final int prio = ((Long) event.getContent().getField(getLayout().fieldPrio()).getValue()).intValue();
- final int threadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), String.valueOf(tid));
+
+ String threadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(tid, cpu);
+ if (threadAttributeName == null) {
+ return;
+ }
+
+ final int threadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), threadAttributeName);
/*
* The process indicated in the event's payload is now ready to run.
@Override
public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
ITmfEventField content = event.getContent();
+ Integer cpu = KernelEventHandlerUtils.getCpu(event);
int tid = ((Long) content.getField("tid").getValue()).intValue(); //$NON-NLS-1$
int pid = ((Long) content.getField("pid").getValue()).intValue(); //$NON-NLS-1$
int ppid = ((Long) content.getField("ppid").getValue()).intValue(); //$NON-NLS-1$
* with anything relevant for now.
*/
- int curThreadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), String.valueOf(tid));
+ String threadAttributeName = KernelEventHandlerUtils.buildThreadAttributeName(tid, cpu);
+ if (threadAttributeName == null) {
+ return;
+ }
+
+ int curThreadNode = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeThreads(ss), threadAttributeName);
long timestamp = KernelEventHandlerUtils.getTimestamp(event);
/* Set the process' name */
setProcessName(ss, name, curThreadNode, timestamp);
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.Attributes;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandlerUtils;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowThreadAction;
import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
}
final List<ControlFlowEntry> entryList = new ArrayList<>();
- final Map<Integer, ControlFlowEntry> entryMap = new HashMap<>();
+ /** Map of view entries, key is a pair [threadId, cpuId] */
+ final Map<Pair<Integer, Integer>, ControlFlowEntry> entryMap = new HashMap<>();
long start = ssq.getStartTime();
setStartTime(Math.min(getStartTime(), start));
@Override
public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
for (int threadQuark : threadQuarks) {
- String threadName = ssq.getAttributeName(threadQuark);
- int threadId = -1;
- try {
- threadId = Integer.parseInt(threadName);
- } catch (NumberFormatException e1) {
- continue;
- }
- if (threadId <= 0) { // ignore the 'unknown' (-1) and swapper (0) threads
+ String threadAttributeName = ssq.getAttributeName(threadQuark);
+
+ Pair<Integer, Integer> entryKey = KernelEventHandlerUtils.parseThreadAttributeName(threadAttributeName);
+ int threadId = entryKey.getFirst();
+
+ if (threadId < 0) { // ignore the 'unknown' (-1) thread
continue;
}
execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
String execName = execNameInterval.getStateValue().unboxStr();
int ppid = ppidInterval.getStateValue().unboxInt();
- ControlFlowEntry entry = entryMap.get(threadId);
+ ControlFlowEntry entry = entryMap.get(entryKey);
if (entry == null) {
entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
entryList.add(entry);
- entryMap.put(threadId, entry);
+ entryMap.put(entryKey, entry);
} else {
/*
* Update the name of the entry to the
}
}
if (isNull) {
- entryMap.remove(threadId);
+ entryMap.remove(entryKey);
}
lastExecNameStartTime = startTime;
lastExecNameEndTime = endTime;
List<Integer> list = fixture.getQuarks(Attributes.THREADS, "*", Attributes.EXEC_NAME);
/* Number of different kernel threads in the trace */
- assertEquals(168, list.size());
+ assertEquals(169, list.size());
}
@Test
*/
interface TestValues {
- int size = 1034;
+ int size = 1040;
long[] startTimes = {
1331668247314038062L,
1331668247314038062L,
1331668247314038062L,
1331668247314038062L,
- 1331668248013353414L,
- 1331668248004935409L,
+ 1331668248014145796L,
1331668247314601653L,
+ 1331668247314601653L,
+ 1331668247314038062L,
1331668247314038062L,
+ 1331668248013353414L,
1331668247314038062L,
1331668248014184526L,
1331668248014130616L,
1331668247316925661L,
1331668247314038062L,
1331668247314038062L,
+ 1331668247317063795L,
+ 1331668247317063795L,
+ 1331668247314038062L,
+ 1331668247314038062L,
1331668247999256178L,
1331668247999239403L,
1331668247999250697L,
1331668259054285979L,
1331668259054285979L,
1331668248014620024L,
- 1331668248014620024L,
1331668259054285979L,
1331668259054285979L,
1331668259054285979L,
+ 1331668259054285979L,
+ 1331668248015333196L,
+ 1331668259054285979L,
1331668248014548923L,
1331668248014188534L,
1331668259054285979L,
1331668259054285979L,
1331668259054285979L,
1331668259054285979L,
+ 1331668259054285979L,
+ 1331668259054285979L,
+ 1331668259054285979L,
+ 1331668259054285979L,
1331668248016556933L,
1331668248016556933L,
1331668248016592456L,
TmfStateValue.nullValue(),
TmfStateValue.nullValue(),
TmfStateValue.newValueInt(5),
- TmfStateValue.newValueString("swapper/1"),
+ TmfStateValue.newValueString("swapper/0"),
TmfStateValue.newValueInt(20),
TmfStateValue.nullValue(),
TmfStateValue.nullValue(),
+ TmfStateValue.newValueInt(5),
+ TmfStateValue.nullValue(),
TmfStateValue.newValueInt(1432),
TmfStateValue.newValueInt(4),
TmfStateValue.nullValue(),
TmfStateValue.newValueString("lttng-sessiond"),
TmfStateValue.nullValue(),
TmfStateValue.nullValue(),
+ TmfStateValue.newValueString("swapper/1"),
+ TmfStateValue.newValueInt(20),
+ TmfStateValue.nullValue(),
+ TmfStateValue.nullValue(),
TmfStateValue.newValueInt(1),
TmfStateValue.newValueInt(20),
TmfStateValue.newValueString("sys_futex"),
TmfStateValue.nullValue(),
TmfStateValue.nullValue(),
};
-}
\ No newline at end of file
+}
TreeCheckedCounter treeCheckCounter = new TreeCheckedCounter(treeBot);
// get how many items there are
Integer checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals("default", 200, checked.intValue());
+ assertEquals("default", 225, checked.intValue());
// test "uncheck all button"
bot.button(UNCHECK_ALL).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
// test check active
bot.button(CHECK_ACTIVE).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals(CHECK_ACTIVE, 43, checked.intValue());
+ assertEquals(CHECK_ACTIVE, 68, checked.intValue());
// test check all
bot.button(CHECK_ALL).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals(CHECK_ALL, 200, checked.intValue());
+ assertEquals(CHECK_ALL, 225, checked.intValue());
// test uncheck inactive
bot.button(UNCHECK_INACTIVE).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals(UNCHECK_INACTIVE, 43, checked.intValue());
+ assertEquals(UNCHECK_INACTIVE, 68, checked.intValue());
// test check selected
treeBot.select(1);
bot.button(UNCHECK_ALL).click();
bot.button(CHECK_ALL).click();
bot.button(UNCHECK_SELECTED).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals(UNCHECK_SELECTED, 199, checked.intValue());
+ assertEquals(UNCHECK_SELECTED, 224, checked.intValue());
// test uncheck subtree
bot.button(CHECK_ALL).click();
bot.button(UNCHECK_SUBTREE).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);
- assertEquals(UNCHECK_SELECTED, 199, checked.intValue());
+ assertEquals(UNCHECK_SELECTED, 224, checked.intValue());
// test filter
bot.button(UNCHECK_ALL).click();
checked = UIThreadRunnable.syncExec(treeCheckCounter);