lttng: Add the dependency graph model and handlers for an LTTng kernel
authorFrancis Giraldeau <francis.giraldeau@gmail.com>
Mon, 9 Feb 2015 03:46:04 +0000 (22:46 -0500)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Wed, 21 Oct 2015 12:55:32 +0000 (08:55 -0400)
trace

Change-Id: I0ec0ee9e141e13117ef2367059ad709afb74a130
Signed-off-by: Francis Giraldeau <francis.giraldeau@gmail.com>
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/41479
Reviewed-by: Hudson CI
22 files changed:
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/LinuxValues.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/KernelStateProvider.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernelanalysis/LinuxValues.java [deleted file]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/META-INF/MANIFEST.MF
lttng/org.eclipse.tracecompass.lttng2.kernel.core/plugin.xml
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecGraphProvider.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/LttngKernelExecutionGraph.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/building/package-info.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/BaseHandler.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/EventContextHandler.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/Messages.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerExecutionGraph.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerSched.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/TraceEventHandlerStatedump.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/messages.properties [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/handlers/package-info.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/EventField.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngInterruptContext.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngSystemModel.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/LttngWorker.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/analysis/graph/model/package-info.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf/feature.xml

diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/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
new file mode 100644 (file)
index 0000000..a43a582
--- /dev/null
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * 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.analysis.os.linux.core.kernelanalysis;
+
+/**
+ * Definitions of values used in the Linux kernel code.
+ *
+ * Instead of using "magic numbers" in state providers, the definitions should
+ * be added here first.
+ *
+ * @author Alexandre Montplaisir
+ * @since 2.0
+ */
+public interface LinuxValues {
+
+    /**
+     * Process states found in scheduler events.
+     *
+     * From include/linux/sched.h
+     *
+     * <pre>
+     * #define TASK_RUNNING 0
+     * #define TASK_INTERRUPTIBLE 1
+     * #define TASK_UNINTERRUPTIBLE 2
+     * #define __TASK_STOPPED 4
+     * #define __TASK_TRACED 8
+     * #define EXIT_DEAD 16
+     * #define EXIT_ZOMBIE 32
+     * #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
+     * #define TASK_DEAD 64
+     * #define TASK_WAKEKILL 128
+     * #define TASK_WAKING 256
+     * #define TASK_PARKED 512
+     * #define TASK_STATE_MAX 1024
+     * </pre>
+     */
+    /**
+     * The task is running normally, can be interrupted, in a syscall or user
+     * mode.
+     */
+    int TASK_STATE_RUNNING = 0;
+
+    /**
+     * The process is in an interruptible sleep, (waiting for an event to
+     * complete)
+     */
+    int TASK_INTERRUPTIBLE = 1;
+
+    /**
+     * The process is in an uninteruptible sleep, (usually waiting on IO)
+     */
+    int TASK_UNINTERRUPTIBLE = 2;
+
+    /**
+     * The process is stopped, it is waiting for a SIGCONT
+     */
+    int TASK_STOPPED__ = 4;
+
+    /**
+     * The process is being monitored by other processes like a debugger
+     */
+    int TASK_TRACED__ = 8;
+
+    /**
+     * The task is terminated. It is lingering waiting for a parent to reap it.
+     */
+    int EXIT_ZOMBIE = 16;
+
+    /**
+     * The final state, the process reaches this state when being reaped. This
+     * state should not be seen.
+     */
+    int EXIT_DEAD = 32;
+
+    /**
+     * The task is dead, that means the PID can be re-used.
+     */
+    int TASK_DEAD = 64;
+
+    /**
+     * The task will wake up only on kill signals
+     */
+    int TASK_WAKEKILL = 128;
+
+    /**
+     * A task is being woken up, should not appear in sched switch, but if we
+     * poll.
+     */
+    int TASK_WAKING = 256;
+
+    /**
+     * A very deep sleep that can only be woken by an unpark wakeup
+     */
+    int TASK_PARK = 512;
+
+    /**
+     * This is the maximum value + 1 that the task state can be. TASK_STATE_MAX
+     * - 1 is useful to mask the task state.
+     */
+    int TASK_STATE_MAX = 1024;
+
+    /**
+     * Process statuses, used in LTTng statedump events.
+     *
+     * This is LTTng-specific, but the statedump are handled at this level, so
+     * it makes sense to add those definitions here.
+     *
+     * Taken from lttng-module's lttng-statedump-impl.c:
+     *
+     * <pre>
+     * enum lttng_process_status {
+     *     LTTNG_UNNAMED = 0,
+     *     LTTNG_WAIT_FORK = 1,
+     *     LTTNG_WAIT_CPU = 2,
+     *     LTTNG_EXIT = 3,
+     *     LTTNG_ZOMBIE = 4,
+     *     LTTNG_WAIT = 5,
+     *     LTTNG_RUN = 6,
+     *     LTTNG_DEAD = 7,
+     * };
+     * </pre>
+     */
+
+    /** Task is initially preempted */
+    int STATEDUMP_PROCESS_STATUS_WAIT_CPU = 2;
+
+    /** Task is initially blocked */
+    int STATEDUMP_PROCESS_STATUS_WAIT = 5;
+
+    /**
+     * SoftIRQ definitions
+     *
+     * From linux/interrupt.h
+     *
+     * <pre>
+     * enum
+     * {
+     *     HI_SOFTIRQ=0,
+     *     TIMER_SOFTIRQ,
+     *     NET_TX_SOFTIRQ,
+     *     NET_RX_SOFTIRQ,
+     *     BLOCK_SOFTIRQ,
+     *     BLOCK_IOPOLL_SOFTIRQ,
+     *     TASKLET_SOFTIRQ,
+     *     SCHED_SOFTIRQ,
+     *     HRTIMER_SOFTIRQ,
+     *     RCU_SOFTIRQ,
+     *     NR_SOFTIRQS // not used as this is the NUMBER of softirqs
+     * };
+     * </pre>
+     */
+
+    /** High-priority tasklet */
+    int SOFTIRQ_HI = 0;
+
+    /** Interrupted because of timer */
+    int SOFTIRQ_TIMER = 1;
+
+    /** Interrupted because of network transmission */
+    int SOFTIRQ_NET_TX = 2;
+
+    /** Interrupted because of network reception */
+    int SOFTIRQ_NET_RX = 3;
+
+    /** Interrupted because of block operation */
+    int SOFTIRQ_BLOCK = 4;
+
+    /** Interrupted because of block IO */
+    int SOFTIRQ_BLOCK_IOPOLL = 5;
+
+    /** Tasklet (differed device interrupt) */
+    int SOFTIRQ_TASKLET = 6;
+
+    /** Interrupted because of the scheduler */
+    int SOFTIRQ_SCHED = 7;
+
+    /** Interrupted because of HR timer */
+    int SOFTIRQ_HRTIMER = 8;
+
+    /** Interrupted because of RCU */
+    int SOFTIRQ_RCU = 9;
+}
index ba15b1fdcac9edf5202bde2555534393b8a563ff..8eb5df45a5d2fc997dee40f9d306699595f1d8aa 100644 (file)
@@ -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/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/internal/analysis/os/linux/core/kernelanalysis/LinuxValues.java
deleted file mode 100644 (file)
index d3791c2..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
- *
- * 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.analysis.os.linux.core.kernelanalysis;
-
-/**
- * Definitions of values used in the Linux kernel code.
- *
- * Instead of using "magic numbers" in state providers, the definitions should
- * be added here first.
- *
- * @author Alexandre Montplaisir
- */
-public interface LinuxValues {
-
-    /**
-     * Process states found in scheduler events.
-     *
-     * From include/linux/sched.h
-     *
-     * <pre>
-     * #define TASK_RUNNING 0
-     * #define TASK_INTERRUPTIBLE 1
-     * #define TASK_UNINTERRUPTIBLE 2
-     * #define __TASK_STOPPED 4
-     * #define __TASK_TRACED 8
-     * #define EXIT_DEAD 16
-     * #define EXIT_ZOMBIE 32
-     * #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
-     * #define TASK_DEAD 64
-     * #define TASK_WAKEKILL 128
-     * #define TASK_WAKING 256
-     * #define TASK_PARKED 512
-     * #define TASK_STATE_MAX 1024
-     * </pre>
-     */
-    /**
-     * The task is running normally, can be interrupted, in a syscall or user
-     * mode.
-     */
-    int TASK_STATE_RUNNING = 0;
-
-    /**
-     * The process is in an interruptible sleep, (waiting for an event to
-     * complete)
-     */
-    int TASK_INTERRUPTIBLE = 1;
-
-    /**
-     * The process is in an uninteruptible sleep, (usually waiting on IO)
-     */
-    int TASK_UNINTERRUPTIBLE = 2;
-
-    /**
-     * The process is stopped, it is waiting for a SIGCONT
-     */
-    int TASK_STOPPED__ = 4;
-
-    /**
-     * The process is being monitored by other processes like a debugger
-     */
-    int TASK_TRACED__ = 8;
-
-    /**
-     * The task is terminated. It is lingering waiting for a parent to reap it.
-     */
-    int EXIT_ZOMBIE = 16;
-
-    /**
-     * The final state, the process reaches this state when being reaped. This
-     * state should not be seen.
-     */
-    int EXIT_DEAD = 32;
-
-    /**
-     * The task is dead, that means the PID can be re-used.
-     */
-    int TASK_DEAD = 64;
-
-    /**
-     * The task will wake up only on kill signals
-     */
-    int TASK_WAKEKILL = 128;
-
-    /**
-     * A task is being woken up, should not appear in sched switch, but if we
-     * poll.
-     */
-    int TASK_WAKING = 256;
-
-    /**
-     * A very deep sleep that can only be woken by an unpark wakeup
-     */
-    int TASK_PARK = 512;
-
-    /**
-     * This is the maximum value + 1 that the task state can be. TASK_STATE_MAX
-     * - 1 is useful to mask the task state.
-     */
-    int TASK_STATE_MAX = 1024;
-
-    /**
-     * Process statuses, used in LTTng statedump events.
-     *
-     * This is LTTng-specific, but the statedump are handled at this level, so
-     * it makes sense to add those definitions here.
-     *
-     * Taken from lttng-module's lttng-statedump-impl.c:
-     *
-     * <pre>
-     * enum lttng_process_status {
-     *     LTTNG_UNNAMED = 0,
-     *     LTTNG_WAIT_FORK = 1,
-     *     LTTNG_WAIT_CPU = 2,
-     *     LTTNG_EXIT = 3,
-     *     LTTNG_ZOMBIE = 4,
-     *     LTTNG_WAIT = 5,
-     *     LTTNG_RUN = 6,
-     *     LTTNG_DEAD = 7,
-     * };
-     * </pre>
-     */
-
-    /** Task is initially preempted */
-    int STATEDUMP_PROCESS_STATUS_WAIT_CPU = 2;
-
-    /** Task is initially blocked */
-    int STATEDUMP_PROCESS_STATUS_WAIT = 5;
-
-    /**
-     * SoftIRQ definitions
-     *
-     * From linux/interrupt.h
-     *
-     * <pre>
-     * enum
-     * {
-     *     HI_SOFTIRQ=0,
-     *     TIMER_SOFTIRQ,
-     *     NET_TX_SOFTIRQ,
-     *     NET_RX_SOFTIRQ,
-     *     BLOCK_SOFTIRQ,
-     *     BLOCK_IOPOLL_SOFTIRQ,
-     *     TASKLET_SOFTIRQ,
-     *     SCHED_SOFTIRQ,
-     *     HRTIMER_SOFTIRQ,
-     *     RCU_SOFTIRQ,
-     *     NR_SOFTIRQS // not used as this is the NUMBER of softirqs
-     * };
-     * </pre>
-     */
-
-    /** High-priority tasklet */
-    int SOFTIRQ_HI = 0;
-
-    /** Interrupted because of timer */
-    int SOFTIRQ_TIMER = 1;
-
-    /** Interrupted because of network transmission */
-    int SOFTIRQ_NET_TX = 2;
-
-    /** Interrupted because of network reception */
-    int SOFTIRQ_NET_RX = 3;
-
-    /** Interrupted because of block operation */
-    int SOFTIRQ_BLOCK = 4;
-
-    /** Interrupted because of block IO */
-    int SOFTIRQ_BLOCK_IOPOLL = 5;
-
-    /** Tasklet (differed device interrupt) */
-    int SOFTIRQ_TASKLET = 6;
-
-    /** Interrupted because of the scheduler */
-    int SOFTIRQ_SCHED = 7;
-
-    /** Interrupted because of HR timer */
-    int SOFTIRQ_HRTIMER = 8;
-
-    /** Interrupted because of RCU */
-    int SOFTIRQ_RCU = 9;
-}
index b935531246620edea7f90fe186105a286368a96b..ca3c92b6d8a785b5adb67de973c7df79c4fb2413 100644 (file)
@@ -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",
index 52710452f17b3c375b08035d050abe5180ed29a3..f62c6c77d456a5e6f228838321d0a748acf12946 100644 (file)
                   class="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.trace.VirtualMachineExperiment">
             </tracetype>
       </module>
+      <module
+            analysis_module="org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecutionGraph"
+            applies_experiment="true"
+            id="org.eclipse.tracecompass.lttng2.kernel.core.execgraph"
+            name="LTTng Kernel Exec Graph">
+         <tracetype
+               class="org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace">
+         </tracetype>
+      </module>
    </extension>
 </plugin>
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 (file)
index 0000000..127d3c6
--- /dev/null
@@ -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:
+ *
+ * <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 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<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) {
+            if (k == null) {
+                throw new NullPointerException();
+            }
+            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 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 (file)
index 0000000..0efd308
--- /dev/null
@@ -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 (file)
index 0000000..7d74f24
--- /dev/null
@@ -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 (file)
index 0000000..460392d
--- /dev/null
@@ -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 <francis.giraldeau@gmail.com>
+ *
+ */
+public class BaseHandler extends AbstractTraceEventHandler {
+
+    private final LttngKernelExecGraphProvider fProvider;
+    private Map<ITmfTrace, Boolean> fHasEventSchedTTWU;
+
+    BaseHandler(LttngKernelExecGraphProvider provider) {
+        fProvider = provider;
+        fHasEventSchedTTWU = new HashMap<>();
+        ITmfTrace trace = getProvider().getTrace();
+        LttngEventLayout layout = getProvider().getEventLayout();
+        Collection<ITmfTrace> traceSet = TmfTraceManager.getTraceSet(trace);
+        for (ITmfTrace traceItem : traceSet) {
+            if (traceItem instanceof ITmfTraceWithPreDefinedEvents) {
+                Set<? extends ITmfEventType> content = ((ITmfTraceWithPreDefinedEvents) traceItem).getContainedEventTypes();
+                Set<String> 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 (file)
index 0000000..d41005f
--- /dev/null
@@ -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 (file)
index 0000000..36d0340
--- /dev/null
@@ -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 <francis.giraldeau@gmail.com>
+ *
+ */
+@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 (file)
index 0000000..ddccd32
--- /dev/null
@@ -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<String, Integer, LttngWorker> fKernel;
+    private final IMatchProcessingUnit fMatchProcessing;
+    private HashMap<ITmfEvent, TmfVertex> fTcpNodes;
+    private TmfEventMatching fTcpMatching;
+
+    /**
+     * Constructor
+     *
+     * @param provider
+     *            The parent graph provider
+     */
+    public TraceEventHandlerExecutionGraph(LttngKernelExecGraphProvider provider) {
+        super(provider);
+        fKernel = NonNullUtils.checkNotNull(HashBasedTable.<String, Integer, LttngWorker> 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<ITmfTrace> 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 (file)
index 0000000..879c7af
--- /dev/null
@@ -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 (file)
index 0000000..0c17d0c
--- /dev/null
@@ -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 (file)
index 0000000..b968f91
--- /dev/null
@@ -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 (file)
index 0000000..d7c45ba
--- /dev/null
@@ -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 (file)
index 0000000..048dca4
--- /dev/null
@@ -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 (file)
index 0000000..8afd0d3
--- /dev/null
@@ -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 (file)
index 0000000..f7961de
--- /dev/null
@@ -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<String, Integer, HostThread> fCurrentTids = NonNullUtils.checkNotNull(HashBasedTable.<String, Integer, HostThread> create());
+    private final Table<String, Integer, Stack<LttngInterruptContext>> fIntCtxStacks = NonNullUtils.checkNotNull(HashBasedTable.<String, Integer, Stack<LttngInterruptContext>> create());
+    private final Map<HostThread, LttngWorker> 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<LttngWorker> 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<LttngInterruptContext> 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<LttngInterruptContext> 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<LttngInterruptContext> 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 (file)
index 0000000..433c746
--- /dev/null
@@ -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 (file)
index 0000000..9caf257
--- /dev/null
@@ -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
index 1eb8338faa4ae92ab4ee276b342f3916b1e74f5f..63ced33afa385bd46116c0c29443cb0e69f10b7c 100644 (file)
          version="0.0.0"
          unpack="false"/>
 
+   <plugin
+         id="org.eclipse.tracecompass.analysis.graph.core"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
This page took 0.049176 seconds and 5 git commands to generate.