From af7f72ceaa8980b309082ee8ce73edb6b756bc53 Mon Sep 17 00:00:00 2001 From: Francis Giraldeau Date: Sun, 8 Feb 2015 22:46:04 -0500 Subject: [PATCH] lttng: Add the dependency graph model and handlers for an LTTng kernel trace MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I0ec0ee9e141e13117ef2367059ad709afb74a130 Signed-off-by: Francis Giraldeau Signed-off-by: Geneviève Bastien Signed-off-by: Matthew Khouzam Reviewed-on: https://git.eclipse.org/r/41479 Reviewed-by: Hudson CI --- .../core/kernelanalysis/LinuxValues.java | 3 +- .../kernelanalysis/KernelStateProvider.java | 2 +- .../META-INF/MANIFEST.MF | 6 +- .../plugin.xml | 9 + .../LttngKernelExecGraphProvider.java | 216 +++++++++ .../building/LttngKernelExecutionGraph.java | 62 +++ .../analysis/graph/building/package-info.java | 11 + .../analysis/graph/handlers/BaseHandler.java | 82 ++++ .../graph/handlers/EventContextHandler.java | 110 +++++ .../analysis/graph/handlers/Messages.java | 37 ++ .../TraceEventHandlerExecutionGraph.java | 424 ++++++++++++++++++ .../handlers/TraceEventHandlerSched.java | 199 ++++++++ .../handlers/TraceEventHandlerStatedump.java | 67 +++ .../graph/handlers/messages.properties | 10 + .../analysis/graph/handlers/package-info.java | 11 + .../core/analysis/graph/model/EventField.java | 102 +++++ .../graph/model/LttngInterruptContext.java | 66 +++ .../graph/model/LttngSystemModel.java | 169 +++++++ .../analysis/graph/model/LttngWorker.java | 136 ++++++ .../analysis/graph/model/package-info.java | 11 + tmf/org.eclipse.tracecompass.tmf/feature.xml | 7 + 21 files changed, 1737 insertions(+), 3 deletions(-) rename analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/{internal => }/analysis/os/linux/core/kernelanalysis/LinuxValues.java (98%) create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecGraphProvider.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecutionGraph.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/package-info.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/BaseHandler.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/EventContextHandler.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/Messages.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerExecutionGraph.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerSched.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerStatedump.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/messages.properties create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/package-info.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/EventField.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngInterruptContext.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngSystemModel.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngWorker.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/package-info.java diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/LinuxValues.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/LinuxValues.java similarity index 98% rename from analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/LinuxValues.java rename to analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/LinuxValues.java index d3791c2cd1..a43a582980 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/LinuxValues.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/LinuxValues.java @@ -7,7 +7,7 @@ * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.tracecompass.internal.analysis.os.linux.core.kernelanalysis; +package org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis; /** * Definitions of values used in the Linux kernel code. @@ -16,6 +16,7 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.core.kernelanalysis; * be added here first. * * @author Alexandre Montplaisir + * @since 2.0 */ public interface LinuxValues { diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/KernelStateProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/KernelStateProvider.java index ba15b1fdca..8eb5df45a5 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/KernelStateProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/KernelStateProvider.java @@ -18,9 +18,9 @@ import java.util.Map; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes; +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.LinuxValues; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.StateValues; import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; -import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernelanalysis.LinuxValues; import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF index b935531246..ca3c92b6d8 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF @@ -14,8 +14,12 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.tracecompass.tmf.core, org.eclipse.tracecompass.tmf.ctf.core, org.eclipse.tracecompass.lttng2.control.core, - org.eclipse.tracecompass.analysis.os.linux.core + org.eclipse.tracecompass.analysis.os.linux.core, + org.eclipse.tracecompass.analysis.graph.core Export-Package: org.eclipse.tracecompass.internal.lttng2.kernel.core;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests", + org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests", + org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests", + org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui,org.eclipse.tracecompass.lttng2.kernel.core.tests", org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui", org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui", org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.model.qemukvm;x-friends:="org.eclipse.tracecompass.lttng2.kernel.core.tests,org.eclipse.tracecompass.lttng2.kernel.ui", diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml index 52710452f1..f62c6c77d4 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml @@ -29,5 +29,14 @@ class="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment"> + + + + diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecGraphProvider.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecGraphProvider.java new file mode 100644 index 0000000000..127d3c631b --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecGraphProvider.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.building; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex.EdgeDirection; +import org.eclipse.tracecompass.analysis.graph.core.building.AbstractTmfGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers.EventContextHandler; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers.TraceEventHandlerExecutionGraph; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers.TraceEventHandlerSched; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers.TraceEventHandlerStatedump; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout; +import org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +/** + * The graph provider builds an execution graph from a kernel trace. The + * execution graph is a 2d-mesh model of the system, where vertices represent + * events, horizontal edges represent states of tasks, and where vertical edges + * represent relations between tasks (currently local wake-up and pairs of + * network packets). + * + * Event handling is split into smaller sub-handlers. One event request is done, + * and each event is passed to the handlers in the order in the list, such as + * this pseudo code: + * + *
+ * for each event:
+ *   for each handler:
+ *     handler.handleEvent(event)
+ * 
+ * + * @author Geneviève Bastien + * @author Francis Giraldeau + */ +public class LttngKernelExecGraphProvider extends AbstractTmfGraphProvider { + + private final LttngEventLayout fEventLayout; + private final LttngSystemModel fSystem; + + /** + * Represents an interrupt context + */ + public enum Context { + /** Not in an interrupt */ + NONE, + /** The interrupt is a soft IRQ */ + SOFTIRQ, + /** The interrupt is an IRQ */ + IRQ, + /** The interrupt is a timer */ + HRTIMER + } + + /** + * A list of status a thread can be in + */ + public enum ProcessStatus { + /** Unknown process status */ + UNKNOWN(0), + /** Waiting for a fork */ + WAIT_FORK(1), + /** Waiting for the CPU */ + WAIT_CPU(2), + /** The thread has exited, but is not dead yet */ + EXIT(3), + /** The thread is a zombie thread */ + ZOMBIE(4), + /** The thread is blocked */ + WAIT_BLOCKED(5), + /** The thread is running */ + RUN(6), + /** The thread is dead */ + DEAD(7); + private final int fValue; + + private ProcessStatus(int value) { + fValue = value; + } + + private int value() { + return fValue; + } + + /** + * Get the ProcessStatus associated with a long value + * + * @param val + * The long value corresponding to a status + * @return The {@link ProcessStatus} enum value + */ + static public ProcessStatus getStatus(long val) { + for (ProcessStatus e : ProcessStatus.values()) { + if (e.value() == val) { + return e; + } + } + return UNKNOWN; + } + } + + /** + * Constructor + * + * @param trace + * The trace on which to build graph + */ + public LttngKernelExecGraphProvider(ITmfTrace trace) { + super(trace, "LTTng Kernel"); //$NON-NLS-1$ + fSystem = new LttngSystemModel(); + + /* + * TODO: factorize this code because it is duplicated everywhere to + * access layout + */ + if (trace instanceof LttngKernelTrace) { + + fEventLayout = (LttngEventLayout) ((LttngKernelTrace) trace).getKernelEventLayout(); + } else { + /* Fall-back to the base LttngEventLayout */ + fEventLayout = (LttngEventLayout) LttngEventLayout.getInstance(); + } + + registerHandler(new TraceEventHandlerStatedump(this)); + registerHandler(new TraceEventHandlerSched(this)); + registerHandler(new EventContextHandler(this)); + registerHandler(new TraceEventHandlerExecutionGraph(this)); + } + + /** + * Simplify graph after construction + */ + @Override + public void done() { + TmfGraph graph = getAssignedGraph(); + if (graph == null) { + throw new NullPointerException(); + } + Set keys = graph.getWorkers(); + List kernelWorker = new ArrayList<>(); + /* build the set of worker to eliminate */ + for (Object k : keys) { + if (k instanceof LttngWorker) { + LttngWorker w = (LttngWorker) k; + if (w.getHostThread().getTid() == -1) { + kernelWorker.add(w); + } + } + } + for (LttngWorker k : kernelWorker) { + if (k == null) { + throw new NullPointerException(); + } + List nodes = graph.getNodesOf(k); + for (TmfVertex node : nodes) { + /* + * send -> recv, it removes the vertex between the real source + * and destination + */ + TmfEdge nextH = node.getEdge(EdgeDirection.OUTGOING_HORIZONTAL_EDGE); + TmfEdge inV = node.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE); + if (inV != null && nextH != null) { + + TmfVertex next = nextH.getVertexTo(); + TmfEdge nextV = next.getEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE); + if (nextV != null) { + TmfVertex src = inV.getVertexFrom(); + TmfVertex dst = nextV.getVertexTo(); + + /* unlink */ + node.removeEdge(EdgeDirection.INCOMING_VERTICAL_EDGE); + next.removeEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE); + + /* simplified link */ + src.linkVertical(dst).setType(inV.getType()); + } + } + } + } + } + + /** + * Returns the event layout for the current trace + * + * @return the eventLayout + */ + public LttngEventLayout getEventLayout() { + return fEventLayout; + } + + /** + * Returns the system model + * + * @return the system + */ + public LttngSystemModel getSystem() { + return fSystem; + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecutionGraph.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecutionGraph.java new file mode 100644 index 0000000000..0efd3083ed --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecutionGraph.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.building; + +import org.eclipse.tracecompass.analysis.graph.core.building.ITmfGraphProvider; +import org.eclipse.tracecompass.analysis.graph.core.building.TmfGraphBuilderModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +/** + * Graph building module for the lttng kernel execution graph + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class LttngKernelExecutionGraph extends TmfGraphBuilderModule { + + /** + * Analysis id of this module + */ + public static final String ANALYSIS_ID = "org.eclipse.tracecompass.lttng2.kernel.core.execgraph"; //$NON-NLS-1$ + + @Override + public boolean canExecute(ITmfTrace trace) { + /** + * TODO: Trace must have at least sched_switches and sched_wakeups + * enabled + */ + return true; + } + + @Override + protected ITmfGraphProvider getGraphProvider() { + ITmfTrace trace = getTrace(); + if (trace == null) { + throw new NullPointerException(); + } + return new LttngKernelExecGraphProvider(trace); + } + + @Override + protected String getFullHelpText() { + return super.getFullHelpText(); + } + + @Override + protected String getShortHelpText(ITmfTrace trace) { + return super.getShortHelpText(trace); + } + + @Override + protected String getTraceCannotExecuteHelpText(ITmfTrace trace) { + return "The trace must have events 'sched_switch' and 'sched_wakeup' enabled"; //$NON-NLS-1$ + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/package-info.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/package-info.java new file mode 100644 index 0000000000..7d74f24f4f --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building; \ No newline at end of file diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/BaseHandler.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/BaseHandler.java new file mode 100644 index 0000000000..460392d112 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/BaseHandler.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.tracecompass.analysis.graph.core.building.AbstractTraceEventHandler; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.event.ITmfEventType; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents; +import org.eclipse.tracecompass.tmf.core.trace.TmfEventTypeCollectionHelper; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; + +/** + * Holds the fields commons to all handler classes. + * + * @author Francis Giraldeau + * + */ +public class BaseHandler extends AbstractTraceEventHandler { + + private final LttngKernelExecGraphProvider fProvider; + private Map fHasEventSchedTTWU; + + BaseHandler(LttngKernelExecGraphProvider provider) { + fProvider = provider; + fHasEventSchedTTWU = new HashMap<>(); + ITmfTrace trace = getProvider().getTrace(); + LttngEventLayout layout = getProvider().getEventLayout(); + Collection traceSet = TmfTraceManager.getTraceSet(trace); + for (ITmfTrace traceItem : traceSet) { + if (traceItem instanceof ITmfTraceWithPreDefinedEvents) { + Set content = ((ITmfTraceWithPreDefinedEvents) traceItem).getContainedEventTypes(); + Set traceEvents = TmfEventTypeCollectionHelper.getEventNames(content); + boolean hasEvent = traceEvents.contains(layout.eventSchedProcessTTWU()); + fHasEventSchedTTWU.put(traceItem, hasEvent); + } + } + } + + /** + * Returns the parent graph provider + * + * @return the graph provider + */ + public LttngKernelExecGraphProvider getProvider() { + return fProvider; + } + + /** + * Return if the trace has the try to wake-up event + * + * @param trace + * the trace to check + * @return if the trace has the try to wake-up event + */ + public boolean traceHasEventSchedTTWU(ITmfTrace trace) { + Boolean ret = fHasEventSchedTTWU.get(trace); + if (ret == null) { + return false; + } + return ret; + } + + @Override + public void handleEvent(ITmfEvent event) { + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/EventContextHandler.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/EventContextHandler.java new file mode 100644 index 0000000000..d41005f114 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/EventContextHandler.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngInterruptContext; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel; +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; + +/** + * Event Handler to handle the interrupt context stack of the model + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class EventContextHandler extends BaseHandler { + + /** + * Constructor + * + * @param provider + * The parent graph provider + */ + public EventContextHandler(LttngKernelExecGraphProvider provider) { + super(provider); + } + + @Override + public void handleEvent(ITmfEvent event) { + String eventName = event.getName(); + IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(); + if (eventName.equals(eventLayout.eventSoftIrqEntry())) { + handleSoftirqEntry(event); + } else if (eventName.equals(eventLayout.eventSoftIrqExit())) { + handleSoftirqExit(event); + } else if (eventName.equals(eventLayout.eventHRTimerExpireEntry())) { + handleHrtimerExpireEntry(event); + } else if (eventName.equals(eventLayout.eventHRTimerExpireExit())) { + handleHrtimerExpireExit(event); + } else if (eventName.equals(eventLayout.eventIrqHandlerEntry())) { + handleIrqHandlerEntry(event); + } else if (eventName.equals(eventLayout.eventIrqHandlerExit())) { + handleIrqHandlerExit(event); + } + } + + private void pushInterruptContext(ITmfEvent event, Context ctx) { + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngSystemModel system = getProvider().getSystem(); + + LttngInterruptContext interruptCtx = new LttngInterruptContext(event, ctx); + + system.pushContextStack(event.getTrace().getHostId(), cpu, interruptCtx); + } + + private void popInterruptContext(ITmfEvent event, Context ctx) { + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngSystemModel system = getProvider().getSystem(); + + /* TODO: add a warning bookmark if the interrupt context is not coherent */ + LttngInterruptContext interruptCtx = system.peekContextStack(event.getTrace().getHostId(), cpu); + if (interruptCtx.getContext() == ctx) { + system.popContextStack(event.getTrace().getHostId(), cpu); + } + } + + private void handleSoftirqEntry(ITmfEvent event) { + pushInterruptContext(event, Context.SOFTIRQ); + } + + private void handleSoftirqExit(ITmfEvent event) { + popInterruptContext(event, Context.SOFTIRQ); + } + + private void handleIrqHandlerEntry(ITmfEvent event) { + pushInterruptContext(event, Context.IRQ); + } + + private void handleIrqHandlerExit(ITmfEvent event) { + popInterruptContext(event, Context.IRQ); + } + + private void handleHrtimerExpireEntry(ITmfEvent event) { + pushInterruptContext(event, Context.HRTIMER); + } + + private void handleHrtimerExpireExit(ITmfEvent event) { + popInterruptContext(event, Context.HRTIMER); + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/Messages.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/Messages.java new file mode 100644 index 0000000000..36d0340f79 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/Messages.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Messages for lttng graph handlers + * + * @author Francis Giraldeau + * + */ +@NonNullByDefault(false) +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers.messages"; //$NON-NLS-1$ + + /** + * Default thread name + */ + public static String TraceEventHandlerSched_UnknownThreadName; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerExecutionGraph.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerExecutionGraph.java new file mode 100644 index 0000000000..ddccd32e7d --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerExecutionGraph.java @@ -0,0 +1,424 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; + +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge.EdgeType; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex; +import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex.EdgeDirection; +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.LinuxValues; +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; +import org.eclipse.tracecompass.common.core.NonNullUtils; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.EventField; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngInterruptContext; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect; +import org.eclipse.tracecompass.tmf.core.event.matching.IMatchProcessingUnit; +import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventDependency; +import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +/** + * Event handler that actually builds the execution graph from the events + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class TraceEventHandlerExecutionGraph extends BaseHandler { + + /* + * The following IRQ constants was found empirically. + * + * TODO: other IRQ values should be determined from the lttng_statedump_interrupt events. + */ + private static final int IRQ_TIMER = 0; + + private static final NullProgressMonitor DEFAULT_PROGRESS_MONITOR = new NullProgressMonitor(); + + private final Table fKernel; + private final IMatchProcessingUnit fMatchProcessing; + private HashMap fTcpNodes; + private TmfEventMatching fTcpMatching; + + /** + * Constructor + * + * @param provider + * The parent graph provider + */ + public TraceEventHandlerExecutionGraph(LttngKernelExecGraphProvider provider) { + super(provider); + fKernel = NonNullUtils.checkNotNull(HashBasedTable. create()); + + fTcpNodes = new HashMap<>(); + fMatchProcessing = new IMatchProcessingUnit() { + + @Override + public void matchingEnded() { + } + + @Override + public int countMatches() { + return 0; + } + + @Override + public void addMatch(@Nullable TmfEventDependency match) { + if (match == null) { + return; + } + TmfVertex output = fTcpNodes.remove(match.getSourceEvent()); + TmfVertex input = fTcpNodes.remove(match.getDestinationEvent()); + if (output != null && input != null) { + output.linkVertical(input).setType(EdgeType.NETWORK); + } + } + + @Override + public void init(@Nullable Collection fTraces) { + + } + + }; + + ITmfTrace trace = provider.getTrace(); + fTcpMatching = new TmfEventMatching(Collections.singleton(trace), fMatchProcessing); + fTcpMatching.initMatching(); + } + + private LttngWorker getOrCreateKernelWorker(ITmfEvent event, Integer cpu) { + String host = event.getTrace().getHostId(); + LttngWorker worker = fKernel.get(host, cpu); + if (worker == null) { + HostThread ht = new HostThread(host, -1); + worker = new LttngWorker(ht, "kernel/" + cpu, event.getTimestamp().getValue()); //$NON-NLS-1$ + worker.setStatus(ProcessStatus.RUN); + + fKernel.put(host, cpu, worker); + } + return worker; + } + + @Override + public void handleEvent(ITmfEvent ev) { + String eventName = ev.getName(); + LttngEventLayout eventLayout = getProvider().getEventLayout(); + + if (eventName.equals(eventLayout.eventSchedSwitch())) { + handleSchedSwitch(ev); + } else if (eventName.equals(eventLayout.eventSchedProcessTTWU())) { + if (traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSchedProcessWakeup())) { + if (!traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSchedProcessWakeupNew())) { + if (!traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSoftIrqEntry())) { + handleSoftirqEntry(ev); + } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_IN) || + eventName.equals(TcpEventStrings.NETIF_RECEIVE_SKB)) { + handleInetSockLocalIn(ev); + } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_OUT) || + eventName.equals(TcpEventStrings.NET_DEV_QUEUE)) { + handleInetSockLocalOut(ev); + } + } + + private TmfVertex stateExtend(LttngWorker task, long ts) { + TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph()); + TmfVertex node = new TmfVertex(ts); + ProcessStatus status = task.getStatus(); + graph.append(task, node, resolveProcessStatus(status)); + return node; + } + + private TmfVertex stateChange(LttngWorker task, long ts) { + TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph()); + TmfVertex node = new TmfVertex(ts); + ProcessStatus status = task.getOldStatus(); + graph.append(task, node, resolveProcessStatus(status)); + return node; + } + + private static EdgeType resolveProcessStatus(ProcessStatus status) { + EdgeType ret = EdgeType.UNKNOWN; + switch (status) { + case DEAD: + break; + case EXIT: + case RUN: + ret = EdgeType.RUNNING; + break; + case UNKNOWN: + ret = EdgeType.UNKNOWN; + break; + case WAIT_BLOCKED: + ret = EdgeType.BLOCKED; + break; + case WAIT_CPU: + case WAIT_FORK: + ret = EdgeType.PREEMPTED; + break; + case ZOMBIE: + ret = EdgeType.UNKNOWN; + break; + default: + break; + } + return ret; + } + + private void handleSchedSwitch(ITmfEvent event) { + String host = event.getTrace().getHostId(); + long ts = event.getTimestamp().getValue(); + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + Integer next = EventField.getInt(event, eventLayout.fieldNextTid()); + Integer prev = EventField.getInt(event, eventLayout.fieldPrevTid()); + + LttngWorker nextTask = system.findWorker(new HostThread(host, next)); + LttngWorker prevTask = system.findWorker(new HostThread(host, prev)); + + if (prevTask == null || nextTask == null) { + return; + } + stateChange(prevTask, ts); + stateChange(nextTask, ts); + } + + private void handleSchedWakeup(ITmfEvent event) { + TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph()); + String host = event.getTrace().getHostId(); + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + long ts = event.getTimestamp().getValue(); + Integer tid = EventField.getInt(event, eventLayout.fieldTid()); + + LttngWorker target = system.findWorker(new HostThread(host, tid)); + LttngWorker current = system.getWorkerOnCpu(host, cpu); + if (target == null) { + return; + } + + ProcessStatus status = target.getOldStatus(); + switch (status) { + case WAIT_FORK: + waitFork(graph, ts, target, current); + break; + case WAIT_BLOCKED: + waitBlocked(event, graph, host, cpu, eventLayout, system, ts, target, current); + break; + case DEAD: + case EXIT: + case RUN: + case UNKNOWN: + case WAIT_CPU: + case ZOMBIE: + break; + default: + break; + } + } + + private void waitBlocked(ITmfEvent event, TmfGraph graph, String host, Integer cpu, LttngEventLayout eventLayout, LttngSystemModel system, long ts, LttngWorker target, @Nullable LttngWorker current) { + LttngInterruptContext context = system.peekContextStack(host, cpu); + switch (context.getContext()) { + case HRTIMER: + // shortcut of appendTaskNode: resolve blocking source in situ + graph.append(target, new TmfVertex(ts), EdgeType.TIMER); + break; + case IRQ: + irq(graph, eventLayout, ts, target, context); + break; + case SOFTIRQ: + softIrq(event, graph, cpu, eventLayout, ts, target, context); + break; + case NONE: + none(ts, target, current); + break; + default: + break; + } + } + + private void softIrq(ITmfEvent event, TmfGraph graph, Integer cpu, LttngEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) { + TmfVertex wup = new TmfVertex(ts); + TmfEdge l2 = graph.append(target, wup); + if (l2 != null) { + int vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec()).intValue(); + l2.setType(resolveSoftirq(vec)); + } + // special case for network related softirq + Long vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec()); + if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) { + // create edge if wake up is caused by incoming packet + LttngWorker k = getOrCreateKernelWorker(event, cpu); + TmfVertex tail = graph.getTail(k); + if (tail != null && tail.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE) != null) { + TmfVertex kwup = stateExtend(k, event.getTimestamp().getValue()); + kwup.linkVertical(wup); + } + } + } + + private void none(long ts, LttngWorker target, @Nullable LttngWorker current) { + // task context wakeup + if (current != null) { + TmfVertex n0 = stateExtend(current, ts); + TmfVertex n1 = stateChange(target, ts); + n0.linkVertical(n1); + } else { + stateChange(target, ts); + } + } + + private static void irq(TmfGraph graph, LttngEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) { + TmfEdge link = graph.append(target, new TmfVertex(ts)); + if (link != null) { + int vec = EventField.getLong(context.getEvent(), eventLayout.fieldIrq()).intValue(); + link.setType(resolveIRQ(vec)); + } + } + + private void waitFork(TmfGraph graph, long ts, LttngWorker target, @Nullable LttngWorker current) { + if (current != null) { + TmfVertex n0 = stateExtend(current, ts); + TmfVertex n1 = stateChange(target, ts); + graph.link(n0, n1); + } else { + stateChange(target, ts); + } + } + + private static EdgeType resolveIRQ(int vec) { + EdgeType ret = EdgeType.UNKNOWN; + switch (vec) { + case IRQ_TIMER: + ret = EdgeType.INTERRUPTED; + break; + default: + ret = EdgeType.UNKNOWN; + break; + } + return ret; + } + + private static EdgeType resolveSoftirq(int vec) { + EdgeType ret = EdgeType.UNKNOWN; + switch (vec) { + case LinuxValues.SOFTIRQ_HRTIMER: + case LinuxValues.SOFTIRQ_TIMER: + ret = EdgeType.TIMER; + break; + case LinuxValues.SOFTIRQ_BLOCK: + case LinuxValues.SOFTIRQ_BLOCK_IOPOLL: + ret = EdgeType.BLOCK_DEVICE; + break; + case LinuxValues.SOFTIRQ_NET_RX: + case LinuxValues.SOFTIRQ_NET_TX: + ret = EdgeType.NETWORK; + break; + case LinuxValues.SOFTIRQ_SCHED: + ret = EdgeType.INTERRUPTED; + break; + default: + ret = EdgeType.UNKNOWN; + break; + } + return ret; + } + + private void handleInetSockLocalIn(ITmfEvent event) { + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + String host = event.getTrace().getHostId(); + LttngSystemModel system = getProvider().getSystem(); + + LttngInterruptContext intCtx = system.peekContextStack(host, cpu); + Context context = intCtx.getContext(); + if (context == Context.SOFTIRQ) { + LttngWorker k = getOrCreateKernelWorker(event, cpu); + TmfVertex endpoint = stateExtend(k, event.getTimestamp().getValue()); + fTcpNodes.put(event, endpoint); + // TODO add actual progress monitor + fTcpMatching.matchEvent(event, event.getTrace(), DEFAULT_PROGRESS_MONITOR); + } + } + + private void handleInetSockLocalOut(ITmfEvent event) { + Object cpuObj = NonNullUtils.checkNotNull(TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event)); + Integer cpu = (Integer) cpuObj; + String host = event.getTrace().getHostId(); + LttngSystemModel system = getProvider().getSystem(); + + LttngInterruptContext intCtx = system.peekContextStack(host, cpu); + Context context = intCtx.getContext(); + + LttngWorker sender = null; + if (context == Context.NONE) { + sender = system.getWorkerOnCpu(event.getTrace().getHostId(), cpu); + } else if (context == Context.SOFTIRQ) { + sender = getOrCreateKernelWorker(event, cpu); + } + if (sender == null) { + return; + } + TmfVertex endpoint = stateExtend(sender, event.getTimestamp().getValue()); + fTcpNodes.put(event, endpoint); + // TODO, add actual progress monitor + fTcpMatching.matchEvent(event, event.getTrace(), new NullProgressMonitor()); + } + + private void handleSoftirqEntry(ITmfEvent event) { + LttngEventLayout eventLayout = getProvider().getEventLayout(); + TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph()); + Long vec = EventField.getLong(event, eventLayout.fieldVec()); + if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) { + Object cpuObj = NonNullUtils.checkNotNull(TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event)); + Integer cpu = (Integer) cpuObj; + LttngWorker k = getOrCreateKernelWorker(event, cpu); + graph.add(k, new TmfVertex(event.getTimestamp().getValue())); + } + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerSched.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerSched.java new file mode 100644 index 0000000000..879c7af26f --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerSched.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.LinuxValues; +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; +import org.eclipse.tracecompass.common.core.NonNullUtils; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.EventField; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout; +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; + +/** + * Provides the current task running on a CPU according to scheduling events + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class TraceEventHandlerSched extends BaseHandler { + + /** + * Constructor + * + * @param provider + * The parent graph provider + */ + public TraceEventHandlerSched(LttngKernelExecGraphProvider provider) { + super(provider); + } + + @Override + public void handleEvent(ITmfEvent ev) { + String eventName = ev.getName(); + LttngEventLayout eventLayout = getProvider().getEventLayout(); + + if (eventName.equals(eventLayout.eventSchedSwitch())) { + handleSchedSwitch(ev); + } else if (eventName.equals(eventLayout.eventSchedProcessTTWU())) { + if (traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSchedProcessWakeup())) { + if (!traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSchedProcessWakeupNew())) { + if (!traceHasEventSchedTTWU(ev.getTrace())) { + handleSchedWakeup(ev); + } + } else if (eventName.equals(eventLayout.eventSchedProcessFork())) { + handleSchedProcessFork(ev); + } else if (eventName.equals(eventLayout.eventSchedProcessExit())) { + handleSchedProcessExit(ev); + } else if (eventName.equals(eventLayout.eventSchedProcessExec())) { + handleSchedProcessExec(ev); + } + } + + private void handleSchedSwitch(ITmfEvent event) { + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + Integer next = EventField.getInt(event, eventLayout.fieldNextTid()); + Integer prev = EventField.getInt(event, eventLayout.fieldPrevTid()); + long ts = event.getTimestamp().getValue(); + long prev_state = EventField.getLong(event, eventLayout.fieldPrevState()); + prev_state = (long) ((int) prev_state) & (LinuxValues.TASK_STATE_RUNNING | LinuxValues.TASK_INTERRUPTIBLE | LinuxValues.TASK_UNINTERRUPTIBLE); + String host = event.getTrace().getHostId(); + + system.cacheTidOnCpu(cpu, new HostThread(event.getTrace().getHostId(), next)); + + HostThread nextHt = new HostThread(host, next); + LttngWorker nextTask = system.findWorker(nextHt); + if (nextTask == null) { + String name = EventField.getOrDefault(event, eventLayout.fieldNextComm(), NonNullUtils.checkNotNull(Messages.TraceEventHandlerSched_UnknownThreadName)); + nextTask = new LttngWorker(nextHt, name, ts); + system.addWorker(nextTask); + } + nextTask.setStatus(ProcessStatus.RUN); + + HostThread prevHt = new HostThread(host, prev); + LttngWorker prevTask = system.findWorker(prevHt); + if (prevTask == null) { + String name = EventField.getOrDefault(event, eventLayout.fieldPrevComm(), NonNullUtils.checkNotNull(Messages.TraceEventHandlerSched_UnknownThreadName)); + prevTask = new LttngWorker(prevHt, name, ts); + system.addWorker(prevTask); + } + /* prev_state == 0 means runnable, thus waits for cpu */ + if (prev_state == 0) { + prevTask.setStatus(ProcessStatus.WAIT_CPU); + } else { + prevTask.setStatus(ProcessStatus.WAIT_BLOCKED); + } + } + + private void handleSchedProcessFork(ITmfEvent event) { + String host = event.getTrace().getHostId(); + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + Integer childTid = EventField.getInt(event, eventLayout.fieldChildTid()); + String name = EventField.getString(event, eventLayout.fieldChildComm()); + long ts = event.getTimestamp().getValue(); + + HostThread childHt = new HostThread(host, childTid); + + LttngWorker childTask = system.findWorker(childHt); + if (childTask == null) { + childTask = new LttngWorker(childHt, name, ts); + system.addWorker(childTask); + } + + childTask.setStatus(ProcessStatus.WAIT_FORK); + } + + private void handleSchedWakeup(ITmfEvent event) { + String host = event.getTrace().getHostId(); + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + Integer tid = EventField.getInt(event, eventLayout.fieldTid()); + HostThread targetHt = new HostThread(host, tid); + + LttngWorker target = system.findWorker(targetHt); + LttngWorker current = system.getWorkerOnCpu(host, cpu); + if (target == null) { + String name = EventField.getOrDefault(event, eventLayout.fieldComm(), NonNullUtils.checkNotNull(Messages.TraceEventHandlerSched_UnknownThreadName)); + target = new LttngWorker(targetHt, name, event.getTimestamp().getValue()); + system.addWorker(target); + target.setStatus(ProcessStatus.WAIT_BLOCKED); + } + // spurious wakeup + ProcessStatus status = target.getStatus(); + if ((current != null && target.getHostThread().equals(current.getHostThread())) || + status == ProcessStatus.WAIT_CPU) { + return; + } + if (status == ProcessStatus.WAIT_BLOCKED || + status == ProcessStatus.WAIT_FORK || + status == ProcessStatus.UNKNOWN) { + target.setStatus(ProcessStatus.WAIT_CPU); + return; + } + } + + private void handleSchedProcessExit(ITmfEvent event) { + String host = event.getTrace().getHostId(); + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + Integer tid = EventField.getInt(event, eventLayout.fieldTid()); + LttngWorker task = system.findWorker(new HostThread(host, tid)); + if (task == null) { + return; + } + task.setStatus(ProcessStatus.EXIT); + } + + private void handleSchedProcessExec(ITmfEvent event) { + String host = event.getTrace().getHostId(); + Object cpuObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event); + if (cpuObj == null) { + throw new NullPointerException(); + } + Integer cpu = (Integer) cpuObj; + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + + String filename = EventField.getString(event, eventLayout.fieldFilename()); + LttngWorker task = system.getWorkerOnCpu(host, cpu); + if (task == null) { + return; + } + task.setName(filename); + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerStatedump.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerStatedump.java new file mode 100644 index 0000000000..0c17d0cbd7 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerStatedump.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; + +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.EventField; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; + +/** + * Handles the LTTng statedump events necessary for the initialization of the + * system model + * + * @author Francis Giraldeau + */ +public class TraceEventHandlerStatedump extends BaseHandler { + + /** + * Constructor + * + * @param provider + * The parent graph provider + */ + public TraceEventHandlerStatedump(LttngKernelExecGraphProvider provider) { + super(provider); + } + + @Override + public void handleEvent(ITmfEvent event) { + LttngEventLayout eventLayout = getProvider().getEventLayout(); + LttngSystemModel system = getProvider().getSystem(); + String eventName = event.getName(); + if (!eventName.equals(eventLayout.eventStatedumpProcessState())) { + return; + } + + Integer tid = EventField.getInt(event, eventLayout.fieldTid()); + String name = EventField.getOrDefault(event, eventLayout.fieldName(), Messages.TraceEventHandlerSched_UnknownThreadName); + Integer status = EventField.getInt(event, eventLayout.fieldStatus()); + + String host = event.getTrace().getHostId(); + long ts = event.getTimestamp().getValue(); + + HostThread ht = new HostThread(host, tid); + LttngWorker task = system.findWorker(ht); + if (task == null) { + task = new LttngWorker(ht, name, ts); + system.addWorker(task); + } else { + task.setName(name); + } + + task.setStatus(ProcessStatus.getStatus(status)); + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/messages.properties b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/messages.properties new file mode 100644 index 0000000000..b968f918e5 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/messages.properties @@ -0,0 +1,10 @@ +############################################################################### +# Copyright (c) 2015 Ecole Polytechnique de Montreal +# +# 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 +############################################################################### + +TraceEventHandlerSched_UnknownThreadName=unknown diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/package-info.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/package-info.java new file mode 100644 index 0000000000..d7c45bac9f --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers; \ No newline at end of file diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/EventField.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/EventField.java new file mode 100644 index 0000000000..048dca4c48 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/EventField.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.model; + +import org.eclipse.tracecompass.common.core.NonNullUtils; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; + +/** + * Type casting for getting field values + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class EventField { + + /** + * Get int field + * + * @param event + * the event + * @param name + * the field name + * @return the long value + */ + public static Integer getInt(ITmfEvent event, String name) { + ITmfEventField field = NonNullUtils.checkNotNull(event.getContent().getField(name)); + Object value = field.getValue(); + if (value instanceof Long) { + return NonNullUtils.checkNotNull(((Long) value).intValue()); + } + return NonNullUtils.checkNotNull((Integer) value); + } + + /** + * Get long field + * + * @param event + * the event + * @param name + * the field name + * @return the long value + */ + public static Long getLong(ITmfEvent event, String name) { + ITmfEventField field = NonNullUtils.checkNotNull(event.getContent().getField(name)); + return NonNullUtils.checkNotNull((Long) field.getValue()); + } + + /** + * Get string field + * + * @param event + * the event + * @param name + * the field name + * @return the string value + */ + public static String getString(ITmfEvent event, String name) { + ITmfEventField field = NonNullUtils.checkNotNull(event.getContent().getField(name)); + return NonNullUtils.checkNotNull((String) field.getValue()); + } + + /** + * Get float field + * + * @param event + * the event + * @param name + * the field name + * @return the float value + */ + public static double getFloat(ITmfEvent event, String name) { + ITmfEventField field = NonNullUtils.checkNotNull(event.getContent().getField(name)); + return NonNullUtils.checkNotNull((Double) field.getValue()); + } + + /** + * Get string field with default value + * + * @param event + * the event + * @param name + * the field name + * @param def + * the default value to return if the field does not exists + * @return the long value + */ + public static String getOrDefault(ITmfEvent event, String name, String def) { + ITmfEventField field = event.getContent().getField(name); + if (field == null) { + return def; + } + return NonNullUtils.checkNotNull((String) field.getValue()); + } +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngInterruptContext.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngInterruptContext.java new file mode 100644 index 0000000000..8afd0d3e8d --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngInterruptContext.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.model; + +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.event.TmfEvent; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; +import org.eclipse.tracecompass.tmf.core.trace.ITmfContext; + +/** + * A class representing an interrupt context in the kernel. It associates the + * reason of the context with an event. + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class LttngInterruptContext { + + /** + * The default context when none is defined + */ + public static final LttngInterruptContext DEFAULT_CONTEXT = new LttngInterruptContext(new TmfEvent(null, ITmfContext.UNKNOWN_RANK, TmfTimestamp.BIG_BANG, null, null), Context.NONE); + + private final ITmfEvent fEvent; + private final Context fContext; + + /** + * Constructor + * + * @param event + * The event representing the start of this interrupt context + * @param ctx + * The context type + */ + public LttngInterruptContext(ITmfEvent event, Context ctx) { + fEvent = event; + fContext = ctx; + } + + /** + * The event associated with this interrupt context + * + * @return The event marking the entry in this interrupt context + */ + public ITmfEvent getEvent() { + return fEvent; + } + + /** + * Get the type of interrupt context this context represents + * + * @return The type of interrupt context + */ + public Context getContext() { + return fContext; + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngSystemModel.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngSystemModel.java new file mode 100644 index 0000000000..f7961de676 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngSystemModel.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.model; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; +import org.eclipse.tracecompass.common.core.NonNullUtils; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +/** + * This class contains the model of a Linux system + * + * TODO: This model is custom made for the LTTng dependency analysis for ease of + * development of the feature, but most of it and the classes it uses also apply + * to any Linux OS trace, so the classes in this package should be moved to + * analysis.os.linux + * + * @author Francis Giraldeau + * @author Geneviève Bastien + */ +public class LttngSystemModel { + + private final Table fCurrentTids = NonNullUtils.checkNotNull(HashBasedTable. create()); + private final Table> fIntCtxStacks = NonNullUtils.checkNotNull(HashBasedTable.> create()); + private final Map fWorkerMap = new HashMap<>(); + + /** + * Cache the TID currently on the CPU of a host, for easier access later on + * + * @param cpu + * The CPU ID + * @param ht + * The {@link HostThread} object that is running on this CPU + */ + public void cacheTidOnCpu(Integer cpu, HostThread ht) { + fCurrentTids.put(ht.getHost(), cpu, ht); + } + + /** + * Get the {@link LttngWorker} object that is currently running on the CPU + * of a host + * + * @param host + * The identifier of the trace/machine of the CPU + * @param cpu + * The CPU ID on which the worker is running + * @return The {@link LttngWorker} running on the CPU + */ + public @Nullable LttngWorker getWorkerOnCpu(String host, Integer cpu) { + HostThread ht = fCurrentTids.get(host, cpu); + if (ht == null) { + return null; + } + return findWorker(ht); + } + + /** + * Return the worker associated with this host TID + * + * @param ht + * The host thread associated with a worker + * @return The {@link LttngWorker} associated with a host thread + */ + public @Nullable LttngWorker findWorker(HostThread ht) { + return fWorkerMap.get(ht); + } + + /** + * Add a new worker to the system + * + * @param worker + * The worker to add + */ + public void addWorker(LttngWorker worker) { + fWorkerMap.put(worker.getHostThread(), worker); + } + + /** + * Get the list of workers on this system + * + * @return The list of workers on the system + */ + public Collection getWorkers() { + return NonNullUtils.checkNotNull(fWorkerMap.values()); + } + + /** + * Pushes an interrupt context on the stack for a CPU on a host + * + * @param hostId + * The host ID of the trace/machine the interrupt context belongs + * to + * @param cpu + * The CPU this interrupt happened on + * @param interruptCtx + * The interrupt context to push on the stack + */ + public void pushContextStack(String hostId, Integer cpu, LttngInterruptContext interruptCtx) { + Stack stack = fIntCtxStacks.get(hostId, cpu); + if (stack == null) { + stack = new Stack<>(); + fIntCtxStacks.put(hostId, cpu, stack); + } + stack.push(interruptCtx); + } + + /** + * Peeks the top of the interrupt context stack for a CPU on a host, to see + * what is the latest context. + * + * @param hostId + * The host ID of the trace/machine the interrupt context belongs + * to + * @param cpu + * The CPU this interrupt happened on + * @return The latest interrupt context on the CPU of the host + */ + public LttngInterruptContext peekContextStack(String hostId, Integer cpu) { + Stack stack = fIntCtxStacks.get(hostId, cpu); + if (stack == null) { + return LttngInterruptContext.DEFAULT_CONTEXT; + } + if (stack.empty()) { + return LttngInterruptContext.DEFAULT_CONTEXT; + } + LttngInterruptContext peek = stack.peek(); + if (peek == null) { + peek = LttngInterruptContext.DEFAULT_CONTEXT; + } + return peek; + } + + /** + * Removes the top of the interrupt context stack for a CPU on a host and + * returns the result + * + * @param hostId + * The host ID of the trace/machine the interrupt context belongs + * to + * @param cpu + * The CPU this interrupt happened on + * @return The latest interrupt context on the CPU of the host + */ + public @Nullable LttngInterruptContext popContextStack(String hostId, Integer cpu) { + Stack stack = fIntCtxStacks.get(hostId, cpu); + if (stack == null) { + return null; + } + if (stack.empty()) { + return null; + } + return stack.pop(); + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngWorker.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngWorker.java new file mode 100644 index 0000000000..433c746f0f --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngWorker.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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.tracecompass.internal.lttng2.kernel.core.analysis.graph.model; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker; +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; +import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus; + +/** + * This class represents the worker unit from the execution graph + * + * TODO: See if this class could be integrated inside HostThread instead. + * + * @author Geneviève Bastien + */ +public class LttngWorker implements IGraphWorker { + + private final HostThread fHostTid; + private final long fStart; + + private String fThreadName; + private ProcessStatus fStatus = ProcessStatus.UNKNOWN; + private ProcessStatus fOldStatus = ProcessStatus.UNKNOWN; + + /** + * Constructor + * + * @param ht + * The host thread represented by this worker + * @param name + * The name of this thread + * @param ts + * The timestamp + */ + public LttngWorker(HostThread ht, String name, long ts) { + fHostTid = ht; + fThreadName = name; + fStart = ts; + } + + @Override + public String getHostId() { + return fHostTid.getHost(); + } + + /** + * Set the name of this worker + * + * @param name The name of this worker + */ + public void setName(String name) { + fThreadName = name; + } + + /** + * Get the name of this worker + * + * @return The name of the worker + */ + public String getName() { + return fThreadName; + } + + /** + * Set the status, saving the old value that can still be accessed using {@link LttngWorker#getOldStatus()} + * + * @param status The new status of this + */ + public void setStatus(ProcessStatus status) { + fOldStatus = fStatus; + fStatus = status; + } + + /** + * Get the status of this thread + * + * @return The thread status + */ + public ProcessStatus getStatus() { + return fStatus; + } + + /** + * Return the previous status this worker was in + * + * @return The previous status of this worker + */ + public ProcessStatus getOldStatus() { + return fOldStatus; + } + + /** + * Get the host thread associated with this worker + * + * @return The {@link HostThread} associated with this worker + */ + public HostThread getHostThread() { + return fHostTid; + } + + /** + * Get the start time of this worker + * + * @return The start time in nanoseconds + */ + public long getStart() { + return fStart; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof LttngWorker) { + return getHostThread().equals(((LttngWorker) obj).getHostThread()); + } + return false; + } + + @Override + public int hashCode() { + return fHostTid.hashCode(); + } + + @Override + public String toString() { + return '[' + fThreadName + ',' + fHostTid.getTid() + ']'; + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/package-info.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/package-info.java new file mode 100644 index 0000000000..9caf257002 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2015 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model; \ No newline at end of file diff --git a/tmf/org.eclipse.tracecompass.tmf/feature.xml b/tmf/org.eclipse.tracecompass.tmf/feature.xml index 1eb8338faa..63ced33afa 100644 --- a/tmf/org.eclipse.tracecompass.tmf/feature.xml +++ b/tmf/org.eclipse.tracecompass.tmf/feature.xml @@ -80,4 +80,11 @@ version="0.0.0" unpack="false"/> + + -- 2.34.1