LTTng: Introduce the virtual machine analysis analysis and core model
[deliverable/tracecompass.git] / org.eclipse.tracecompass.lttng2.kernel.core / src / org / eclipse / tracecompass / internal / lttng2 / kernel / core / analysis / vm / module / VirtualMachineCpuAnalysis.java
CommitLineData
4a74f111
MG
1/*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
3 *
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
8 *
9 * Contributors:
10 * Mohamad Gebai - Initial API and implementation
11 * Geneviève Bastien - Initial API and implementation
12 *******************************************************************************/
13
14package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
15
16import java.util.Comparator;
17import java.util.HashSet;
18import java.util.Set;
19
20import org.eclipse.core.runtime.IProgressMonitor;
21import org.eclipse.jdt.annotation.NonNull;
22import org.eclipse.jdt.annotation.Nullable;
23import org.eclipse.tracecompass.common.core.NonNullUtils;
24import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VcpuStateValues;
25import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes;
26import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelAnalysis;
27import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelThreadInformationProvider;
28import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
29import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
30import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
31import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
32import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
33import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval;
34import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
35import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
36import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
37import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
38import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
39import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
40import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
41import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
42import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
43import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperimentUtils;
44
45import com.google.common.collect.ImmutableSet;
46import com.google.common.collect.Multimap;
47import com.google.common.collect.TreeMultimap;
48
49/**
50 * Module for the virtual machine CPU analysis. It tracks the status of the
51 * virtual CPUs for each guest of the experiment.
52 *
53 * @author Mohamad Gebai
54 * @author Geneviève Bastien
55 */
56public class VirtualMachineCpuAnalysis extends TmfStateSystemAnalysisModule {
57
58 // TODO: Update with event layout when requirements are back */
59 static final Set<String> REQUIRED_EVENTS = NonNullUtils.checkNotNull(ImmutableSet.<String> of(
60 // LttngStrings.SCHED_SWITCH
61 ));
62
63 /* State value for a preempted virtual CPU */
64 private static final ITmfStateValue VCPU_PREEMPT_VALUE = TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT);
65
66 /**
67 * Constructor
68 */
69 public VirtualMachineCpuAnalysis() {
70 super();
71 }
72
73 @Override
74 protected ITmfStateProvider createStateProvider() {
75 ITmfTrace trace = getTrace();
76 if (!(trace instanceof TmfExperiment)) {
77 throw new IllegalStateException();
78 }
79 return new VirtualMachineStateProvider((TmfExperiment) trace);
80 }
81
82 @Override
83 protected @NonNull StateSystemBackendType getBackendType() {
84 return StateSystemBackendType.FULL;
85 }
86
87 @Override
88 public String getHelpText() {
89 return Messages.getMessage(Messages.VirtualMachineCPUAnalysis_Help);
90 }
91
92 @Override
93 protected Iterable<IAnalysisModule> getDependentAnalyses() {
94 Set<IAnalysisModule> modules = new HashSet<>();
95 /* Depends on the LTTng Kernel analysis modules */
96 for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
97 for (LttngKernelAnalysis module : TmfTraceUtils.getAnalysisModulesOfClass(trace, LttngKernelAnalysis.class)) {
98 modules.add(module);
99 }
100 }
101 return modules;
102 }
103
104 private static Multimap<Integer, ITmfStateInterval> createThreadMultimap() {
105
106 /*
107 * Create the multimap for threads with the appropriate comparator
108 * objects for keys and values
109 */
110 final Multimap<Integer, ITmfStateInterval> map = NonNullUtils.checkNotNull(TreeMultimap.<Integer, ITmfStateInterval> create(
111 new Comparator<Integer>() {
112 @Override
113 public int compare(@Nullable Integer arg0, @Nullable Integer arg1) {
114 /*
115 * Keys do not have to be sorted, just use natural
116 * sorting
117 */
118 if (arg0 == null || arg1 == null) {
119 return -1;
120 }
121 return arg0.compareTo(arg1);
122 }
123 }, new Comparator<ITmfStateInterval>() {
124 @Override
125 public int compare(@Nullable ITmfStateInterval arg0, @Nullable ITmfStateInterval arg1) {
126 if (arg0 == null || arg1 == null) {
127 return 0;
128 }
129 if (arg1.getStateValue() == VCPU_PREEMPT_VALUE && arg0.getStateValue() != VCPU_PREEMPT_VALUE) {
130 /*
131 * For VCPU_PREEMPT state values, the state has to
132 * be after any other state that it overlaps,
133 * because those intervals usually decorate the
134 * other intervals.
135 */
136 if (((Long) arg0.getEndTime()).compareTo(arg1.getStartTime()) < 0) {
137 return -1;
138 }
139 return ((Long) arg0.getStartTime()).compareTo(arg1.getEndTime());
140 }
141 /* Otherwise, we use ordering by start time */
142 return (((Long) arg0.getStartTime()).compareTo(arg1.getStartTime()));
143 }
144 }));
145 return map;
146 }
147
148 /**
149 * Get the status intervals for the threads from a virtual machine. Those
150 * intervals are correlated with the data from the virtual CPU's preemption
151 * status.
152 *
153 * This method uses the Linux Kernel Analysis data for the thread's status
154 * intervals.
155 *
156 * @param vmQuark
157 * The quark of the virtual machine
158 * @param start
159 * The start time of the period to get the intervals from
160 * @param end
161 * The end time of the period to get the intervals from
162 * @param resolution
163 * The resolution
164 * @param monitor
165 * A progress monitor for this task
166 * @return A map of status intervals for the machine's threads, including
167 * preempted intervals. Intervals from the thread status and the CPU
168 * preemption status overlap and are ordered such that CPU
169 * preemption intervals are after any interval they overlap with
170 */
171 public Multimap<Integer, ITmfStateInterval> getUpdatedThreadIntervals(int vmQuark, long start, long end, long resolution, IProgressMonitor monitor) {
172
173 final Multimap<Integer, ITmfStateInterval> map = createThreadMultimap();
174
175 ITmfStateSystem ss = getStateSystem();
176 if (ss == null) {
177 return map;
178 }
179 ITmfTrace trace = getTrace();
180 if (!(trace instanceof TmfExperiment)) {
181 return map;
182 }
183
184 String vmHostId = NonNullUtils.checkNotNull(ss.getAttributeName(vmQuark));
185 LttngKernelAnalysis kernelModule = TmfExperimentUtils.getAnalysisModuleOfClassForHost((TmfExperiment) trace, vmHostId, LttngKernelAnalysis.class);
186 if (kernelModule == null) {
187 return map;
188 }
189
190 /*
191 * Initialize the map with the original status intervals from the kernel
192 * module
193 */
194 for (Integer tid : LttngKernelThreadInformationProvider.getThreadIds(kernelModule)) {
195 if (tid == null) {
196 throw new IllegalStateException();
197 }
198 map.putAll(tid, LttngKernelThreadInformationProvider.getStatusIntervalsForThread(kernelModule, tid, start, end, resolution, monitor));
199 if (monitor.isCanceled()) {
200 return map;
201 }
202 }
203
204 try {
205 /* Correlate thread information with virtual CPU information */
206 for (Integer vcpuQuark : ss.getSubAttributes(vmQuark, false)) {
207 Long virtualCPU = Long.parseLong(ss.getAttributeName(vcpuQuark));
208 Integer statusQuark = ss.getQuarkRelative(vcpuQuark, VmAttributes.STATUS);
209
210 for (ITmfStateInterval cpuInterval : StateSystemUtils.queryHistoryRange(ss, statusQuark, start, end - 1, resolution, monitor)) {
211 ITmfStateValue stateValue = cpuInterval.getStateValue();
212 switch (stateValue.getType()) {
213 case INTEGER:
214 int value = stateValue.unboxInt();
215 /*
216 * If the current CPU is either preempted or in
217 * hypervisor mode, add preempted intervals to running
218 * processes
219 */
220 if ((value & (VcpuStateValues.VCPU_PREEMPT | VcpuStateValues.VCPU_VMM)) == 0) {
221 break;
222 }
223 Integer threadOnCpu = LttngKernelThreadInformationProvider.getThreadOnCpu(kernelModule, virtualCPU, cpuInterval.getStartTime());
224 if (threadOnCpu != null) {
225 map.put(threadOnCpu, new TmfStateInterval(cpuInterval.getStartTime(), cpuInterval.getEndTime(), threadOnCpu, VCPU_PREEMPT_VALUE));
226 }
227 break;
228 case DOUBLE:
229 case LONG:
230 case NULL:
231 case STRING:
232 default:
233 break;
234 }
235
236 }
237 }
238 } catch (AttributeNotFoundException | StateSystemDisposedException e) {
239 }
240 return NonNullUtils.checkNotNull(map);
241 }
242
243}
This page took 0.053623 seconds and 5 git commands to generate.