1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 Ericsson, É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 * Patrick Tasse - Initial API and implementation
11 * Geneviève Bastien - Move code to provide base classes for time graph view
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.ui
.views
.controlflow
;
16 import java
.util
.LinkedHashMap
;
17 import java
.util
.List
;
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
.kernel
.KernelAnalysisModule
;
25 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.StateValues
;
26 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
27 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelTrace
;
28 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.kernel
.Attributes
;
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
;
48 * Presentation provider for the control flow view
50 public class ControlFlowPresentationProvider
extends TimeGraphPresentationProvider
{
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));
63 private State(RGB rgb
) {
70 * Average width of the characters used for state labels. Is computed in the
71 * first call to postDrawEvent(). Is null before that.
73 private Integer fAverageCharacterWidth
= null;
78 public ControlFlowPresentationProvider() {
79 super(Messages
.ControlFlowView_stateTypeName
);
82 private static State
[] getStateValues() {
83 return State
.values();
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());
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();
103 if (event
instanceof NullTimeEvent
) {
110 public String
getEventName(ITimeEvent event
) {
111 if (event
instanceof TimeEvent
) {
112 TimeEvent ev
= (TimeEvent
) event
;
114 return getMatchingState(ev
.getValue()).toString();
117 return Messages
.ControlFlowView_multipleStates
;
120 private static State
getMatchingState(int 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
;
135 return State
.UNKNOWN
;
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
)) {
146 ControlFlowEntry entry
= (ControlFlowEntry
) event
.getEntry();
147 ITmfStateSystem ssq
= TmfStateSystemAnalysisModule
.getStateSystem(entry
.getTrace(), KernelAnalysisModule
.ID
);
151 int tid
= entry
.getThreadId();
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
));
170 } catch (AttributeNotFoundException
| TimeRangeException
| StateValueTypeException e
) {
171 Activator
.getDefault().logError("Error in ControlFlowPresentationProvider", e
); //$NON-NLS-1$
172 } catch (StateSystemDisposedException e
) {
175 int status
= ((TimeEvent
) event
).getValue();
176 if (status
== StateValues
.PROCESS_STATUS_RUN_SYSCALL
) {
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());
185 } catch (AttributeNotFoundException
| TimeRangeException e
) {
186 Activator
.getDefault().logError("Error in ControlFlowPresentationProvider", e
); //$NON-NLS-1$
187 } catch (StateSystemDisposedException e
) {
196 public void postDrawEvent(ITimeEvent event
, Rectangle bounds
, GC gc
) {
197 if (fAverageCharacterWidth
== null) {
198 fAverageCharacterWidth
= gc
.getFontMetrics().getAverageCharWidth();
200 if (bounds
.width
<= fAverageCharacterWidth
) {
203 if (!(event
instanceof TimeEvent
)) {
206 ControlFlowEntry entry
= (ControlFlowEntry
) event
.getEntry();
207 ITmfStateSystem ss
= TmfStateSystemAnalysisModule
.getStateSystem(entry
.getTrace(), KernelAnalysisModule
.ID
);
211 int status
= ((TimeEvent
) event
).getValue();
213 if (status
!= StateValues
.PROCESS_STATUS_RUN_SYSCALL
) {
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
));
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.
228 ITmfTrace trace
= entry
.getTrace();
229 if (trace
instanceof IKernelTrace
) {
230 IKernelAnalysisEventLayout layout
= ((IKernelTrace
) trace
).getKernelEventLayout();
231 beginIndex
= layout
.eventSyscallEntryPrefix().length();
234 Utils
.drawText(gc
, state
.toString().substring(beginIndex
), bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
, true, true);
236 } catch (AttributeNotFoundException
| TimeRangeException e
) {
237 Activator
.getDefault().logError("Error in ControlFlowPresentationProvider", e
); //$NON-NLS-1$
238 } catch (StateSystemDisposedException e
) {