1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Mohamad Gebai - Initial API and implementation
11 * Geneviève Bastien - Initial API and implementation
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.vm
.module
;
16 import java
.util
.Comparator
;
17 import java
.util
.HashSet
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelAnalysisModule
;
23 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelThreadInformationProvider
;
24 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.vm
.VcpuStateValues
;
25 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.vm
.VmAttributes
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
31 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.TmfStateInterval
;
32 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
33 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModule
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.ITmfStateProvider
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfStateSystemAnalysisModule
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperiment
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperimentUtils
;
43 import com
.google
.common
.collect
.ImmutableSet
;
44 import com
.google
.common
.collect
.Multimap
;
45 import com
.google
.common
.collect
.TreeMultimap
;
48 * Module for the virtual machine CPU analysis. It tracks the status of the
49 * virtual CPUs for each guest of the experiment.
51 * @author Mohamad Gebai
52 * @author Geneviève Bastien
54 public class VirtualMachineCpuAnalysis
extends TmfStateSystemAnalysisModule
{
56 /** The ID of this analysis module */
57 public static final String ID
= "org.eclipse.tracecompass.lttng2.analysis.vm.core.VirtualMachineAnalysisModule"; //$NON-NLS-1$
59 // TODO: Update with event layout when requirements are back */
60 static final Set
<String
> REQUIRED_EVENTS
= ImmutableSet
.of(
61 // LttngStrings.SCHED_SWITCH
64 /* State value for a preempted virtual CPU */
65 private static final ITmfStateValue VCPU_PREEMPT_VALUE
= TmfStateValue
.newValueInt(VcpuStateValues
.VCPU_PREEMPT
);
70 public VirtualMachineCpuAnalysis() {
75 protected ITmfStateProvider
createStateProvider() {
76 ITmfTrace trace
= getTrace();
77 if (!(trace
instanceof TmfExperiment
)) {
78 throw new IllegalStateException();
80 return new VirtualMachineStateProvider((TmfExperiment
) trace
);
84 protected @NonNull StateSystemBackendType
getBackendType() {
85 return StateSystemBackendType
.FULL
;
89 public String
getHelpText() {
90 return Messages
.getMessage(Messages
.VirtualMachineCPUAnalysis_Help
);
94 protected Iterable
<IAnalysisModule
> getDependentAnalyses() {
95 Set
<IAnalysisModule
> modules
= new HashSet
<>();
96 /* Depends on the LTTng Kernel analysis modules */
97 for (ITmfTrace trace
: TmfTraceManager
.getTraceSet(getTrace())) {
98 for (KernelAnalysisModule module
: TmfTraceUtils
.getAnalysisModulesOfClass(trace
, KernelAnalysisModule
.class)) {
105 private static Multimap
<Integer
, ITmfStateInterval
> createThreadMultimap() {
108 * Create the multimap for threads with the appropriate comparator
109 * objects for keys and values
111 final Multimap
<Integer
, ITmfStateInterval
> map
= TreeMultimap
.create(
112 /* Key comparator. Keys do not have to be sorted, just use natural sorting*/
113 Comparator
.naturalOrder(),
115 /* Value comparator */
117 if (arg1
.getStateValue() == VCPU_PREEMPT_VALUE
&& arg0
.getStateValue() != VCPU_PREEMPT_VALUE
) {
119 * For VCPU_PREEMPT state values, the state has to be
120 * after any other state that it overlaps, because those
121 * intervals usually decorate the other intervals.
123 if (((Long
) arg0
.getEndTime()).compareTo(arg1
.getStartTime()) < 0) {
126 return ((Long
) arg0
.getStartTime()).compareTo(arg1
.getEndTime());
128 /* Otherwise, we use ordering by start time */
129 return (((Long
) arg0
.getStartTime()).compareTo(arg1
.getStartTime()));
135 * Get the status intervals for the threads from a virtual machine. Those
136 * intervals are correlated with the data from the virtual CPU's preemption
139 * This method uses the Linux Kernel Analysis data for the thread's status
143 * The quark of the virtual machine
145 * The start time of the period to get the intervals from
147 * The end time of the period to get the intervals from
151 * A progress monitor for this task
152 * @return A map of status intervals for the machine's threads, including
153 * preempted intervals. Intervals from the thread status and the CPU
154 * preemption status overlap and are ordered such that CPU
155 * preemption intervals are after any interval they overlap with
157 public Multimap
<Integer
, ITmfStateInterval
> getUpdatedThreadIntervals(int vmQuark
, long start
, long end
, long resolution
, IProgressMonitor monitor
) {
159 final Multimap
<Integer
, ITmfStateInterval
> map
= createThreadMultimap();
161 ITmfStateSystem ss
= getStateSystem();
165 ITmfTrace trace
= getTrace();
166 if (!(trace
instanceof TmfExperiment
)) {
170 String vmHostId
= ss
.getAttributeName(vmQuark
);
171 KernelAnalysisModule kernelModule
= TmfExperimentUtils
.getAnalysisModuleOfClassForHost((TmfExperiment
) trace
, vmHostId
, KernelAnalysisModule
.class);
172 if (kernelModule
== null) {
177 * Initialize the map with the original status intervals from the kernel
180 for (Integer tid
: KernelThreadInformationProvider
.getThreadIds(kernelModule
)) {
181 map
.putAll(tid
, KernelThreadInformationProvider
.getStatusIntervalsForThread(kernelModule
, tid
, start
, end
, resolution
, monitor
));
182 if (monitor
.isCanceled()) {
188 /* Correlate thread information with virtual CPU information */
189 for (Integer vcpuQuark
: ss
.getSubAttributes(vmQuark
, false)) {
190 Long virtualCPU
= Long
.parseLong(ss
.getAttributeName(vcpuQuark
));
191 Integer statusQuark
= ss
.getQuarkRelative(vcpuQuark
, VmAttributes
.STATUS
);
193 for (ITmfStateInterval cpuInterval
: StateSystemUtils
.queryHistoryRange(ss
, statusQuark
, start
, end
- 1, resolution
, monitor
)) {
194 ITmfStateValue stateValue
= cpuInterval
.getStateValue();
195 switch (stateValue
.getType()) {
197 int value
= stateValue
.unboxInt();
199 * If the current CPU is either preempted or in
200 * hypervisor mode, add preempted intervals to running
203 if ((value
& (VcpuStateValues
.VCPU_PREEMPT
| VcpuStateValues
.VCPU_VMM
)) == 0) {
206 Integer threadOnCpu
= KernelThreadInformationProvider
.getThreadOnCpu(kernelModule
, virtualCPU
, cpuInterval
.getStartTime());
207 if (threadOnCpu
!= null) {
208 map
.put(threadOnCpu
, new TmfStateInterval(cpuInterval
.getStartTime(), cpuInterval
.getEndTime(), threadOnCpu
, VCPU_PREEMPT_VALUE
));
221 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {