367532743a9e0bf91edb456198b7bd4b36e3727a
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / analysis / os / linux / ui / views / controlflow / ControlFlowPresentationProvider.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.analysis.os.linux.ui.views.controlflow;
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.GC;
22 import org.eclipse.swt.graphics.RGB;
23 import org.eclipse.swt.graphics.Rectangle;
24 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes;
25 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysisModule;
26 import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.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.ui.Activator;
30 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
31 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
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.exceptions.StateValueTypeException;
35 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
36 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
37 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
38 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
39 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
40 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
41 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
42 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
43 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
44 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
45 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
46
47 /**
48 * Presentation provider for the control flow view
49 */
50 public class ControlFlowPresentationProvider extends TimeGraphPresentationProvider {
51
52 private enum State {
53 UNKNOWN (new RGB(100, 100, 100)),
54 WAIT_UNKNOWN (new RGB(200, 200, 200)),
55 WAIT_BLOCKED (new RGB(200, 200, 0)),
56 WAIT_FOR_CPU (new RGB(200, 100, 0)),
57 USERMODE (new RGB(0, 200, 0)),
58 SYSCALL (new RGB(0, 0, 200)),
59 INTERRUPTED (new RGB(200, 0, 100));
60
61 public final RGB rgb;
62
63 private State(RGB rgb) {
64 this.rgb = rgb;
65 }
66
67 }
68
69 /**
70 * Average width of the characters used for state labels. Is computed in the
71 * first call to postDrawEvent(). Is null before that.
72 */
73 private Integer fAverageCharacterWidth = null;
74
75 /**
76 * Default constructor
77 */
78 public ControlFlowPresentationProvider() {
79 super(Messages.ControlFlowView_stateTypeName);
80 }
81
82 private static State[] getStateValues() {
83 return State.values();
84 }
85
86 @Override
87 public StateItem[] getStateTable() {
88 State[] states = getStateValues();
89 StateItem[] stateTable = new StateItem[states.length];
90 for (int i = 0; i < stateTable.length; i++) {
91 State state = states[i];
92 stateTable[i] = new StateItem(state.rgb, state.toString());
93 }
94 return stateTable;
95 }
96
97 @Override
98 public int getStateTableIndex(ITimeEvent event) {
99 if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
100 int status = ((TimeEvent) event).getValue();
101 return getMatchingState(status).ordinal();
102 }
103 if (event instanceof NullTimeEvent) {
104 return INVISIBLE;
105 }
106 return TRANSPARENT;
107 }
108
109 @Override
110 public String getEventName(ITimeEvent event) {
111 if (event instanceof TimeEvent) {
112 TimeEvent ev = (TimeEvent) event;
113 if (ev.hasValue()) {
114 return getMatchingState(ev.getValue()).toString();
115 }
116 }
117 return Messages.ControlFlowView_multipleStates;
118 }
119
120 private static State getMatchingState(int status) {
121 switch (status) {
122 case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
123 return State.WAIT_UNKNOWN;
124 case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
125 return State.WAIT_BLOCKED;
126 case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
127 return State.WAIT_FOR_CPU;
128 case StateValues.PROCESS_STATUS_RUN_USERMODE:
129 return State.USERMODE;
130 case StateValues.PROCESS_STATUS_RUN_SYSCALL:
131 return State.SYSCALL;
132 case StateValues.PROCESS_STATUS_INTERRUPTED:
133 return State.INTERRUPTED;
134 default:
135 return State.UNKNOWN;
136 }
137 }
138
139 @Override
140 public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {
141 Map<String, String> retMap = new LinkedHashMap<>();
142 if (!(event instanceof TimeEvent) || !((TimeEvent) event).hasValue() ||
143 !(event.getEntry() instanceof ControlFlowEntry)) {
144 return retMap;
145 }
146 ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
147 ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
148 if (ssq == null) {
149 return retMap;
150 }
151 int tid = entry.getThreadId();
152
153 try {
154 // Find every CPU first, then get the current thread
155 int cpusQuark = ssq.getQuarkAbsolute(Attributes.CPUS);
156 List<Integer> cpuQuarks = ssq.getSubAttributes(cpusQuark, false);
157 for (Integer cpuQuark : cpuQuarks) {
158 int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
159 ITmfStateInterval interval = ssq.querySingleState(event.getTime(), currentThreadQuark);
160 if (!interval.getStateValue().isNull()) {
161 ITmfStateValue state = interval.getStateValue();
162 int currentThreadId = state.unboxInt();
163 if (tid == currentThreadId) {
164 retMap.put(Messages.ControlFlowView_attributeCpuName, ssq.getAttributeName(cpuQuark));
165 break;
166 }
167 }
168 }
169
170 } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
171 Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
172 } catch (StateSystemDisposedException e) {
173 /* Ignored */
174 }
175 int status = ((TimeEvent) event).getValue();
176 if (status == StateValues.PROCESS_STATUS_RUN_SYSCALL) {
177 try {
178 int syscallQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
179 ITmfStateInterval value = ssq.querySingleState(event.getTime(), syscallQuark);
180 if (!value.getStateValue().isNull()) {
181 ITmfStateValue state = value.getStateValue();
182 retMap.put(Messages.ControlFlowView_attributeSyscallName, state.toString());
183 }
184
185 } catch (AttributeNotFoundException | TimeRangeException e) {
186 Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
187 } catch (StateSystemDisposedException e) {
188 /* Ignored */
189 }
190 }
191
192 return retMap;
193 }
194
195 @Override
196 public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
197 if (fAverageCharacterWidth == null) {
198 fAverageCharacterWidth = gc.getFontMetrics().getAverageCharWidth();
199 }
200 if (bounds.width <= fAverageCharacterWidth) {
201 return;
202 }
203 if (!(event instanceof TimeEvent)) {
204 return;
205 }
206 ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
207 ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
208 if (ss == null) {
209 return;
210 }
211 int status = ((TimeEvent) event).getValue();
212
213 if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL) {
214 return;
215 }
216 try {
217 int syscallQuark = ss.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
218 ITmfStateInterval value = ss.querySingleState(event.getTime(), syscallQuark);
219 if (!value.getStateValue().isNull()) {
220 ITmfStateValue state = value.getStateValue();
221 gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
222
223 /*
224 * Remove the "sys_" or "syscall_entry_" or similar from what we
225 * draw in the rectangle. This depends on the trace's event layout.
226 */
227 int beginIndex = 0;
228 ITmfTrace trace = entry.getTrace();
229 if (trace instanceof IKernelTrace) {
230 IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
231 beginIndex = layout.eventSyscallEntryPrefix().length();
232 }
233
234 Utils.drawText(gc, state.toString().substring(beginIndex), bounds.x, bounds.y, bounds.width, bounds.height, true, true);
235 }
236 } catch (AttributeNotFoundException | TimeRangeException e) {
237 Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
238 } catch (StateSystemDisposedException e) {
239 /* Ignored */
240 }
241 }
242 }
This page took 0.036597 seconds and 4 git commands to generate.