/******************************************************************************* * 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.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; 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: * * <pre> * for each event: * for each handler: * handler.handleEvent(event) * </pre> * * @author Geneviève Bastien * @author Francis Giraldeau */ public class LttngKernelExecGraphProvider extends AbstractTmfGraphProvider { 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, /** The inter-processor interrupt */ IPI, } /** * 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(); 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<IGraphWorker> keys = graph.getWorkers(); List<LttngWorker> 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) { List<TmfVertex> 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 given trace * * @param trace * the trace * * @return the eventLayout */ public IKernelAnalysisEventLayout getEventLayout(ITmfTrace trace) { if (trace instanceof LttngKernelTrace) { return ((LttngKernelTrace) trace).getKernelEventLayout(); } return LttngEventLayout.getInstance(); } /** * Returns the system model * * @return the system */ public LttngSystemModel getSystem() { return fSystem; } }