os.linux: Re-organize the KernelAnalysisModule
[deliverable/tracecompass.git] / org.eclipse.tracecompass.lttng2.kernel.core / src / org / eclipse / tracecompass / internal / lttng2 / kernel / core / analysis / vm / module / VirtualMachineCpuAnalysis.java
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 É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
14 package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module;
15
16 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
18 import java.util.Comparator;
19 import java.util.HashSet;
20 import java.util.Set;
21
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.KernelAnalysisModule;
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;
46
47 import com.google.common.collect.ImmutableSet;
48 import com.google.common.collect.Multimap;
49 import com.google.common.collect.TreeMultimap;
50
51 /**
52 * Module for the virtual machine CPU analysis. It tracks the status of the
53 * virtual CPUs for each guest of the experiment.
54 *
55 * @author Mohamad Gebai
56 * @author Geneviève Bastien
57 */
58 public class VirtualMachineCpuAnalysis extends TmfStateSystemAnalysisModule {
59
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
63 ));
64
65 /* State value for a preempted virtual CPU */
66 private static final ITmfStateValue VCPU_PREEMPT_VALUE = TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT);
67
68 /**
69 * Constructor
70 */
71 public VirtualMachineCpuAnalysis() {
72 super();
73 }
74
75 @Override
76 protected ITmfStateProvider createStateProvider() {
77 ITmfTrace trace = getTrace();
78 if (!(trace instanceof TmfExperiment)) {
79 throw new IllegalStateException();
80 }
81 return new VirtualMachineStateProvider((TmfExperiment) trace);
82 }
83
84 @Override
85 protected @NonNull StateSystemBackendType getBackendType() {
86 return StateSystemBackendType.FULL;
87 }
88
89 @Override
90 public String getHelpText() {
91 return Messages.getMessage(Messages.VirtualMachineCPUAnalysis_Help);
92 }
93
94 @Override
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 (KernelAnalysisModule module : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) {
101 modules.add(module);
102 }
103 }
104 return modules;
105 }
106
107 private static Multimap<Integer, ITmfStateInterval> createThreadMultimap() {
108
109 /*
110 * Create the multimap for threads with the appropriate comparator
111 * objects for keys and values
112 */
113 final Multimap<Integer, ITmfStateInterval> map = NonNullUtils.checkNotNull(TreeMultimap.<Integer, ITmfStateInterval> create(
114 new Comparator<Integer>() {
115 @Override
116 public int compare(@Nullable Integer arg0, @Nullable Integer arg1) {
117 /*
118 * Keys do not have to be sorted, just use natural
119 * sorting
120 */
121 if (arg0 == null || arg1 == null) {
122 return -1;
123 }
124 return arg0.compareTo(arg1);
125 }
126 }, new Comparator<ITmfStateInterval>() {
127 @Override
128 public int compare(@Nullable ITmfStateInterval arg0, @Nullable ITmfStateInterval arg1) {
129 if (arg0 == null || arg1 == null) {
130 return 0;
131 }
132 if (arg1.getStateValue() == VCPU_PREEMPT_VALUE && arg0.getStateValue() != VCPU_PREEMPT_VALUE) {
133 /*
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
137 * other intervals.
138 */
139 if (((Long) arg0.getEndTime()).compareTo(arg1.getStartTime()) < 0) {
140 return -1;
141 }
142 return ((Long) arg0.getStartTime()).compareTo(arg1.getEndTime());
143 }
144 /* Otherwise, we use ordering by start time */
145 return (((Long) arg0.getStartTime()).compareTo(arg1.getStartTime()));
146 }
147 }));
148 return map;
149 }
150
151 /**
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
154 * status.
155 *
156 * This method uses the Linux Kernel Analysis data for the thread's status
157 * intervals.
158 *
159 * @param vmQuark
160 * The quark of the virtual machine
161 * @param start
162 * The start time of the period to get the intervals from
163 * @param end
164 * The end time of the period to get the intervals from
165 * @param resolution
166 * The resolution
167 * @param monitor
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
173 */
174 public Multimap<Integer, ITmfStateInterval> getUpdatedThreadIntervals(int vmQuark, long start, long end, long resolution, IProgressMonitor monitor) {
175
176 final Multimap<Integer, ITmfStateInterval> map = createThreadMultimap();
177
178 ITmfStateSystem ss = getStateSystem();
179 if (ss == null) {
180 return map;
181 }
182 ITmfTrace trace = getTrace();
183 if (!(trace instanceof TmfExperiment)) {
184 return map;
185 }
186
187 String vmHostId = NonNullUtils.checkNotNull(ss.getAttributeName(vmQuark));
188 KernelAnalysisModule kernelModule = TmfExperimentUtils.getAnalysisModuleOfClassForHost((TmfExperiment) trace, vmHostId, KernelAnalysisModule.class);
189 if (kernelModule == null) {
190 return map;
191 }
192
193 /*
194 * Initialize the map with the original status intervals from the kernel
195 * module
196 */
197 for (Integer tid : KernelThreadInformationProvider.getThreadIds(kernelModule)) {
198 if (tid == null) {
199 throw new IllegalStateException();
200 }
201 map.putAll(tid, KernelThreadInformationProvider.getStatusIntervalsForThread(kernelModule, tid, start, end, resolution, monitor));
202 if (monitor.isCanceled()) {
203 return map;
204 }
205 }
206
207 try {
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);
212
213 for (ITmfStateInterval cpuInterval : StateSystemUtils.queryHistoryRange(ss, statusQuark, start, end - 1, resolution, monitor)) {
214 ITmfStateValue stateValue = cpuInterval.getStateValue();
215 switch (stateValue.getType()) {
216 case INTEGER:
217 int value = stateValue.unboxInt();
218 /*
219 * If the current CPU is either preempted or in
220 * hypervisor mode, add preempted intervals to running
221 * processes
222 */
223 if ((value & (VcpuStateValues.VCPU_PREEMPT | VcpuStateValues.VCPU_VMM)) == 0) {
224 break;
225 }
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));
229 }
230 break;
231 case DOUBLE:
232 case LONG:
233 case NULL:
234 case STRING:
235 default:
236 break;
237 }
238
239 }
240 }
241 } catch (AttributeNotFoundException | StateSystemDisposedException e) {
242 }
243 return NonNullUtils.checkNotNull(map);
244 }
245
246 }
This page took 0.037573 seconds and 5 git commands to generate.