import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect;
import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.LinuxTestCase;
import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.kernel.KernelAnalysisTestFactory;
+import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
/* Make sure the Kernel analysis has run */
((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null));
IAnalysisModule module = null;
- for (IAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) {
+ for (IAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, TidAnalysisModule.class)) {
module = mod;
}
assertNotNull(module);
fTrace.dispose();
}
- private void resolveNextEvent(ITmfContext context, Integer tid) {
+ private Integer resolveNextEvent(ITmfContext context) {
ITmfTrace trace = fTrace;
ITmfEvent event = trace.getNext(context);
assertNotNull(event);
-
- Object tidObj = TmfTraceUtils.resolveEventAspectOfClassForEvent(trace, KernelTidAspect.class, event);
- if (tid == null) {
- assertNull(tidObj);
- } else {
- assertNotNull(tidObj);
- assertEquals(tid, tidObj);
- }
+ return (Integer) TmfTraceUtils.resolveEventAspectOfClassForEvent(trace, KernelTidAspect.class, event);
}
/**
public void testResolveTidAspect() {
ITmfContext context = fTrace.seekEvent(0L);
- resolveNextEvent(context, null);
- resolveNextEvent(context, null);
- resolveNextEvent(context, null);
- resolveNextEvent(context, 11);
- resolveNextEvent(context, null);
- resolveNextEvent(context, null);
- resolveNextEvent(context, 20);
- resolveNextEvent(context, 20);
- resolveNextEvent(context, 21);
- resolveNextEvent(context, 11);
- resolveNextEvent(context, 30);
- resolveNextEvent(context, 21);
- resolveNextEvent(context, 20);
+ List<Integer> expected = new ArrayList<>();
+ expected.add(null);
+ expected.add(null);
+ expected.add(null);
+ expected.add(11);
+ expected.add(null);
+ expected.add(null);
+ expected.add(20);
+ expected.add(20);
+ expected.add(21);
+ expected.add(11);
+ expected.add(30);
+ expected.add(21);
+ expected.add(20);
+ List<Integer> tids = new ArrayList<>();
+
+ for (int i = 0; i < expected.size(); i++) {
+ tids.add(resolveNextEvent(context));
+ }
+ assertEquals(expected, tids);
}
}
package org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.trace;
import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect;
import org.eclipse.tracecompass.analysis.os.linux.core.event.aspect.ThreadPriorityAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
org.eclipse.tracecompass.analysis.os.linux.core.latency,
org.eclipse.tracecompass.analysis.os.linux.core.model,
org.eclipse.tracecompass.analysis.os.linux.core.signals,
+ org.eclipse.tracecompass.analysis.os.linux.core.tid,
org.eclipse.tracecompass.analysis.os.linux.core.trace,
org.eclipse.tracecompass.internal.analysis.os.linux.core;x-internal:=true,
org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests",
analysis.contextswitch = Context switch
analysis.kernelmemory = Kernel memory usage
analysis.io = Input/Output
+analysis.tid = Active Thread
automatic="false"
id="org.eclipse.tracecompass.analysis.os.linux.latency.syscall"
name="%analysis.latency">
- <tracetype
+ <tracetype
applies="true"
class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
</tracetype>
- </module>
+ </module>
<module
analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.contextswitch.KernelContextSwitchAnalysis"
id="org.eclipse.tracecompass.analysis.os.linux.contextswitch"
analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule"
id="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemory"
name="%analysis.kernelmemory">
- <tracetype
+ <tracetype
+ applies="true"
+ class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
+ </tracetype>
+ </module>
+ <module
+ analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule"
+ automatic="true"
+ icon="icons/threads.png"
+ id="org.eclipse.tracecompass.analysis.os.linux.kernel.tid"
+ name="%analysis.tid">
+ <tracetype
applies="true"
class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
</tracetype>
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.analysis.os.linux.core.event.aspect.LinuxTidAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule;
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;
}
/* Find the analysis module for the trace */
- KernelAnalysisModule analysis = TmfTraceUtils.getAnalysisModuleOfClass(event.getTrace(),
- KernelAnalysisModule.class, KernelAnalysisModule.ID);
+ TidAnalysisModule analysis = TmfTraceUtils.getAnalysisModuleOfClass(event.getTrace(),
+ TidAnalysisModule.class, TidAnalysisModule.ID);
if (analysis == null) {
return null;
}
- Integer tid = KernelThreadInformationProvider.getThreadOnCpu(
- analysis, cpu, event.getTimestamp().getValue());
- if (tid != null) {
- return tid;
- }
- return null;
+ return analysis.getThreadOnCpuAtTime(cpu, event.getTimestamp().toNanos());
}
}
--- /dev/null
+/*******************************************************************************
+ * 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.core.tid;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.jdt.annotation.NonNull;
+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.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
+import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+
+/**
+ * Active TID state provider, this only does one thing: figure out the active
+ * TID on any given CPU. This state provider is designed to do one thing and do
+ * it fast.
+ *
+ * Note: this state provider exists as a way to accelerate the TID aspect, but
+ * also to start splitting up the kernel analysis into smaller sections.
+ *
+ * Note 2: this is deliberately only package visible.
+ *
+ * @author Matthew Khouzam
+ */
+class ActiveTidStateProvider extends AbstractTmfStateProvider {
+
+ private static final @NonNull String PROVIDER_ID = "activeTidAnalysis.provider"; //$NON-NLS-1$
+ private static final int VERSION = 0;
+
+ private final Map<Integer, Integer> fCpuNumToQuark = new TreeMap<>();
+ private final @NonNull String fSchedSwitch;
+ private final @NonNull String fNextTid;
+ private final @NonNull IKernelAnalysisEventLayout fLayout;
+
+ public ActiveTidStateProvider(@NonNull ITmfTrace trace, @NonNull IKernelAnalysisEventLayout layout) {
+ super(trace, PROVIDER_ID);
+ fSchedSwitch = layout.eventSchedSwitch();
+ fNextTid = layout.fieldNextTid();
+ fLayout = layout;
+ }
+
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
+ @Override
+ public @NonNull ITmfStateProvider getNewInstance() {
+ return new ActiveTidStateProvider(getTrace(), fLayout);
+ }
+
+ @Override
+ protected void eventHandle(@NonNull ITmfEvent event) {
+ Integer cpu = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event);
+ if (cpu == null) {
+ return;
+ }
+ if (!event.getName().equals(fSchedSwitch)) {
+ return;
+ }
+ ITmfStateSystemBuilder ssb = getStateSystemBuilder();
+ if (ssb == null) {
+ return;
+ }
+ try {
+ Integer cpuQuark = fCpuNumToQuark.get(cpu);
+ if (cpuQuark == null) {
+ String cpuAttributeName = NonNullUtils.nullToEmptyString(cpu);
+ cpuQuark = ssb.getQuarkAbsoluteAndAdd(cpuAttributeName);
+ fCpuNumToQuark.put(cpu, cpuQuark);
+ }
+ int nextTid = ((Long) event.getContent().getField(fNextTid).getValue()).intValue();
+ final TmfStateValue value = TmfStateValue.newValueInt(nextTid);
+ ssb.modifyAttribute(event.getTimestamp().toNanos(), value, cpuQuark);
+ } catch (StateValueTypeException | AttributeNotFoundException e) {
+ Activator.getDefault().logError(NonNullUtils.nullToEmptyString(e.getMessage()), e);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * 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.core.tid;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisRequirement;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * Active tid analysis module, this only does one thing: figure out the active
+ * tid on any given cpu. This analysis should be approx 10x faster than the full
+ * {@link KernelAnalysisModule}.
+ *
+ * Note: this module exists as a way to accelerate the TID aspect, but also to
+ * start splitting up the kernel analysis into smaller sections.
+ *
+ * @author Matthew Khouzam
+ * @since 2.0
+ */
+public class TidAnalysisModule extends TmfStateSystemAnalysisModule {
+
+ /** The ID of this analysis module */
+ public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.kernel.tid"; //$NON-NLS-1$
+
+ /** The requirements as an immutable set */
+ private static final @NonNull Set<@NonNull TmfAnalysisRequirement> REQUIREMENTS = Collections.EMPTY_SET;
+
+ @Override
+ public @NonNull Iterable<@NonNull TmfAnalysisRequirement> getAnalysisRequirements() {
+ return REQUIREMENTS;
+ }
+
+ @Override
+ protected @NonNull ITmfStateProvider createStateProvider() {
+ ITmfTrace trace = checkNotNull(getTrace());
+ IKernelAnalysisEventLayout layout = (trace instanceof IKernelTrace) ? ((IKernelTrace) trace).getKernelEventLayout() : IKernelAnalysisEventLayout.DEFAULT_LAYOUT;
+ return new ActiveTidStateProvider(trace, layout);
+ }
+
+ /**
+ * Gets the current thread ID on a given CPU for a given time
+ *
+ * @param cpu
+ * the CPU
+ * @param time
+ * the time in nanoseconds
+ * @return the current TID at the time on the CPU or {@code null} if not
+ * known
+ */
+ public @Nullable Integer getThreadOnCpuAtTime(int cpu, long time) {
+ ITmfStateSystem stateSystem = getStateSystem();
+ if (stateSystem == null) {
+ return null;
+ }
+
+ Integer tid = null;
+ try {
+ int cpuQuark = stateSystem.getQuarkAbsolute(Integer.toString(cpu));
+ ITmfStateValue value = stateSystem.querySingleState(time, cpuQuark).getStateValue();
+ if (value.getType().equals(Type.INTEGER)) {
+ tid = value.unboxInt();
+ }
+ } catch (AttributeNotFoundException | StateSystemDisposedException e) {
+ Activator.getDefault().logError(NonNullUtils.nullToEmptyString(e.getMessage()), e);
+ }
+ return tid;
+ }
+
+ /**
+ * Gets the CPU a thread is running on for a given time <br>
+ * Note: this is not designed to be fast, only convenient
+ *
+ * @param tid
+ * the tid
+ * @param time
+ * the time in nanoseconds
+ * @return the current CPU at the time for a TID or {@code null} if not
+ * available
+ */
+ public @Nullable Integer getCpuForTidAtTime(int tid, long time) {
+ ITmfStateSystem stateSystem = getStateSystem();
+ if (stateSystem == null) {
+ return null;
+ }
+
+ try {
+ for (ITmfStateInterval interval : stateSystem.queryFullState(time)) {
+ if (tid == interval.getStateValue().unboxInt()) {
+ return Integer.parseInt(stateSystem.getAttributeName(interval.getAttribute()));
+ }
+ }
+ } catch (StateSystemDisposedException e) {
+ Activator.getDefault().logError(NonNullUtils.nullToEmptyString(e.getMessage()), e);
+ }
+ return null;
+ }
+}