analysis: let the soft irq raised state appear in the Resources view
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / internal / analysis / os / linux / ui / views / resources / ResourcesPresentationProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, É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 * Patrick Tasse - Initial API and implementation
11 * Geneviève Bastien - Move code to provide base classes for time graph view
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources;
15
16 import java.util.LinkedHashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.graphics.Color;
22 import org.eclipse.swt.graphics.GC;
23 import org.eclipse.swt.graphics.RGB;
24 import org.eclipse.swt.graphics.Rectangle;
25 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
26 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
27 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
28 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
29 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
30 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
31 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
32 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesEntry.Type;
33 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
34 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
35 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
36 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
37 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
38 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
39 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
40 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
41 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
42 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
43 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
44 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
45 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
46 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
47 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
48 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.ITmfTimeGraphDrawingHelper;
49 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
50 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
51 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
52
53 /**
54 * Presentation provider for the Resource view, based on the generic TMF
55 * presentation provider.
56 *
57 * @author Patrick Tasse
58 */
59 public class ResourcesPresentationProvider extends TimeGraphPresentationProvider {
60
61 private long fLastThreadId = -1;
62 private Color fColorWhite;
63 private Color fColorGray;
64 private Integer fAverageCharWidth;
65
66 private enum State {
67 IDLE (new RGB(200, 200, 200)),
68 USERMODE (new RGB( 0, 200, 0)),
69 SYSCALL (new RGB( 0, 0, 200)),
70 IRQ (new RGB(200, 0, 100)),
71 SOFT_IRQ (new RGB(200, 150, 100)),
72 IRQ_ACTIVE (new RGB(200, 0, 100)),
73 SOFT_IRQ_RAISED (new RGB(200, 200, 0)),
74 SOFT_IRQ_ACTIVE (new RGB(200, 150, 100));
75
76 public final RGB rgb;
77
78 private State(RGB rgb) {
79 this.rgb = rgb;
80 }
81 }
82
83 /**
84 * Default constructor
85 */
86 public ResourcesPresentationProvider() {
87 super();
88 }
89
90 private static State[] getStateValues() {
91 return State.values();
92 }
93
94 private static State getEventState(TimeEvent event) {
95 if (event.hasValue()) {
96 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
97 int value = event.getValue();
98
99 if (entry.getType() == Type.CPU) {
100 if (value == StateValues.CPU_STATUS_IDLE) {
101 return State.IDLE;
102 } else if (value == StateValues.CPU_STATUS_RUN_USERMODE) {
103 return State.USERMODE;
104 } else if (value == StateValues.CPU_STATUS_RUN_SYSCALL) {
105 return State.SYSCALL;
106 } else if (value == StateValues.CPU_STATUS_IRQ) {
107 return State.IRQ;
108 } else if (value == StateValues.CPU_STATUS_SOFTIRQ) {
109 return State.SOFT_IRQ;
110 } else if (value == StateValues.CPU_STATUS_SOFT_IRQ_RAISED) {
111 return State.SOFT_IRQ_RAISED;
112 }
113 } else if (entry.getType() == Type.IRQ) {
114 return State.IRQ_ACTIVE;
115 } else if (entry.getType() == Type.SOFT_IRQ) {
116 if (value == StateValues.CPU_STATUS_SOFT_IRQ_RAISED) {
117 return State.SOFT_IRQ_RAISED;
118 }
119 return State.SOFT_IRQ_ACTIVE;
120 }
121 }
122 return null;
123 }
124
125 @Override
126 public int getStateTableIndex(ITimeEvent event) {
127 State state = getEventState((TimeEvent) event);
128 if (state != null) {
129 return state.ordinal();
130 }
131 if (event instanceof NullTimeEvent) {
132 return INVISIBLE;
133 }
134 return TRANSPARENT;
135 }
136
137 @Override
138 public StateItem[] getStateTable() {
139 State[] states = getStateValues();
140 StateItem[] stateTable = new StateItem[states.length];
141 for (int i = 0; i < stateTable.length; i++) {
142 State state = states[i];
143 stateTable[i] = new StateItem(state.rgb, state.toString());
144 }
145 return stateTable;
146 }
147
148 @Override
149 public String getEventName(ITimeEvent event) {
150 State state = getEventState((TimeEvent) event);
151 if (state != null) {
152 return state.toString();
153 }
154 if (event instanceof NullTimeEvent) {
155 return null;
156 }
157 return Messages.ResourcesView_multipleStates;
158 }
159
160 @Override
161 public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) {
162
163 Map<String, String> retMap = new LinkedHashMap<>();
164 if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
165
166 TimeEvent tcEvent = (TimeEvent) event;
167 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
168
169 if (tcEvent.hasValue()) {
170 ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
171 if (ss == null) {
172 return retMap;
173 }
174 // Check for IRQ or Soft_IRQ type
175 if (entry.getType().equals(Type.IRQ) || entry.getType().equals(Type.SOFT_IRQ)) {
176
177 // Get CPU of IRQ or SoftIRQ and provide it for the tooltip display
178 int cpu = tcEvent.getValue();
179 if (cpu >= 0) {
180 retMap.put(Messages.ResourcesView_attributeCpuName, String.valueOf(cpu));
181 }
182 }
183
184 // Check for type CPU
185 else if (entry.getType().equals(Type.CPU)) {
186 int status = tcEvent.getValue();
187
188 if (status == StateValues.CPU_STATUS_IRQ) {
189 // In IRQ state get the IRQ that caused the interruption
190 int cpu = entry.getId();
191
192 try {
193 List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
194 List<Integer> irqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.IRQS, "*"); //$NON-NLS-1$
195
196 for (int irqQuark : irqQuarks) {
197 ITmfStateInterval value = fullState.get(irqQuark);
198 if (!value.getStateValue().isNull()) {
199 String irq = ss.getAttributeName(irqQuark);
200 retMap.put(Messages.ResourcesView_attributeIrqName, irq);
201 break;
202 }
203 }
204 } catch (TimeRangeException | StateValueTypeException e) {
205 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
206 } catch (StateSystemDisposedException e) {
207 /* Ignored */
208 }
209 } else if (status == StateValues.CPU_STATUS_SOFTIRQ) {
210 // In SOFT_IRQ state get the SOFT_IRQ that caused the interruption
211 int cpu = entry.getId();
212
213 try {
214 List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
215 List<Integer> softIrqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
216
217 for (int softIrqQuark : softIrqQuarks) {
218 ITmfStateInterval value = fullState.get(softIrqQuark);
219 if (!value.getStateValue().isNull()) {
220 String softIrq = ss.getAttributeName(softIrqQuark);
221 retMap.put(Messages.ResourcesView_attributeSoftIrqName, softIrq);
222 break;
223 }
224 }
225 } catch (TimeRangeException | StateValueTypeException e) {
226 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
227 } catch (StateSystemDisposedException e) {
228 /* Ignored */
229 }
230 } else if (status == StateValues.CPU_STATUS_RUN_USERMODE || status == StateValues.CPU_STATUS_RUN_SYSCALL) {
231 // In running state get the current tid
232
233 try {
234 retMap.put(Messages.ResourcesView_attributeHoverTime, Utils.formatTime(hoverTime, TimeFormat.CALENDAR, Resolution.NANOSEC));
235 int cpuQuark = entry.getQuark();
236 int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
237 ITmfStateInterval interval = ss.querySingleState(hoverTime, currentThreadQuark);
238 if (!interval.getStateValue().isNull()) {
239 ITmfStateValue value = interval.getStateValue();
240 int currentThreadId = value.unboxInt();
241 retMap.put(Messages.ResourcesView_attributeTidName, Integer.toString(currentThreadId));
242 int execNameQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME);
243 interval = ss.querySingleState(hoverTime, execNameQuark);
244 if (!interval.getStateValue().isNull()) {
245 value = interval.getStateValue();
246 retMap.put(Messages.ResourcesView_attributeProcessName, value.unboxStr());
247 }
248 if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
249 int syscallQuark = ss.optQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL);
250 if (syscallQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
251 return retMap;
252 }
253 interval = ss.querySingleState(hoverTime, syscallQuark);
254 if (!interval.getStateValue().isNull()) {
255 value = interval.getStateValue();
256 retMap.put(Messages.ResourcesView_attributeSyscallName, value.unboxStr());
257 }
258 }
259 }
260 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
261 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
262 } catch (StateSystemDisposedException e) {
263 /* Ignored */
264 }
265 }
266 }
267 }
268 }
269
270 return retMap;
271 }
272
273 @Override
274 public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
275 if (fColorGray == null) {
276 fColorGray = gc.getDevice().getSystemColor(SWT.COLOR_GRAY);
277 }
278 if (fColorWhite == null) {
279 fColorWhite = gc.getDevice().getSystemColor(SWT.COLOR_WHITE);
280 }
281 if (fAverageCharWidth == null) {
282 fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth();
283 }
284
285 ITmfTimeGraphDrawingHelper drawingHelper = getDrawingHelper();
286 if (bounds.width <= fAverageCharWidth) {
287 return;
288 }
289
290 if (!(event instanceof TimeEvent)) {
291 return;
292 }
293 TimeEvent tcEvent = (TimeEvent) event;
294 if (!tcEvent.hasValue()) {
295 return;
296 }
297
298 ResourcesEntry entry = (ResourcesEntry) event.getEntry();
299 if (!entry.getType().equals(Type.CPU)) {
300 return;
301 }
302
303 int status = tcEvent.getValue();
304 if (status != StateValues.CPU_STATUS_RUN_USERMODE && status != StateValues.CPU_STATUS_RUN_SYSCALL) {
305 return;
306 }
307
308 ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
309 if (ss == null) {
310 return;
311 }
312 long time = event.getTime();
313 try {
314 while (time < event.getTime() + event.getDuration()) {
315 int cpuQuark = entry.getQuark();
316 int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
317 ITmfStateInterval tidInterval = ss.querySingleState(time, currentThreadQuark);
318 long startTime = Math.max(tidInterval.getStartTime(), event.getTime());
319 int x = Math.max(drawingHelper.getXForTime(startTime), bounds.x);
320 if (x >= bounds.x + bounds.width) {
321 break;
322 }
323 if (!tidInterval.getStateValue().isNull()) {
324 ITmfStateValue value = tidInterval.getStateValue();
325 int currentThreadId = value.unboxInt();
326 long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration());
327 int xForEndTime = drawingHelper.getXForTime(endTime);
328 if (xForEndTime > bounds.x) {
329 int width = Math.min(xForEndTime, bounds.x + bounds.width) - x - 1;
330 if (width > 0) {
331 String attribute = null;
332 int beginIndex = 0;
333 if (status == StateValues.CPU_STATUS_RUN_USERMODE && currentThreadId != fLastThreadId) {
334 attribute = Attributes.EXEC_NAME;
335 } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) {
336 attribute = Attributes.SYSTEM_CALL;
337 /*
338 * Remove the "sys_" or "syscall_entry_" or similar from what we
339 * draw in the rectangle. This depends on the trace's event layout.
340 */
341 ITmfTrace trace = entry.getTrace();
342 if (trace instanceof IKernelTrace) {
343 IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
344 beginIndex = layout.eventSyscallEntryPrefix().length();
345 }
346 }
347 if (attribute != null) {
348 int quark = ss.optQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), attribute);
349 if (quark == ITmfStateSystem.INVALID_ATTRIBUTE) {
350 return;
351 }
352 ITmfStateInterval interval = ss.querySingleState(time, quark);
353 if (!interval.getStateValue().isNull()) {
354 value = interval.getStateValue();
355 gc.setForeground(fColorWhite);
356 int drawn = Utils.drawText(gc, value.unboxStr().substring(beginIndex), x + 1, bounds.y, width, bounds.height, true, true);
357 if (drawn > 0 && status == StateValues.CPU_STATUS_RUN_USERMODE) {
358 fLastThreadId = currentThreadId;
359 }
360 }
361 }
362 if (xForEndTime < bounds.x + bounds.width) {
363 gc.setForeground(fColorGray);
364 gc.drawLine(xForEndTime, bounds.y + 1, xForEndTime, bounds.y + bounds.height - 2);
365 }
366 }
367 }
368 }
369 // make sure next time is at least at the next pixel
370 time = Math.max(tidInterval.getEndTime() + 1, drawingHelper.getTimeAtX(x + 1));
371 }
372 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
373 Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$
374 } catch (StateSystemDisposedException e) {
375 /* Ignored */
376 }
377 }
378
379 @Override
380 public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) {
381 fLastThreadId = -1;
382 }
383 }
This page took 0.039001 seconds and 5 git commands to generate.