linux.core: Support IPIs in kernel analysis (Bug 498215)
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 21 Jul 2016 20:53:21 +0000 (16:53 -0400)
committerFrancis Giraldeau <francis.giraldeau@gmail.com>
Mon, 25 Jul 2016 19:21:29 +0000 (15:21 -0400)
Interprocessor interrupts (IPIs) are special types of interrupts by
which one processor will interrupt another in a multi-core system. They
are typically used for

* cache flushes
* shutdowns

They are not logged with standard events, but rather events looking like
"x86_irq_vectors_thermal_apic_exit".

This patch makes them register as IRQs (which they are) in the control
flow view and resources view.

Change-Id: I5380b6bc2d18f2ee98f7675eb1918794a78a71b3
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/77731
Reviewed-by: Hudson CI
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-by: Francis Giraldeau <francis.giraldeau@gmail.com>
Tested-by: Francis Giraldeau <francis.giraldeau@gmail.com>
analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/trace/IKernelAnalysisEventLayout.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIEntryHandler.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIExitHandler.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/trace/layout/Lttng27EventLayout.java

index 5dce2ea041cae02e6b35e9dc86eaaa6b5a3a7c64..577ece4e6fb8506ff90ddeb076a86109e5af59fe 100644 (file)
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 2.0.0.qualifier
+Bundle-Version: 2.1.0.qualifier
 Bundle-Localization: plugin
 Bundle-SymbolicName: org.eclipse.tracecompass.analysis.os.linux.core;singleton:=true
 Bundle-Activator: org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator
index 17e271d2007bdd7eb29a84bb4251b891063cea12..2b58f29686ceaf57c2c89b1361dd2dcbb9e69c67 100644 (file)
@@ -13,6 +13,7 @@
 package org.eclipse.tracecompass.analysis.os.linux.core.trace;
 
 import java.util.Collection;
+import java.util.Collections;
 
 import org.eclipse.jdt.annotation.Nullable;
 
@@ -219,7 +220,6 @@ public interface IKernelAnalysisEventLayout {
      */
     String eventSchedProcessWakeupNew();
 
-
     /**
      * Starting the high resolution timer
      * <p>
@@ -287,8 +287,8 @@ public interface IKernelAnalysisEventLayout {
     /**
      * The kernel just allocated a page of memory.
      * <p>
-     * In Linux, this typically means a user space application just got a page of
-     * ram.
+     * In Linux, this typically means a user space application just got a page
+     * of ram.
      *
      * @return the event name
      * @since 2.0
@@ -305,6 +305,46 @@ public interface IKernelAnalysisEventLayout {
      */
     String eventKmemPageFree();
 
+    /**
+     * <em>Interprocessor interrupts</em> (IPIs) are special types of interrupts by which
+     * one processor will interrupt another in a multi-core and multi-cpu system. They are
+     * typically used for
+     * <ol>
+     * <li>cache flushes</li>
+     * <li>shutdowns</li>
+     * <ol>
+     * They are not logged with standard events, but rather events looking like
+     * "x86_irq_vectors_thermal_apic_exit".
+     * <p>
+     * This event describes the entries into IPIs.
+     *
+     * @return the IPI list
+     * @since 2.1
+     */
+    default Collection<String> getIPIIrqVectorsEntries() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * <em>Interprocessor interrupts</em> (IPIs) are special types of interrupts by which
+     * one processor will interrupt another in a multi-core and multi-cpu system. They are
+     * typically used for
+     * <ol>
+     * <li>cache flushes</li>
+     * <li>shutdowns</li>
+     * <ol>
+     * They are not logged with standard events, but rather events looking like
+     * "x86_irq_vectors_thermal_apic_exit".
+     * <p>
+     * This event describes the exits into IPIs.
+     *
+     * @return the IPI list
+     * @since 2.1
+     */
+    default Collection<String> getIPIIrqVectorsExits() {
+        return Collections.emptyList();
+    }
+
     // ------------------------------------------------------------------------
     // Event field names
     // ------------------------------------------------------------------------
@@ -516,8 +556,8 @@ public interface IKernelAnalysisEventLayout {
     String fieldHRtimer();
 
     /**
-     * The field with the expires value. The expires field holds the expiry time.
-     * of the hrtimer.
+     * The field with the expires value. The expires field holds the expiry
+     * time. of the hrtimer.
      *
      * @return the name of the expires field
      * @since 2.0
@@ -525,8 +565,8 @@ public interface IKernelAnalysisEventLayout {
     String fieldHRtimerExpires();
 
     /**
-     * Gets the field name with the softexpires value. The softexpire value is the
-     * absolute earliest expiry time of the hrtimer.
+     * Gets the field name with the softexpires value. The softexpire value is
+     * the absolute earliest expiry time of the hrtimer.
      *
      * @return the name of the softexpires field
      * @since 2.0
@@ -707,4 +747,15 @@ public interface IKernelAnalysisEventLayout {
         return "diskname"; //$NON-NLS-1$
     }
 
+    /**
+     * The field with the IRQ number. This is used in IPI handlers (entry and
+     * exit).
+     *
+     * @return the name of the field with the IRQ number
+     * @since 2.1
+     */
+    default String fieldIPIVector() {
+        return "vector"; //$NON-NLS-1$
+    }
+
 }
index 1a391b98e66c68d11024fa289f8cfae3480cd08c..99d2250adfdf044783c9e33761063870c8a5fc57 100644 (file)
@@ -18,6 +18,8 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
 import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.IPIEntryHandler;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.IPIExitHandler;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.IrqEntryHandler;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.IrqExitHandler;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers.KernelEventHandler;
@@ -59,7 +61,7 @@ public class KernelStateProvider extends AbstractTmfStateProvider {
      * Version number of this state provider. Please bump this if you modify the
      * contents of the generated state history in some way.
      */
-    private static final int VERSION = 17;
+    private static final int VERSION = 18;
 
     // ------------------------------------------------------------------------
     // Fields
@@ -110,6 +112,12 @@ public class KernelStateProvider extends AbstractTmfStateProvider {
         builder.put(layout.eventSchedProcessFork(), new ProcessForkHandler(layout));
         builder.put(layout.eventSchedProcessExit(), new ProcessExitHandler(layout));
         builder.put(layout.eventSchedProcessFree(), new ProcessFreeHandler(layout));
+        for( String s : layout.getIPIIrqVectorsEntries()) {
+            builder.put(s, new IPIEntryHandler(layout));
+        }
+        for( String s : layout.getIPIIrqVectorsExits()) {
+            builder.put(s, new IPIExitHandler(layout));
+        }
 
         final String eventStatedumpProcessState = layout.eventStatedumpProcessState();
         if (eventStatedumpProcessState != null) {
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIEntryHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIEntryHandler.java
new file mode 100644 (file)
index 0000000..20a2ca2
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * 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.kernel.handlers;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+
+/**
+ * IPI Entry Handler
+ *
+ * @author Matthew Khouzam
+ */
+public class IPIEntryHandler extends KernelEventHandler {
+
+    /**
+     * Constructor
+     *
+     * @param layout
+     *            event layout
+     */
+    public IPIEntryHandler(IKernelAnalysisEventLayout layout) {
+        super(layout);
+    }
+
+    @Override
+    public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+
+        Integer cpu = KernelEventHandlerUtils.getCpu(event);
+        if (cpu == null) {
+            return;
+        }
+        Integer irqId = ((Long) event.getContent().getField(getLayout().fieldIPIVector()).getValue()).intValue();
+
+        /*
+         * Mark this IRQ as active in the resource tree. The state value = the
+         * CPU on which this IRQ is sitting
+         */
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString());
+
+        ITmfStateValue value = TmfStateValue.newValueInt(cpu.intValue());
+        long timestamp = KernelEventHandlerUtils.getTimestamp(event);
+        ss.modifyAttribute(timestamp, value, quark);
+
+        /* Change the status of the running process to interrupted */
+        quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss), Attributes.STATUS);
+        value = StateValues.PROCESS_STATUS_INTERRUPTED_VALUE;
+        ss.modifyAttribute(timestamp, value, quark);
+
+        /* Change the status of the CPU to interrupted */
+        quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getCurrentCPUNode(cpu, ss), Attributes.STATUS);
+        value = StateValues.CPU_STATUS_IRQ_VALUE;
+        ss.modifyAttribute(timestamp, value, quark);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIExitHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIExitHandler.java
new file mode 100644 (file)
index 0000000..373527d
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * 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.kernel.handlers;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+
+/**
+ * IPI Exit Handler
+ *
+ * @author Matthew Khouzam
+ */
+public class IPIExitHandler extends KernelEventHandler {
+
+    /**
+     * Constructor
+     *
+     * @param layout
+     *            event layout
+     */
+    public IPIExitHandler(IKernelAnalysisEventLayout layout) {
+        super(layout);
+    }
+
+    @Override
+    public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+        Integer cpu = KernelEventHandlerUtils.getCpu(event);
+        if (cpu == null) {
+            return;
+        }
+        int currentThreadNode = KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss);
+        Integer irqId = ((Long) event.getContent().getField(getLayout().fieldIPIVector()).getValue()).intValue();
+        /* Put this IRQ back to inactive in the resource tree */
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString());
+        TmfStateValue value = TmfStateValue.nullValue();
+        long timestamp = KernelEventHandlerUtils.getTimestamp(event);
+        ss.modifyAttribute(timestamp, value, quark);
+
+        /* Set the previous process back to running */
+        KernelEventHandlerUtils.setProcessToRunning(timestamp, currentThreadNode, ss);
+
+        /* Set the CPU status back to running or "idle" */
+        KernelEventHandlerUtils.cpuExitInterrupt(timestamp, cpu, ss);
+    }
+}
index 349e10c4b1055464bb6cba3ffd7a9fb5e3f2c350..1d307a0b36e03bb33582c61852cda5be4801659a 100644 (file)
@@ -14,6 +14,8 @@ package org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout;
 
 import java.util.Collection;
 
+import org.eclipse.jdt.annotation.NonNull;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -230,6 +232,16 @@ public class Lttng27EventLayout extends Lttng26EventLayout {
         return IPI_EXIT_SET;
     }
 
+    @Override
+    public @NonNull Collection<@NonNull String> getIPIIrqVectorsEntries() {
+        return getX86IrqVectorsEntry();
+    }
+
+    @Override
+    public @NonNull Collection<@NonNull String> getIPIIrqVectorsExits() {
+        return getX86IrqVectorsExit();
+    }
+
     // ------------------------------------------------------------------------
     // New field definitions in LTTng 2.7
     // ------------------------------------------------------------------------
This page took 0.030007 seconds and 5 git commands to generate.