From: Matthew Khouzam Date: Mon, 1 Feb 2016 21:51:15 +0000 (-0500) Subject: linux: introduce execution contexts in resources view X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;ds=sidebyside;h=19ed65980a00b9d42a7ee8a64809c52ac76bca65;p=deliverable%2Ftracecompass.git linux: introduce execution contexts in resources view The original implementation made sense only one single core systems. An IRQ and softirq would block the whole system and not just a single core. This patch adds the notion of execution contexts to the interrupts. The interrupts are moved under the CPU to show the true execution stack. Then the model is a much truer representation of the kernel. In order to maintain aggregate information in the resources view (total IRQs and such), the notion of AggregateEntries and AggregateIterators are introduced. This allows better understanding of the current state of the system as the resources view now shows what the state of each processor is. Expect a _SLIGHT_ performance degradation during the building of the state system as an additional lookup is required for each interrupt event. This updates the state system model so the testvalues are updated and the generator is updated to work again. Starts to fix bugs: bug 381497 and bug 481855 Change-Id: I2f0f2093344f51caaf08500181cf90400a081f7c Signed-off-by: Matthew Khouzam Signed-off-by: Patrick Tasse Reviewed-on: https://git.eclipse.org/r/65609 Reviewed-by: Hudson CI --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/Attributes.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/Attributes.java index 520b1bb2d0..3324ea9e59 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/Attributes.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/Attributes.java @@ -30,11 +30,12 @@ public interface Attributes { /* First-level attributes */ String CPUS = "CPUs"; String THREADS = "Threads"; - String RESOURCES = "Resources"; /* Sub-attributes of the CPU nodes */ String CURRENT_THREAD = "Current_thread"; String STATUS = "Status"; + String SOFT_IRQS = "Soft_IRQs"; + String IRQS = "IRQs"; /* Sub-attributes of the Thread nodes */ String PPID = "PPID"; @@ -45,10 +46,6 @@ public interface Attributes { String PRIO = "Prio"; String SYSTEM_CALL = "System_call"; - /* Attributes under "Resources" */ - String IRQS = "IRQs"; - String SOFT_IRQS = "Soft_IRQs"; - /* Misc stuff */ String UNKNOWN = "Unknown"; } 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 279e0db21c..3783768660 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 @@ -44,10 +44,8 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import com.google.common.collect.ImmutableMap; /** - * This is the state change input plugin for TMF's state system which handles - * the LTTng 2.0 kernel traces in CTF format. - * - * It uses the reference handler defined in CTFKernelHandler.java. + * This is the state change input plugin for the state system which handles the + * kernel traces. * * @author Alexandre Montplaisir */ @@ -61,7 +59,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 = 11; + private static final int VERSION = 12; // ------------------------------------------------------------------------ // Fields diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqEntryHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqEntryHandler.java index d1897b7cd2..bcc6fa0459 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqEntryHandler.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqEntryHandler.java @@ -49,7 +49,7 @@ public class IrqEntryHandler extends KernelEventHandler { * 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(ss), irqId.toString()); + int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString()); ITmfStateValue value = TmfStateValue.newValueInt(cpu.intValue()); long timestamp = KernelEventHandlerUtils.getTimestamp(event); diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqExitHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqExitHandler.java index 81e7f024a7..9b2103e2bc 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqExitHandler.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqExitHandler.java @@ -36,13 +36,13 @@ public class IrqExitHandler extends KernelEventHandler { @Override public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException { Integer cpu = KernelEventHandlerUtils.getCpu(event); - if( cpu == null ) { + if (cpu == null) { return; } int currentThreadNode = KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss); Integer irqId = ((Long) event.getContent().getField(getLayout().fieldIrq()).getValue()).intValue(); /* Put this IRQ back to inactive in the resource tree */ - int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(ss), irqId.toString()); + int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString()); TmfStateValue value = TmfStateValue.nullValue(); long timestamp = KernelEventHandlerUtils.getTimestamp(event); 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/KernelEventHandlerUtils.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/KernelEventHandlerUtils.java index a6ab3f5d4b..fad83ac0c4 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/KernelEventHandlerUtils.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/KernelEventHandlerUtils.java @@ -30,7 +30,8 @@ import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; */ public final class KernelEventHandlerUtils { - private KernelEventHandlerUtils() {} + private KernelEventHandlerUtils() { + } /** * Get CPU @@ -63,7 +64,6 @@ public final class KernelEventHandlerUtils { return ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpuNumber.toString()); } - /** * Get the timestamp of the event * @@ -139,12 +139,14 @@ public final class KernelEventHandlerUtils { /** * Get the IRQs node * + * @param cpuNumber + * the cpu core * @param ss * the state system * @return the IRQ node quark */ - public static int getNodeIRQs(ITmfStateSystemBuilder ss) { - return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS); + public static int getNodeIRQs(int cpuNumber, ITmfStateSystemBuilder ss) { + return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.IRQS); } /** @@ -161,12 +163,14 @@ public final class KernelEventHandlerUtils { /** * Get the Soft IRQs node * + * @param cpuNumber + * the cpu core * @param ss * the state system * @return the Soft IRQ node quark */ - public static int getNodeSoftIRQs(ITmfStateSystemBuilder ss) { - return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS); + public static int getNodeSoftIRQs(int cpuNumber, ITmfStateSystemBuilder ss) { + return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.SOFT_IRQS); } /** diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqEntryHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqEntryHandler.java index 60dd3c2168..39e08ef416 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqEntryHandler.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqEntryHandler.java @@ -52,7 +52,7 @@ public class SoftIrqEntryHandler extends KernelEventHandler { * Mark this SoftIRQ as active in the resource tree. The state value = * the CPU on which this SoftIRQ is processed */ - int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString()); + int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString()); ITmfStateValue value = TmfStateValue.newValueInt(cpu.intValue()); 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/SoftIrqExitHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqExitHandler.java index f348b02076..110fe4d570 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqExitHandler.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqExitHandler.java @@ -44,7 +44,7 @@ public class SoftIrqExitHandler extends KernelEventHandler { Integer softIrqId = ((Long) event.getContent().getField(getLayout().fieldVec()).getValue()).intValue(); int currentThreadNode = KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss); /* Put this SoftIRQ back to inactive (= -1) in the resource tree */ - int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString()); + int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString()); ITmfStateValue value = TmfStateValue.nullValue(); long timestamp = KernelEventHandlerUtils.getTimestamp(event); diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqRaiseHandler.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqRaiseHandler.java index 3813ca0efc..6773c6491f 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqRaiseHandler.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqRaiseHandler.java @@ -26,7 +26,9 @@ public class SoftIrqRaiseHandler extends KernelEventHandler { /** * Constructor - * @param layout event layout + * + * @param layout + * event layout */ public SoftIrqRaiseHandler(IKernelAnalysisEventLayout layout) { super(layout); @@ -35,11 +37,14 @@ public class SoftIrqRaiseHandler extends KernelEventHandler { @Override public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException { Integer softIrqId = ((Long) event.getContent().getField(getLayout().fieldVec()).getValue()).intValue(); - + Integer cpu = KernelEventHandlerUtils.getCpu(event); + if (cpu == null) { + return; + } /* * Mark this SoftIRQ as *raised* in the resource tree. State value = -2 */ - int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString()); + int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString()); ITmfStateValue value = StateValues.SOFT_IRQ_RAISED_VALUE; ss.modifyAttribute(KernelEventHandlerUtils.getTimestamp(event), value, quark); } diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java new file mode 100644 index 0000000000..97b0ef0d74 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java @@ -0,0 +1,231 @@ +/******************************************************************************* + * 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.analysis.os.linux.ui.tests.view.resources; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.AggregateEventIterator; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; + +/** + * Test class to verify the main cases of the aggregate iterator + * + * @author Matthew Khouzam + * + */ +@NonNullByDefault +public class AggregateIteratorTest { + + /** + *
+     * ----------X---------
+     * 
+ */ + private final ITimeGraphEntry t1 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 10), + new TimeEvent(null, 10, 1, 1), + new NullTimeEvent(null, 11, 9))); + /** + *
+     * -----------X--------
+     * 
+ */ + private final ITimeGraphEntry t2 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 12), + new TimeEvent(null, 12, 1, 1), + new NullTimeEvent(null, 13, 7))); + /** + *
+     * --------X-----------
+     * 
+ */ + private final ITimeGraphEntry t3 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 9), + new TimeEvent(null, 9, 1, 1), + new NullTimeEvent(null, 10, 10))); + + /** + *
+     * --------XXX---------
+     * 
+ */ + private final ITimeGraphEntry t4 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 9), + new TimeEvent(null, 9, 3, 1), + new NullTimeEvent(null, 12, 8))); + + /** + *
+     * ----------XXX-------
+     * 
+ */ + private final ITimeGraphEntry t5 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 10), + new TimeEvent(null, 10, 3, 1), + new NullTimeEvent(null, 13, 7))); + + /** + *
+     * ----------XXX-------
+     * 
+ */ + private final ITimeGraphEntry t6 = new StubTimeGraphEntry(ImmutableList.of( + new NullTimeEvent(null, 0, 10), + new TimeEvent(null, 10, 3, 1), + new NullTimeEvent(null, 13, 7))); + + /** + *
+     * XXXXXXXXXXXXXXXXXXXX
+     * 
+ */ + private final ITimeGraphEntry t7 = new StubTimeGraphEntry(ImmutableList.of( + new TimeEvent(null, 0, 20, 1))); + + /** + * Test non-overlapping intervals + */ + @Test + public void testNoOverlap() { + List expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 1, 1), new NullTimeEvent(null, 11, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t1, t2, t3), COMPARATOR); + runTest(expected, fixture); + } + + /** + * Test intervals with 2 events that partially overlap + */ + @Test + public void testPartialOverlap() { + List expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 2, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t4, t5), COMPARATOR); + runTest(expected, fixture); + } + + /** + * Test two iterators that are identical, it will give the same result + */ + @Test + public void testFullOverlap() { + List expected = ImmutableList.of(new NullTimeEvent(null, 0, 10), new TimeEvent(null, 10, 3, 1), new NullTimeEvent(null, 13, 7)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t6, t5), COMPARATOR); + runTest(expected, fixture); + } + + /** + * Test two iterators that are identical, it will give the same result + */ + @Test + public void testSameStartOverlap() { + List expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 2, 1), new NullTimeEvent(null, 12, 8)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t3, t4), COMPARATOR); + runTest(expected, fixture); + } + + /** + * Test two iterators that are identical, it will give the same result + */ + @Test + public void testSameEndOverlap() { + List expected = ImmutableList.of(new NullTimeEvent(null, 0, 10), new TimeEvent(null, 10, 2, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t5, t2), COMPARATOR); + runTest(expected, fixture); + } + + /** + * Test two iterators where one only has one HUGE event + */ + @Test + public void testOverlapEnglobing() { + List expected = ImmutableList.of(new TimeEvent(null, 0, 10, 1), new TimeEvent(null, 10, 1, 1), new TimeEvent(null, 11, 9, 1)); + AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t1, t7), COMPARATOR); + runTest(expected, fixture); + } + + private static void runTest(List expected, AggregateEventIterator fixture) { + List results = new ArrayList<>(); + Iterators.addAll(results, fixture); + assertEquals(expected.size(), results.size()); + for (int i = 0; i < expected.size(); i++) { + final @NonNull TimeEvent actual = (@NonNull TimeEvent) results.get(i); + final @NonNull TimeEvent expected2 = (@NonNull TimeEvent) expected.get(i); + final @NonNull String name = Integer.toString(i); + assertEquals(name, expected2.getClass(), actual.getClass()); + assertEquals(name, expected2.getDuration(), actual.getDuration()); + assertEquals(name, expected2.getTime(), actual.getTime()); + assertEquals(name, expected2.getEntry(), actual.getEntry()); + assertEquals(name, expected2.getValue(), actual.getValue()); + } + } + + static class StubTimeGraphEntry extends TimeGraphEntry { + + private final Iterable<@NonNull ITimeEvent> fEvents; + + public StubTimeGraphEntry(Iterable events) { + super("stub", Long.MIN_VALUE, Long.MAX_VALUE); + fEvents = events; + } + + @Override + public boolean hasTimeEvents() { + return !Iterables.isEmpty(fEvents); + } + + // for a stub, not worth making it work. + @SuppressWarnings("null") + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { + return fEvents.iterator(); + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { + if (startTime != Long.MIN_VALUE || stopTime != Long.MAX_VALUE) { + throw new IllegalArgumentException("startTime must be Long.MIN_VALUE, stopTime must be Long.MAX_VALUE"); + } + return getTimeEventsIterator(); + } + + } + + /** + * Same as in AggregateResourcesEntry but we want a snapshot and to not + * update the tests at every new mode of resources view + */ + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(ITimeEvent o1, ITimeEvent o2) { + // largest value + return Integer.compare(getValue(o2), getValue(o1)); + } + + private int getValue(ITimeEvent element) { + return (element instanceof TimeEvent) ? ((TimeEvent) element).getValue() : Integer.MIN_VALUE; + } + }; + +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java new file mode 100644 index 0000000000..6ecb4f9a34 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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.analysis.os.linux.ui.views.resources; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * Aggregate TimeEvent iterator, this takes multiple streams of events and + * merges them into one single time event stream + * + * @author Matthew Khouzam + * @since 2.0 + */ +public class AggregateEventIterator implements Iterator<@NonNull ITimeEvent> { + + private final List<@NonNull CachingIterator> fIterators = new ArrayList<>(); + + private final Comparator fComparator; + + /** + * Constructor + * + * @param contributors + * the entries to aggregate + * @param comparator + * The comparator to sort time events + */ + public AggregateEventIterator(@NonNull List contributors, Comparator comparator) { + this(contributors, Long.MIN_VALUE, Long.MAX_VALUE, 1, comparator); + } + + /** + * Constructor with a time range + * + * @param contributors + * the entries to aggregate + * @param startTime + * start time in nanoseconds + * @param endTime + * stop time in nanoseconds + * @param duration + * duration of one pixel in nanoseconds + * @param comparator + * The comparator to sort time events + */ + public AggregateEventIterator(@NonNull List contributors, long startTime, long endTime, long duration, Comparator comparator) { + fComparator = comparator; + contributors.forEach(timeGraphEntry -> { + final Iterator<@NonNull ITimeEvent> timeEventsIterator = timeGraphEntry.getTimeEventsIterator(startTime, endTime, duration); + if (timeEventsIterator != null) { + CachingIterator iterator = new CachingIterator(timeEventsIterator, comparator); + if (iterator.hasNext()) { + fIterators.add(iterator); + } + } + }); + } + + @Override + public boolean hasNext() { + return !fIterators.isEmpty(); + } + + @Override + public @NonNull ITimeEvent next() { + + final List<@NonNull CachingIterator> iterators = fIterators; + if (iterators.isEmpty()) { + throw new NoSuchElementException("Aggregate iterator is empty"); //$NON-NLS-1$ + } + + ITimeEvent winner = iterators.get(0).peek(); + long trimTime = winner.getTime() + winner.getDuration(); + for (int i = 1; i < iterators.size(); i++) { + CachingIterator iterator = iterators.get(i); + ITimeEvent candidate = iterator.peek(); + if (candidate.getTime() < winner.getTime()) { + trimTime = Math.min(winner.getTime(), candidate.getTime() + candidate.getDuration()); + winner = candidate; + } else if (candidate.getTime() == winner.getTime()) { + trimTime = Math.min(trimTime, candidate.getTime() + candidate.getDuration()); + if (fComparator.compare(candidate, winner) < 0) { + winner = candidate; + } + } else { + trimTime = Math.min(trimTime, candidate.getTime()); + } + } + + /* Trim the next event before the trim time, if necessary. */ + final ITimeEvent next = (trimTime < (winner.getDuration() + winner.getTime())) ? winner.splitBefore(trimTime) : winner; + + /* Trim all remaining events after the trim time, if necessary. */ + Iterator iteratorIterator = iterators.iterator(); + while (iteratorIterator.hasNext()) { + CachingIterator iterator = iteratorIterator.next(); + iterator.trim(trimTime); + /* Remove empty iterators from the list */ + if (!iterator.hasNext()) { + iteratorIterator.remove(); + } + } + + return checkNotNull(next); + } +} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java new file mode 100644 index 0000000000..eeafe6ec4a --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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.analysis.os.linux.ui.views.resources; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; + +/** + * Internal entry of the aggregate kind, it is one without a state system value, + * it uses other entries and aggregates their values. + * + * @author Matthew Khouzam + */ +class AggregateResourcesEntry extends ResourcesEntry { + + private final @NonNull List fContributors = new ArrayList<>(); + + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(ITimeEvent o1, ITimeEvent o2) { + // largest value + return Integer.compare(getValue(o2), getValue(o1)); + } + + private int getValue(ITimeEvent element) { + return (element instanceof TimeEvent) ? ((TimeEvent) element).getValue() : Integer.MIN_VALUE; + } + }; + + /** + * AggregateResourcesEntry Constructor + * + * @param trace + * the parent trace + * @param startTime + * the start time + * @param endTime + * the end time + * @param type + * the type + * @param id + * the id + */ + public AggregateResourcesEntry(@NonNull ITmfTrace trace, + long startTime, long endTime, Type type, int id) { + super(ITmfStateSystem.INVALID_ATTRIBUTE, trace, startTime, endTime, type, id); + } + + @Override + public void addEvent(ITimeEvent event) { + } + + @Override + public void addZoomedEvent(ITimeEvent event) { + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { + return new AggregateEventIterator(fContributors, COMPARATOR); + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { + return new AggregateEventIterator(fContributors, startTime, stopTime, visibleDuration, COMPARATOR); + } + + public void addContributor(ITimeGraphEntry entry) { + fContributors.add(entry); + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java new file mode 100644 index 0000000000..46c4b6b1d5 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * 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.analysis.os.linux.ui.views.resources; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; + +/** + * Caching iterator of time events with a couple extras. + *
    + *
  • peek() allows reading the head without removing it
  • + *
  • trim() allows removing a bit of the first event
  • + *
+ * + * @author Matthew Khouzam + */ +class CachingIterator implements Iterator<@NonNull ITimeEvent>, Comparable { + private ITimeEvent fEvent; + private @NonNull Iterator<@NonNull ? extends ITimeEvent> fIterator; + private final Comparator fComparator; + + public CachingIterator(@NonNull Iterator<@NonNull ? extends ITimeEvent> iterator, Comparator comparator) { + fIterator = iterator; + fComparator = comparator; + fEvent = iterator.hasNext() ? iterator.next() : null; + } + + @Override + public ITimeEvent next() { + ITimeEvent retVal = fEvent; + fEvent = fIterator.hasNext() ? fIterator.next() : null; + if (retVal == null) { + throw new NoSuchElementException("Iterator is empty"); //$NON-NLS-1$ + } + return retVal; + } + + @Override + public boolean hasNext() { + return fEvent != null; + } + + /** + * Retrieves, but does not remove, the next element of this iterator, or + * returns {@code null} if this iterator does not have a next. + * + * @return the next element of the iterator + */ + public ITimeEvent peek() { + return fEvent; + } + + @Override + public int compareTo(CachingIterator o) { + final ITimeEvent myEvent = peek(); + final ITimeEvent otherEvent = o.peek(); + return fComparator.compare(myEvent, otherEvent); + } + + /** + * Trims the next element in the iterator to be after a cut-off time. + * + * @param time + * the cut-off time + * @return true if there was a trim + */ + public boolean trim(long time) { + if (time <= fEvent.getTime()) { + return false; + } + if (time < fEvent.getTime() + fEvent.getDuration()) { + fEvent = fEvent.splitAfter(time); + return true; + } + fEvent = fIterator.hasNext() ? fIterator.next() : null; + return true; + } + +} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java index ad1647bb2b..0aad6c0b4e 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java @@ -189,7 +189,7 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider try { List fullState = ss.queryFullState(event.getTime()); - List irqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$ + List irqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.IRQS, "*"); //$NON-NLS-1$ for (int irqQuark : irqQuarks) { if (fullState.get(irqQuark).getStateValue().unboxInt() == cpu) { @@ -212,7 +212,7 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider try { List fullState = ss.queryFullState(event.getTime()); - List softIrqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + List softIrqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ for (int softIrqQuark : softIrqQuarks) { if (fullState.get(softIrqQuark).getStateValue().unboxInt() == cpu) { diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java index 7e0acd49a4..2782db4681 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes; @@ -68,6 +70,7 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView { setFilterColumns(FILTER_COLUMN_NAMES); setFilterLabelProvider(new ResourcesFilterLabelProvider()); setEntryComparator(new ResourcesEntryComparator()); + setAutoExpandLevel(1); } private static class ResourcesEntryComparator implements Comparator { @@ -143,7 +146,8 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView { return; } long end = ssq.getCurrentEndTime(); - if (start == end && !complete) { // when complete execute one last time regardless of end time + if (start == end && !complete) { + // when complete execute one last time regardless of end time continue; } long endTime = end + 1; @@ -156,44 +160,8 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView { } else { traceEntry.updateEndTime(endTime); } - List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ - for (Integer cpuQuark : cpuQuarks) { - int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark)); - ResourcesEntry entry = entryMap.get(cpuQuark); - if (entry == null) { - entry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu); - entryMap.put(cpuQuark, entry); - traceEntry.addChild(entry); - } else { - entry.updateEndTime(endTime); - } - } - List irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$ - for (Integer irqQuark : irqQuarks) { - int irq = Integer.parseInt(ssq.getAttributeName(irqQuark)); - ResourcesEntry entry = entryMap.get(irqQuark); - if (entry == null) { - entry = new ResourcesEntry(irqQuark, trace, startTime, endTime, Type.IRQ, irq); - entryMap.put(irqQuark, entry); - traceEntry.addChild(entry); - } else { - entry.updateEndTime(endTime); - } - } - List softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ - for (Integer softIrqQuark : softIrqQuarks) { - int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark)); - ResourcesEntry entry = entryMap.get(softIrqQuark); - if (entry == null) { - entry = new ResourcesEntry(softIrqQuark, trace, startTime, endTime, Type.SOFT_IRQ, softIrq); - entryMap.put(softIrqQuark, entry); - traceEntry.addChild(entry); - } else { - entry.updateEndTime(endTime); - } - } - + createCpuEntriesWithQuark(trace, ssq, entryMap, traceEntry, startTime, endTime, cpuQuarks); if (parentTrace.equals(getTrace())) { refresh(); } @@ -205,111 +173,220 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView { @Override public void handle(List> fullStates, List prevFullState) { for (ITimeGraphEntry child : traceEntryChildren) { - if (monitor.isCanceled()) { + if (!populateEventsRecursively(fullStates, prevFullState, child).isOK()) { return; } - if (child instanceof TimeGraphEntry) { - TimeGraphEntry entry = (TimeGraphEntry) child; - List eventList = getEventList(entry, ssq, fullStates, prevFullState, monitor); - if (eventList != null) { - for (ITimeEvent event : eventList) { - entry.addEvent(event); - } + } + } + + private IStatus populateEventsRecursively(@NonNull List> fullStates, @Nullable List prevFullState, ITimeGraphEntry entry) { + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + if (entry instanceof TimeGraphEntry) { + TimeGraphEntry timeGraphEntry = (TimeGraphEntry) entry; + List eventList = getEventList(timeGraphEntry, ssq, fullStates, prevFullState, monitor); + if (eventList != null) { + for (ITimeEvent event : eventList) { + timeGraphEntry.addEvent(event); } } } + for (ITimeGraphEntry child : entry.getChildren()) { + IStatus status = populateEventsRecursively(fullStates, prevFullState, child); + if (!status.isOK()) { + return status; + } + } + return Status.OK_STATUS; } }); start = end; } + + } + + private static void createCpuEntriesWithQuark(@NonNull ITmfTrace trace, final ITmfStateSystem ssq, Map entryMap, TimeGraphEntry traceEntry, long startTime, long endTime, List cpuQuarks) { + for (Integer cpuQuark : cpuQuarks) { + final @NonNull String cpuName = ssq.getAttributeName(cpuQuark); + int cpu = Integer.parseInt(cpuName); + ResourcesEntry cpuEntry = entryMap.get(cpuQuark); + if (cpuEntry == null) { + cpuEntry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu); + entryMap.put(cpuQuark, cpuEntry); + traceEntry.addChild(cpuEntry); + } else { + cpuEntry.updateEndTime(endTime); + } + List irqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.IRQS, "*"); //$NON-NLS-1$ + createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, irqQuarks, Type.IRQ); + List softIrqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, softIrqQuarks, Type.SOFT_IRQ); + } + } + + /** + * Create and add execution contexts to a cpu entry. Also creates an + * aggregate entry in the root trace entry. The execution context is + * basically what the cpu is doing in its execution stack. It can be in an + * IRQ, Soft IRQ. MCEs, NMIs, Userland and Kernel execution is not yet + * supported. + * + * @param trace + * the trace + * @param ssq + * the state system + * @param entryMap + * the entry map + * @param startTime + * the start time in nanoseconds + * @param endTime + * the end time in nanoseconds + * @param traceEntry + * the trace timegraph entry + * @param cpuEntry + * the cpu timegraph entry (the entry under the trace entry + * @param childrenQuarks + * the quarks to add to cpu entry + * @param type + * the type of entry being added + */ + private static void createCpuInterruptEntryWithQuark(@NonNull ITmfTrace trace, + final ITmfStateSystem ssq, Map entryMap, + long startTime, long endTime, + TimeGraphEntry traceEntry, ResourcesEntry cpuEntry, + List childrenQuarks, Type type) { + for (Integer quark : childrenQuarks) { + final @NonNull String resourceName = ssq.getAttributeName(quark); + int resourceId = Integer.parseInt(resourceName); + ResourcesEntry interruptEntry = entryMap.get(quark); + if (interruptEntry == null) { + interruptEntry = new ResourcesEntry(quark, trace, startTime, endTime, type, resourceId); + entryMap.put(quark, interruptEntry); + cpuEntry.addChild(interruptEntry); + boolean found = false; + for (ITimeGraphEntry rootElem : traceEntry.getChildren()) { + if (rootElem instanceof AggregateResourcesEntry) { + AggregateResourcesEntry aggregateInterruptEntry = (AggregateResourcesEntry) rootElem; + if (aggregateInterruptEntry.getId() == resourceId && aggregateInterruptEntry.getType().equals(type)) { + found = true; + aggregateInterruptEntry.addContributor(interruptEntry); + break; + } + } + } + if (!found) { + AggregateResourcesEntry aggregateInterruptEntry = new AggregateResourcesEntry(trace, startTime, endTime, type, resourceId); + aggregateInterruptEntry.addContributor(interruptEntry); + traceEntry.addChild(aggregateInterruptEntry); + } + } else { + interruptEntry.updateEndTime(endTime); + } + } } @Override protected @Nullable List getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq, @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { ResourcesEntry resourcesEntry = (ResourcesEntry) entry; - List eventList = null; int quark = resourcesEntry.getQuark(); if (resourcesEntry.getType().equals(Type.CPU)) { - int statusQuark; - try { - statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS); - } catch (AttributeNotFoundException e) { - /* - * The sub-attribute "status" is not available. May happen - * if the trace does not have sched_switch events enabled. - */ + return createCpuEventsList(entry, ssq, fullStates, prevFullState, monitor, quark); + } else if ((resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) && (quark >= 0)) { + return createIrqEventsList(entry, fullStates, prevFullState, monitor, quark); + } + + return null; + } + + private static List createCpuEventsList(TimeGraphEntry entry, ITmfStateSystem ssq, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { + List eventList; + int statusQuark; + try { + statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS); + } catch (AttributeNotFoundException e) { + /* + * The sub-attribute "status" is not available. May happen if the + * trace does not have sched_switch events enabled. + */ + return null; + } + eventList = new ArrayList<>(fullStates.size()); + ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark); + long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); + long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; + for (List fullState : fullStates) { + if (monitor.isCanceled()) { return null; } - eventList = new ArrayList<>(fullStates.size()); - ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark); - long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); - long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; - for (List fullState : fullStates) { - if (monitor.isCanceled()) { - return null; - } - if (statusQuark >= fullState.size()) { - /* No information on this CPU (yet?), skip it for now */ - continue; - } - ITmfStateInterval statusInterval = fullState.get(statusQuark); - int status = statusInterval.getStateValue().unboxInt(); - long time = statusInterval.getStartTime(); - long duration = statusInterval.getEndTime() - time + 1; - if (time == lastStartTime) { - continue; - } - if (!statusInterval.getStateValue().isNull()) { - if (lastEndTime != time && lastEndTime != -1) { - eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); - } - eventList.add(new TimeEvent(entry, time, duration, status)); - } else { - eventList.add(new NullTimeEvent(entry, time, duration)); - } - lastStartTime = time; - lastEndTime = time + duration; + if (statusQuark >= fullState.size()) { + /* No information on this CPU (yet?), skip it for now */ + continue; } - } else if (resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) { - eventList = new ArrayList<>(fullStates.size()); - ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark); - long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); - long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; - boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull(); - for (List fullState : fullStates) { - if (monitor.isCanceled()) { - return null; - } - if (quark >= fullState.size()) { - /* No information on this IRQ (yet?), skip it for now */ - continue; - } - ITmfStateInterval irqInterval = fullState.get(quark); - long time = irqInterval.getStartTime(); - long duration = irqInterval.getEndTime() - time + 1; - if (time == lastStartTime) { - continue; - } - if (!irqInterval.getStateValue().isNull()) { - int cpu = irqInterval.getStateValue().unboxInt(); - eventList.add(new TimeEvent(entry, time, duration, cpu)); - lastIsNull = false; - } else { - if (lastEndTime != time && lastIsNull) { - /* This is a special case where we want to show IRQ_ACTIVE state but we don't know the CPU (it is between two null samples) */ - eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1)); - } - eventList.add(new NullTimeEvent(entry, time, duration)); - lastIsNull = true; + ITmfStateInterval statusInterval = fullState.get(statusQuark); + int status = statusInterval.getStateValue().unboxInt(); + long time = statusInterval.getStartTime(); + long duration = statusInterval.getEndTime() - time + 1; + if (time == lastStartTime) { + continue; + } + if (!statusInterval.getStateValue().isNull()) { + if (lastEndTime != time && lastEndTime != -1) { + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); } - lastStartTime = time; - lastEndTime = time + duration; + eventList.add(new TimeEvent(entry, time, duration, status)); + } else { + eventList.add(new NullTimeEvent(entry, time, duration)); } + lastStartTime = time; + lastEndTime = time + duration; } + return eventList; + } + private static List createIrqEventsList(TimeGraphEntry entry, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { + List eventList; + eventList = new ArrayList<>(fullStates.size()); + ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark); + long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); + long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; + boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull(); + for (List fullState : fullStates) { + if (monitor.isCanceled()) { + return null; + } + if (quark >= fullState.size()) { + /* No information on this IRQ (yet?), skip it for now */ + continue; + } + ITmfStateInterval irqInterval = fullState.get(quark); + long time = irqInterval.getStartTime(); + long duration = irqInterval.getEndTime() - time + 1; + if (time == lastStartTime) { + continue; + } + if (!irqInterval.getStateValue().isNull()) { + int cpu = irqInterval.getStateValue().unboxInt(); + eventList.add(new TimeEvent(entry, time, duration, cpu)); + lastIsNull = false; + } else { + if (lastEndTime != time && lastIsNull) { + /* + * This is a special case where we want to show IRQ_ACTIVE + * state but we don't know the CPU (it is between two null + * samples) + */ + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1)); + } + eventList.add(new NullTimeEvent(entry, time, duration)); + lastIsNull = true; + } + lastStartTime = time; + lastEndTime = time + duration; + } return eventList; } diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/GenerateTestValues.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/GenerateTestValues.java index 17c21c845e..bd7b1f054b 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/GenerateTestValues.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/GenerateTestValues.java @@ -26,13 +26,14 @@ import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTraceUtils; import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace; +import org.junit.Test; /** * Small program to regenerate the values used in "TestValues.java" from the * current LTTng-kernel state provider. * - * It will write its output the a file called 'TestValues.java' in your - * temporary files directory. + * It will write its output the a file called 'TestValues.java' in + * your temporary files directory. * * @author Alexandre Montplaisir */ @@ -42,6 +43,17 @@ public class GenerateTestValues { private static final long targetTimestamp = 18670067372290L + 1331649577946812237L; private static final String INDENT = " "; + /** + * Test wrapper to run main properly + * + * @throws Exception + * we're messing with exception + */ + @Test + public void test() throws Exception { + main(null); + } + /** * Run the program * diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java index 0f869c1bee..d9e2218c02 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java @@ -163,7 +163,7 @@ public abstract class StateSystemTest { assertNotNull(ss); try { - int quark = ss.getQuarkAbsolute(Attributes.RESOURCES, Attributes.IRQS, "1"); + int quark = ss.getQuarkAbsolute(Attributes.CPUS, Integer.toString(0), Attributes.IRQS, "1"); long ts1 = ss.getStartTime(); /* start of the trace */ long ts2 = startTime + 20L * NANOSECS_PER_SEC; /* invalid, but ignored */ diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/TestValues.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/TestValues.java index 1875b5cb4f..72b125af38 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/TestValues.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/TestValues.java @@ -24,7 +24,8 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; * @author Alexandre Montplaisir */ interface TestValues { - int size = 1032; + + int size = 1036; long[] startTimes = { 1331668247314038062L, @@ -62,12 +63,13 @@ interface TestValues { 1331668248014184526L, 1331668248014130616L, 1331668247314038062L, - 1331668247314038062L, - 1331668248011125682L, + 1331668248011090056L, 1331668247314038062L, 1331668247931793142L, 1331668247930941981L, - 1331668247959041965L, + 1331668247314038062L, + 1331668248011125682L, + 1331668247959024716L, 1331668248011129576L, 1331668247314038062L, 1331668247314038062L, @@ -110,6 +112,7 @@ interface TestValues { 1331668247999327778L, 1331668247318631139L, 1331668247314038062L, + 1331668247959041965L, 1331668247960265258L, 1331668247314038062L, 1331668247903884233L, @@ -135,6 +138,7 @@ interface TestValues { 1331668247314038062L, 1331668247330548245L, 1331668247314038062L, + 1331668247919182446L, 1331668247340039213L, 1331668247340083580L, 1331668247966976915L, @@ -264,6 +268,7 @@ interface TestValues { 1331668247926367737L, 1331668247423543945L, 1331668247314038062L, + 1331668247314038062L, 1331668247619316825L, 1331668247619491008L, 1331668247314038062L, @@ -1097,12 +1102,13 @@ interface TestValues { 1331668248014548923L, 1331668248014188534L, 1331668259054285979L, - 1331668259054285979L, 1331668248015040151L, 1331668259054285979L, 1331668248482983146L, 1331668248482983146L, - 1331668248015041609L, + 1331668259054285979L, + 1331668248015170799L, + 1331668248015172434L, 1331668248015176320L, 1331668259054285979L, 1331668259054285979L, @@ -1145,6 +1151,7 @@ interface TestValues { 1331668248016645047L, 1331668252843104826L, 1331668259054285979L, + 1331668248015041609L, 1331668248486545657L, 1331668259054285979L, 1331668248502954816L, @@ -1170,6 +1177,7 @@ interface TestValues { 1331668259054285979L, 1331668259054285979L, 1331668259054285979L, + 1331668248019005964L, 1331668257323835062L, 1331668257323879563L, 1331668248021867385L, @@ -1299,6 +1307,7 @@ interface TestValues { 1331668248424394073L, 1331668259054285979L, 1331668259054285979L, + 1331668259054285979L, 1331668248140683324L, 1331668248140686546L, 1331668259054285979L, @@ -2134,7 +2143,6 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), TmfStateValue.nullValue(), - TmfStateValue.nullValue(), TmfStateValue.newValueInt(1), TmfStateValue.newValueInt(20), TmfStateValue.nullValue(), @@ -2146,6 +2154,8 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), TmfStateValue.nullValue(), + TmfStateValue.nullValue(), + TmfStateValue.nullValue(), TmfStateValue.newValueString("sys_poll"), TmfStateValue.newValueString("lttng-consumerd"), TmfStateValue.nullValue(), @@ -2182,6 +2192,7 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), TmfStateValue.nullValue(), + TmfStateValue.nullValue(), TmfStateValue.newValueInt(1), TmfStateValue.newValueInt(20), TmfStateValue.newValueString("sys_poll"), @@ -2209,6 +2220,7 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), TmfStateValue.nullValue(), + TmfStateValue.nullValue(), TmfStateValue.newValueInt(1), TmfStateValue.newValueInt(20), TmfStateValue.nullValue(), @@ -2337,6 +2349,7 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), TmfStateValue.nullValue(), + TmfStateValue.nullValue(), TmfStateValue.newValueInt(1), TmfStateValue.newValueInt(20), TmfStateValue.newValueString("sys_poll"), @@ -3130,6 +3143,5 @@ interface TestValues { TmfStateValue.nullValue(), TmfStateValue.nullValue(), }; - }