1 /*******************************************************************************
2 * Copyright (c) 2013, 2015 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 static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
18 import org
.eclipse
.jdt
.annotation
.Nullable
;
19 import org
.eclipse
.osgi
.util
.NLS
;
20 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.Activator
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.ITmfStateProvider
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
31 * The state provider for traces that support the Call Stack view.
33 * The attribute tree should have the following structure:
40 * | | +-- CallStack (stack-attribute)
46 * | +-- CallStack (stack-attribute)
54 * +-- CallStack (stack-attribute)
63 * <li>(PID n) is an attribute name representing a unique process identifier.
65 * <li>(TID n) is an attribute whose name is the display name of the thread.
66 * Optionally, its value is a long representing the thread id, used for sorting.
68 * <li>"CallStack" is a stack-attribute whose pushed values are either a string,
69 * int or long representing the function name or address in the call stack. The
70 * type of value used must be constant for a particular CallStack.</li>
73 * @author Patrick Tasse
76 public abstract class CallStackStateProvider
extends AbstractTmfStateProvider
{
83 public static final String PROCESSES
= "Processes"; //$NON-NLS-1$
85 /** CallStack stack-attribute */
86 public static final String CALL_STACK
= "CallStack"; //$NON-NLS-1$
89 * Undefined process ID
93 protected static final int UNDEFINED_PID
= -1;
95 /** Undefined function exit name */
96 protected static final String UNDEFINED
= "UNDEFINED"; //$NON-NLS-1$
98 /** CallStack state system ID */
99 private static final String ID
= "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
102 * Default constructor
105 * The trace for which we build this state system
107 public CallStackStateProvider(ITmfTrace trace
) {
112 protected void eventHandle(ITmfEvent event
) {
113 if (!considerEvent(event
)) {
117 ITmfStateSystemBuilder ss
= checkNotNull(getStateSystemBuilder());
120 /* Check if the event is a function entry */
121 ITmfStateValue functionEntryName
= functionEntry(event
);
122 if (functionEntryName
!= null) {
123 long timestamp
= event
.getTimestamp().toNanos();
124 int pid
= getProcessId(event
);
125 String threadName
= getThreadName(event
);
126 int threadQuark
= ss
.getQuarkAbsoluteAndAdd(PROCESSES
, Integer
.toString(pid
), threadName
);
128 long threadId
= getThreadId(event
);
129 ss
.updateOngoingState(TmfStateValue
.newValueLong(threadId
), threadQuark
);
131 int callStackQuark
= ss
.getQuarkRelativeAndAdd(threadQuark
, CALL_STACK
);
132 ITmfStateValue value
= functionEntryName
;
133 ss
.pushAttribute(timestamp
, value
, callStackQuark
);
137 /* Check if the event is a function exit */
138 ITmfStateValue functionExitState
= functionExit(event
);
139 if (functionExitState
!= null) {
140 long timestamp
= event
.getTimestamp().toNanos();
141 int pid
= getProcessId(event
);
142 String thread
= getThreadName(event
);
143 int quark
= ss
.getQuarkAbsoluteAndAdd(PROCESSES
, Integer
.toString(pid
), thread
, CALL_STACK
);
144 ITmfStateValue poppedValue
= ss
.popAttribute(timestamp
, quark
);
146 * Verify that the value we are popping matches the one in the
147 * event field, unless the latter is undefined.
149 if (!functionExitState
.isNull() && !functionExitState
.equals(poppedValue
)) {
150 Activator
.logWarning(NLS
.bind(
151 Messages
.CallStackStateProvider_UnmatchedPoppedValue
,
157 } catch (AttributeNotFoundException e
) {
163 * Restrict the return type for {@link ITmfStateProvider#getNewInstance}.
168 public abstract CallStackStateProvider
getNewInstance();
171 * Check if this event should be considered at all for function entry/exit
172 * analysis. This check is only run once per event, before
173 * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
174 * checks in those methods).
178 * @return If false, the event will be ignored by the state provider. If
179 * true processing will continue.
181 protected abstract boolean considerEvent(ITmfEvent event
);
184 * Check an event if it indicates a function entry.
187 * An event to check for function entry
188 * @return The state value representing the function being entered, or null
189 * if not a function entry
192 protected abstract @Nullable ITmfStateValue
functionEntry(ITmfEvent event
);
195 * Check an event if it indicates a function exit.
198 * An event to check for function exit
199 * @return The state value representing the function being exited, or
200 * TmfStateValue#nullValue() if the exited function is undefined,
201 * or null if not a function exit.
204 protected abstract @Nullable ITmfStateValue
functionExit(ITmfEvent event
);
207 * Return the process ID of a function entry event.
209 * Use {@link #UNDEFINED_PID} if it is not known.
213 * @return The process ID
216 protected abstract int getProcessId(ITmfEvent event
);
219 * Return the thread id of a function entry event.
223 * @return The thread id
226 protected abstract long getThreadId(ITmfEvent event
);
229 * Return the thread name of a function entry or exit event.
233 * @return The thread name (as will be shown in the view)
235 protected abstract String
getThreadName(ITmfEvent event
);