From: Matthew Khouzam Date: Thu, 21 Jul 2016 20:53:21 +0000 (-0400) Subject: linux.core: Support IPIs in kernel analysis (Bug 498215) X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=051db42f11d1b51519595f65c3bc71958c23ae34;hp=97bee8e11d6cad5be2956bdb6702e20f19e3804d;p=deliverable%2Ftracecompass.git linux.core: Support IPIs in kernel analysis (Bug 498215) 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 Reviewed-on: https://git.eclipse.org/r/77731 Reviewed-by: Hudson CI Reviewed-by: Alexandre Montplaisir Reviewed-by: Francis Giraldeau Tested-by: Francis Giraldeau --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF index 5dce2ea041..577ece4e6f 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF @@ -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 diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/trace/IKernelAnalysisEventLayout.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/trace/IKernelAnalysisEventLayout.java index 17e271d200..2b58f29686 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/trace/IKernelAnalysisEventLayout.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/trace/IKernelAnalysisEventLayout.java @@ -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 *

@@ -287,8 +287,8 @@ public interface IKernelAnalysisEventLayout { /** * The kernel just allocated a page of memory. *

- * 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(); + /** + * Interprocessor interrupts (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 + *

    + *
  1. cache flushes
  2. + *
  3. shutdowns
  4. + *
      + * They are not logged with standard events, but rather events looking like + * "x86_irq_vectors_thermal_apic_exit". + *

      + * This event describes the entries into IPIs. + * + * @return the IPI list + * @since 2.1 + */ + default Collection getIPIIrqVectorsEntries() { + return Collections.emptyList(); + } + + /** + * Interprocessor interrupts (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 + *

        + *
      1. cache flushes
      2. + *
      3. shutdowns
      4. + *
          + * They are not logged with standard events, but rather events looking like + * "x86_irq_vectors_thermal_apic_exit". + *

          + * This event describes the exits into IPIs. + * + * @return the IPI list + * @since 2.1 + */ + default Collection 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$ + } + } diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java index 1a391b98e6..99d2250adf 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java @@ -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 index 0000000000..20a2ca2c8e --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIEntryHandler.java @@ -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 index 0000000000..373527de75 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IPIExitHandler.java @@ -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); + } +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/trace/layout/Lttng27EventLayout.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/trace/layout/Lttng27EventLayout.java index 349e10c4b1..1d307a0b36 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/trace/layout/Lttng27EventLayout.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core/src/org/eclipse/tracecompass/internal/lttng2/kernel/core/trace/layout/Lttng27EventLayout.java @@ -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 // ------------------------------------------------------------------------