1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 Ericsson
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 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.core
.callstack
;
15 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
16 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateValueTypeException
;
17 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.TimeRangeException
;
18 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
;
19 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.TmfStateValue
;
20 import org
.eclipse
.osgi
.util
.NLS
;
21 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.Activator
;
22 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
28 * The state provider for traces that support the Call Stack view.
30 * The attribute tree should have the following structure:
35 * | \-- CallStack (stack-attribute)
41 * | \-- CallStack (stack-attribute)
48 * \-- CallStack (stack-attribute)
56 * (Thread n) is an attribute whose name is the display name of the thread.
57 * Optionally, its value is a long representing the thread id, used for sorting.
59 * CallStack is a stack-attribute whose pushed values are either a string,
60 * int or long representing the function name or address in the call stack.
61 * The type of value used must be constant for a particular CallStack.
63 * @author Patrick Tasse
66 public abstract class CallStackStateProvider
extends AbstractTmfStateProvider
{
68 /** Thread attribute */
69 public static final String THREADS
= "Threads"; //$NON-NLS-1$
70 /** CallStack stack-attribute */
71 public static final String CALL_STACK
= "CallStack"; //$NON-NLS-1$
72 /** Undefined function exit name */
73 public static final String UNDEFINED
= "UNDEFINED"; //$NON-NLS-1$
75 /** CallStack state system ID */
76 private static final String ID
= "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
77 /** Dummy function name for when no function is expected */
78 private static final String NO_FUNCTION
= "no function"; //$NON-NLS-1$
84 * The trace for which we build this state system
86 public CallStackStateProvider(ITmfTrace trace
) {
87 super(trace
, ITmfEvent
.class, ID
);
91 protected void eventHandle(ITmfEvent event
) {
92 if (!considerEvent(event
)) {
96 /* Check if the event is a function entry */
97 String functionEntryName
= functionEntry(event
);
98 if (functionEntryName
!= null) {
99 long timestamp
= event
.getTimestamp().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
100 String thread
= getThreadName(event
);
101 int threadQuark
= ss
.getQuarkAbsoluteAndAdd(THREADS
, thread
);
102 Long threadId
= getThreadId(event
);
103 if (threadId
!= null) {
104 ss
.updateOngoingState(TmfStateValue
.newValueLong(threadId
), threadQuark
);
106 int callStackQuark
= ss
.getQuarkRelativeAndAdd(threadQuark
, CALL_STACK
);
107 ITmfStateValue value
= TmfStateValue
.newValueString(functionEntryName
);
108 ss
.pushAttribute(timestamp
, value
, callStackQuark
);
112 /* Check if the event is a function exit */
113 String functionExitName
= functionExit(event
);
114 if (functionExitName
!= null) {
115 long timestamp
= event
.getTimestamp().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
116 String thread
= getThreadName(event
);
117 int quark
= ss
.getQuarkAbsoluteAndAdd(THREADS
, thread
, CALL_STACK
);
118 ITmfStateValue poppedValue
= ss
.popAttribute(timestamp
, quark
);
119 String poppedName
= (poppedValue
== null ? NO_FUNCTION
: poppedValue
.unboxStr());
122 * Verify that the value we are popping matches the one in the
123 * event field, unless the latter is undefined.
125 if (!functionExitName
.equals(UNDEFINED
) &&
126 !functionExitName
.equals(poppedName
)) {
127 Activator
.logWarning(NLS
.bind(
128 Messages
.CallStackStateProvider_UnmatchedPoppedValue
,
134 } catch (TimeRangeException e
) {
136 } catch (AttributeNotFoundException e
) {
138 } catch (StateValueTypeException e
) {
144 * Check if this event should be considered at all for function entry/exit
145 * analysis. This check is only run once per event, before
146 * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
147 * checks in those methods).
151 * @return If false, the event will be ignored by the state provider. If
152 * true processing will continue.
155 protected abstract boolean considerEvent(ITmfEvent event
);
158 * Check an event if it indicates a function entry.
161 * An event to check for function entry
162 * @return The function name of the function entry, or null if not a
165 protected abstract String
functionEntry(ITmfEvent event
);
168 * Check an event if it indicates a function exit.
171 * An event to check for function exit
172 * @return The function name, or UNDEFINED, for a function exit, or null if
173 * not a function exit.
175 protected abstract String
functionExit(ITmfEvent event
);
178 * Return the thread name of a function entry or exit event.
182 * @return The thread name (as will be shown in the view)
185 protected abstract String
getThreadName(ITmfEvent event
);
188 * Return the thread id of a function entry event.
192 * @return The thread id, or null if undefined
195 protected Long
getThreadId(ITmfEvent event
) {