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
.internal
.analysis
.os
.linux
.ui
.views
.resources
;
16 import java
.util
.LinkedHashMap
;
17 import java
.util
.List
;
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
;
54 * Presentation provider for the Resource view, based on the generic TMF
55 * presentation provider.
57 * @author Patrick Tasse
59 public class ResourcesPresentationProvider
extends TimeGraphPresentationProvider
{
61 private long fLastThreadId
= -1;
62 private Color fColorWhite
;
63 private Color fColorGray
;
64 private Integer fAverageCharWidth
;
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));
78 private State(RGB rgb
) {
86 public ResourcesPresentationProvider() {
90 private static State
[] getStateValues() {
91 return State
.values();
94 private static State
getEventState(TimeEvent event
) {
95 if (event
.hasValue()) {
96 ResourcesEntry entry
= (ResourcesEntry
) event
.getEntry();
97 int value
= event
.getValue();
99 if (entry
.getType() == Type
.CPU
) {
100 if (value
== StateValues
.CPU_STATUS_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
) {
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
;
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
;
119 return State
.SOFT_IRQ_ACTIVE
;
126 public int getStateTableIndex(ITimeEvent event
) {
127 State state
= getEventState((TimeEvent
) event
);
129 return state
.ordinal();
131 if (event
instanceof NullTimeEvent
) {
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());
149 public String
getEventName(ITimeEvent event
) {
150 State state
= getEventState((TimeEvent
) event
);
152 return state
.toString();
154 if (event
instanceof NullTimeEvent
) {
157 return Messages
.ResourcesView_multipleStates
;
161 public Map
<String
, String
> getEventHoverToolTipInfo(ITimeEvent event
, long hoverTime
) {
163 Map
<String
, String
> retMap
= new LinkedHashMap
<>();
164 if (event
instanceof TimeEvent
&& ((TimeEvent
) event
).hasValue()) {
166 TimeEvent tcEvent
= (TimeEvent
) event
;
167 ResourcesEntry entry
= (ResourcesEntry
) event
.getEntry();
169 if (tcEvent
.hasValue()) {
170 ITmfStateSystem ss
= TmfStateSystemAnalysisModule
.getStateSystem(entry
.getTrace(), KernelAnalysisModule
.ID
);
174 // Check for IRQ or Soft_IRQ type
175 if (entry
.getType().equals(Type
.IRQ
) || entry
.getType().equals(Type
.SOFT_IRQ
)) {
177 // Get CPU of IRQ or SoftIRQ and provide it for the tooltip display
178 int cpu
= tcEvent
.getValue();
180 retMap
.put(Messages
.ResourcesView_attributeCpuName
, String
.valueOf(cpu
));
184 // Check for type CPU
185 else if (entry
.getType().equals(Type
.CPU
)) {
186 int status
= tcEvent
.getValue();
188 if (status
== StateValues
.CPU_STATUS_IRQ
) {
189 // In IRQ state get the IRQ that caused the interruption
190 int cpu
= entry
.getId();
193 List
<ITmfStateInterval
> fullState
= ss
.queryFullState(event
.getTime());
194 List
<Integer
> irqQuarks
= ss
.getQuarks(Attributes
.CPUS
, Integer
.toString(cpu
), Attributes
.IRQS
, "*"); //$NON-NLS-1$
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
);
204 } catch (TimeRangeException
| StateValueTypeException e
) {
205 Activator
.getDefault().logError("Error in ResourcesPresentationProvider", e
); //$NON-NLS-1$
206 } catch (StateSystemDisposedException e
) {
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();
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$
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
);
225 } catch (TimeRangeException
| StateValueTypeException e
) {
226 Activator
.getDefault().logError("Error in ResourcesPresentationProvider", e
); //$NON-NLS-1$
227 } catch (StateSystemDisposedException e
) {
230 } else if (status
== StateValues
.CPU_STATUS_RUN_USERMODE
|| status
== StateValues
.CPU_STATUS_RUN_SYSCALL
) {
231 // In running state get the current tid
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());
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
) {
253 interval
= ss
.querySingleState(hoverTime
, syscallQuark
);
254 if (!interval
.getStateValue().isNull()) {
255 value
= interval
.getStateValue();
256 retMap
.put(Messages
.ResourcesView_attributeSyscallName
, value
.unboxStr());
260 } catch (AttributeNotFoundException
| TimeRangeException
| StateValueTypeException e
) {
261 Activator
.getDefault().logError("Error in ResourcesPresentationProvider", e
); //$NON-NLS-1$
262 } catch (StateSystemDisposedException e
) {
274 public void postDrawEvent(ITimeEvent event
, Rectangle bounds
, GC gc
) {
275 if (fColorGray
== null) {
276 fColorGray
= gc
.getDevice().getSystemColor(SWT
.COLOR_GRAY
);
278 if (fColorWhite
== null) {
279 fColorWhite
= gc
.getDevice().getSystemColor(SWT
.COLOR_WHITE
);
281 if (fAverageCharWidth
== null) {
282 fAverageCharWidth
= gc
.getFontMetrics().getAverageCharWidth();
285 ITmfTimeGraphDrawingHelper drawingHelper
= getDrawingHelper();
286 if (bounds
.width
<= fAverageCharWidth
) {
290 if (!(event
instanceof TimeEvent
)) {
293 TimeEvent tcEvent
= (TimeEvent
) event
;
294 if (!tcEvent
.hasValue()) {
298 ResourcesEntry entry
= (ResourcesEntry
) event
.getEntry();
299 if (!entry
.getType().equals(Type
.CPU
)) {
303 int status
= tcEvent
.getValue();
304 if (status
!= StateValues
.CPU_STATUS_RUN_USERMODE
&& status
!= StateValues
.CPU_STATUS_RUN_SYSCALL
) {
308 ITmfStateSystem ss
= TmfStateSystemAnalysisModule
.getStateSystem(entry
.getTrace(), KernelAnalysisModule
.ID
);
312 long time
= event
.getTime();
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
) {
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;
331 String attribute
= null;
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
;
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.
341 ITmfTrace trace
= entry
.getTrace();
342 if (trace
instanceof IKernelTrace
) {
343 IKernelAnalysisEventLayout layout
= ((IKernelTrace
) trace
).getKernelEventLayout();
344 beginIndex
= layout
.eventSyscallEntryPrefix().length();
347 if (attribute
!= null) {
348 int quark
= ss
.optQuarkAbsolute(Attributes
.THREADS
, Integer
.toString(currentThreadId
), attribute
);
349 if (quark
== ITmfStateSystem
.INVALID_ATTRIBUTE
) {
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
;
362 if (xForEndTime
< bounds
.x
+ bounds
.width
) {
363 gc
.setForeground(fColorGray
);
364 gc
.drawLine(xForEndTime
, bounds
.y
+ 1, xForEndTime
, bounds
.y
+ bounds
.height
- 2);
369 // make sure next time is at least at the next pixel
370 time
= Math
.max(tidInterval
.getEndTime() + 1, drawingHelper
.getTimeAtX(x
+ 1));
372 } catch (AttributeNotFoundException
| TimeRangeException
| StateValueTypeException e
) {
373 Activator
.getDefault().logError("Error in ResourcesPresentationProvider", e
); //$NON-NLS-1$
374 } catch (StateSystemDisposedException e
) {
380 public void postDrawEntry(ITimeGraphEntry entry
, Rectangle bounds
, GC gc
) {