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 static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import java
.util
.Comparator
;
19 import java
.util
.HashSet
;
22 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
23 import org
.eclipse
.jdt
.annotation
.NonNull
;
24 import org
.eclipse
.jdt
.annotation
.Nullable
;
25 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelanalysis
.KernelAnalysis
;
26 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelanalysis
.KernelThreadInformationProvider
;
27 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
28 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.vm
.VcpuStateValues
;
29 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.vm
.VmAttributes
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
31 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
32 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
33 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
34 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
35 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.TmfStateInterval
;
36 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
37 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModule
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.ITmfStateProvider
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfStateSystemAnalysisModule
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperiment
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperimentUtils
;
47 import com
.google
.common
.collect
.ImmutableSet
;
48 import com
.google
.common
.collect
.Multimap
;
49 import com
.google
.common
.collect
.TreeMultimap
;
52 * Module for the virtual machine CPU analysis. It tracks the status of the
53 * virtual CPUs for each guest of the experiment.
55 * @author Mohamad Gebai
56 * @author Geneviève Bastien
58 public class VirtualMachineCpuAnalysis
extends TmfStateSystemAnalysisModule
{
60 // TODO: Update with event layout when requirements are back */
61 static final Set
<String
> REQUIRED_EVENTS
= NonNullUtils
.checkNotNull(ImmutableSet
.<String
> of(
62 // LttngStrings.SCHED_SWITCH
65 /* State value for a preempted virtual CPU */
66 private static final ITmfStateValue VCPU_PREEMPT_VALUE
= TmfStateValue
.newValueInt(VcpuStateValues
.VCPU_PREEMPT
);
71 public VirtualMachineCpuAnalysis() {
76 protected ITmfStateProvider
createStateProvider() {
77 ITmfTrace trace
= getTrace();
78 if (!(trace
instanceof TmfExperiment
)) {
79 throw new IllegalStateException();
81 return new VirtualMachineStateProvider((TmfExperiment
) trace
);
85 protected @NonNull StateSystemBackendType
getBackendType() {
86 return StateSystemBackendType
.FULL
;
90 public String
getHelpText() {
91 return Messages
.getMessage(Messages
.VirtualMachineCPUAnalysis_Help
);
95 protected Iterable
<IAnalysisModule
> getDependentAnalyses() {
96 Set
<IAnalysisModule
> modules
= new HashSet
<>();
97 /* Depends on the LTTng Kernel analysis modules */
98 for (ITmfTrace trace
: TmfTraceManager
.getTraceSet(getTrace())) {
99 trace
= checkNotNull(trace
);
100 for (KernelAnalysis module
: TmfTraceUtils
.getAnalysisModulesOfClass(trace
, KernelAnalysis
.class)) {
107 private static Multimap
<Integer
, ITmfStateInterval
> createThreadMultimap() {
110 * Create the multimap for threads with the appropriate comparator
111 * objects for keys and values
113 final Multimap
<Integer
, ITmfStateInterval
> map
= NonNullUtils
.checkNotNull(TreeMultimap
.<Integer
, ITmfStateInterval
> create(
114 new Comparator
<Integer
>() {
116 public int compare(@Nullable Integer arg0
, @Nullable Integer arg1
) {
118 * Keys do not have to be sorted, just use natural
121 if (arg0
== null || arg1
== null) {
124 return arg0
.compareTo(arg1
);
126 }, new Comparator
<ITmfStateInterval
>() {
128 public int compare(@Nullable ITmfStateInterval arg0
, @Nullable ITmfStateInterval arg1
) {
129 if (arg0
== null || arg1
== null) {
132 if (arg1
.getStateValue() == VCPU_PREEMPT_VALUE
&& arg0
.getStateValue() != VCPU_PREEMPT_VALUE
) {
134 * For VCPU_PREEMPT state values, the state has to
135 * be after any other state that it overlaps,
136 * because those intervals usually decorate the
139 if (((Long
) arg0
.getEndTime()).compareTo(arg1
.getStartTime()) < 0) {
142 return ((Long
) arg0
.getStartTime()).compareTo(arg1
.getEndTime());
144 /* Otherwise, we use ordering by start time */
145 return (((Long
) arg0
.getStartTime()).compareTo(arg1
.getStartTime()));
152 * Get the status intervals for the threads from a virtual machine. Those
153 * intervals are correlated with the data from the virtual CPU's preemption
156 * This method uses the Linux Kernel Analysis data for the thread's status
160 * The quark of the virtual machine
162 * The start time of the period to get the intervals from
164 * The end time of the period to get the intervals from
168 * A progress monitor for this task
169 * @return A map of status intervals for the machine's threads, including
170 * preempted intervals. Intervals from the thread status and the CPU
171 * preemption status overlap and are ordered such that CPU
172 * preemption intervals are after any interval they overlap with
174 public Multimap
<Integer
, ITmfStateInterval
> getUpdatedThreadIntervals(int vmQuark
, long start
, long end
, long resolution
, IProgressMonitor monitor
) {
176 final Multimap
<Integer
, ITmfStateInterval
> map
= createThreadMultimap();
178 ITmfStateSystem ss
= getStateSystem();
182 ITmfTrace trace
= getTrace();
183 if (!(trace
instanceof TmfExperiment
)) {
187 String vmHostId
= NonNullUtils
.checkNotNull(ss
.getAttributeName(vmQuark
));
188 KernelAnalysis kernelModule
= TmfExperimentUtils
.getAnalysisModuleOfClassForHost((TmfExperiment
) trace
, vmHostId
, KernelAnalysis
.class);
189 if (kernelModule
== null) {
194 * Initialize the map with the original status intervals from the kernel
197 for (Integer tid
: KernelThreadInformationProvider
.getThreadIds(kernelModule
)) {
199 throw new IllegalStateException();
201 map
.putAll(tid
, KernelThreadInformationProvider
.getStatusIntervalsForThread(kernelModule
, tid
, start
, end
, resolution
, monitor
));
202 if (monitor
.isCanceled()) {
208 /* Correlate thread information with virtual CPU information */
209 for (Integer vcpuQuark
: ss
.getSubAttributes(vmQuark
, false)) {
210 Long virtualCPU
= Long
.parseLong(ss
.getAttributeName(vcpuQuark
));
211 Integer statusQuark
= ss
.getQuarkRelative(vcpuQuark
, VmAttributes
.STATUS
);
213 for (ITmfStateInterval cpuInterval
: StateSystemUtils
.queryHistoryRange(ss
, statusQuark
, start
, end
- 1, resolution
, monitor
)) {
214 ITmfStateValue stateValue
= cpuInterval
.getStateValue();
215 switch (stateValue
.getType()) {
217 int value
= stateValue
.unboxInt();
219 * If the current CPU is either preempted or in
220 * hypervisor mode, add preempted intervals to running
223 if ((value
& (VcpuStateValues
.VCPU_PREEMPT
| VcpuStateValues
.VCPU_VMM
)) == 0) {
226 Integer threadOnCpu
= KernelThreadInformationProvider
.getThreadOnCpu(kernelModule
, virtualCPU
, cpuInterval
.getStartTime());
227 if (threadOnCpu
!= null) {
228 map
.put(threadOnCpu
, new TmfStateInterval(cpuInterval
.getStartTime(), cpuInterval
.getEndTime(), threadOnCpu
, VCPU_PREEMPT_VALUE
));
241 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
243 return NonNullUtils
.checkNotNull(map
);