64eedc44add0f33b2a288471f9a86d47a3e546e7
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / callstack / CallStackStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2013, 2016 Ericsson
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 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.core.callstack;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.tracecompass.internal.tmf.core.Activator;
20 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
21 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
22 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
23 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
24 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
25 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
26 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
27
28 /**
29 * The state provider for traces that support the Call Stack view.
30 *
31 * The attribute tree should have the following structure:
32 *
33 * <pre>
34 * (root)
35 * +-- Processes
36 * +-- (PID 1000)
37 * | +-- (TID 1000)
38 * | | +-- CallStack (stack-attribute)
39 * | | +-- 1
40 * | | +-- 2
41 * | | ...
42 * | | +-- n
43 * | +-- (TID 1001)
44 * | +-- CallStack (stack-attribute)
45 * | +-- 1
46 * | +-- 2
47 * | ...
48 * | +-- n
49 * |
50 * +-- (PID 2000)
51 * +-- (TID 2000)
52 * +-- CallStack (stack-attribute)
53 * +-- 1
54 * +-- 2
55 * ...
56 * +-- n
57 * </pre>
58 *
59 * where:
60 * <ul>
61 * <li>(PID n) is an attribute whose name is the display name of the process.
62 * Optionally, its value can be an int representing the process id. Otherwise,
63 * the attribute name can be set to the process id formatted as a string.</li>
64 * <li>(TID n) is an attribute whose name is the display name of the thread.
65 * Optionally, its value can be a long representing the thread id. Otherwise,
66 * the attribute name can be set to the thread id formatted as a string.</li>
67 * <li>"CallStack" is a stack-attribute whose pushed values are either a string,
68 * int or long representing the function name or address in the call stack. The
69 * type of value used must be constant for a particular CallStack.</li>
70 * </ul>
71 *
72 * @author Patrick Tasse
73 */
74 public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
75
76 /**
77 * Thread attribute
78 *
79 * @since 2.0
80 */
81 public static final String PROCESSES = "Processes"; //$NON-NLS-1$
82
83 /** CallStack stack-attribute */
84 public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
85
86 /**
87 * Unknown process ID
88 *
89 * @since 2.0
90 */
91 public static final int UNKNOWN_PID = -1;
92
93 /**
94 * Unknown name
95 *
96 * @since 2.0
97 */
98 public static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
99
100 /** CallStack state system ID */
101 private static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
102
103 /**
104 * Default constructor
105 *
106 * @param trace
107 * The trace for which we build this state system
108 */
109 public CallStackStateProvider(ITmfTrace trace) {
110 super(trace, ID);
111 }
112
113 @Override
114 protected void eventHandle(ITmfEvent event) {
115 if (!considerEvent(event)) {
116 return;
117 }
118
119 ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
120
121 /* Check if the event is a function entry */
122 ITmfStateValue functionEntryName = functionEntry(event);
123 if (functionEntryName != null) {
124 long timestamp = event.getTimestamp().toNanos();
125
126 String processName = getProcessName(event);
127 int processId = getProcessId(event);
128 if (processName == null) {
129 processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
130 }
131 int processQuark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName);
132 ss.updateOngoingState(TmfStateValue.newValueInt(processId), processQuark);
133
134 String threadName = getThreadName(event);
135 long threadId = getThreadId(event);
136 if (threadName == null) {
137 threadName = Long.toString(threadId);
138 }
139 int threadQuark = ss.getQuarkRelativeAndAdd(processQuark, threadName);
140 ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
141
142 int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
143 ITmfStateValue value = functionEntryName;
144 ss.pushAttribute(timestamp, value, callStackQuark);
145 return;
146 }
147
148 /* Check if the event is a function exit */
149 ITmfStateValue functionExitState = functionExit(event);
150 if (functionExitState != null) {
151 long timestamp = event.getTimestamp().toNanos();
152 String processName = getProcessName(event);
153 if (processName == null) {
154 int processId = getProcessId(event);
155 processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
156 }
157 String threadName = getThreadName(event);
158 if (threadName == null) {
159 threadName = Long.toString(getThreadId(event));
160 }
161 int quark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName, threadName, CALL_STACK);
162 ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
163 /*
164 * Verify that the value we are popping matches the one in the
165 * event field, unless the latter is undefined.
166 */
167 if (!functionExitState.isNull() && !functionExitState.equals(poppedValue)) {
168 Activator.logWarning(NLS.bind(
169 Messages.CallStackStateProvider_UnmatchedPoppedValue,
170 functionExitState,
171 poppedValue));
172 }
173 }
174 }
175
176 /**
177 * Restrict the return type for {@link ITmfStateProvider#getNewInstance}.
178 *
179 * @since 2.0
180 */
181 @Override
182 public abstract CallStackStateProvider getNewInstance();
183
184 /**
185 * Check if this event should be considered at all for function entry/exit
186 * analysis. This check is only run once per event, before
187 * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
188 * checks in those methods).
189 *
190 * @param event
191 * The event to check
192 * @return If false, the event will be ignored by the state provider. If
193 * true processing will continue.
194 */
195 protected abstract boolean considerEvent(ITmfEvent event);
196
197 /**
198 * Check an event if it indicates a function entry.
199 *
200 * @param event
201 * An event to check for function entry
202 * @return The state value representing the function being entered, or null
203 * if not a function entry
204 * @since 2.0
205 */
206 protected abstract @Nullable ITmfStateValue functionEntry(ITmfEvent event);
207
208 /**
209 * Check an event if it indicates a function exit.
210 *
211 * @param event
212 * An event to check for function exit
213 * @return The state value representing the function being exited, or
214 * TmfStateValue#nullValue() if the exited function is undefined,
215 * or null if not a function exit.
216 * @since 2.0
217 */
218 protected abstract @Nullable ITmfStateValue functionExit(ITmfEvent event);
219
220 /**
221 * Return the process ID of a function entry event.
222 * <p>
223 * Use {@link #UNKNOWN_PID} if it is not known.
224 *
225 * @param event
226 * The event
227 * @return The process ID
228 * @since 2.0
229 */
230 protected abstract int getProcessId(ITmfEvent event);
231
232 /**
233 * Return the process name of a function entry event.
234 *
235 * @param event
236 * The event
237 * @return The process name (as will be shown in the view) or null to use
238 * the process ID formatted as a string (or {@link #UNKNOWN})
239 * @since 2.0
240 */
241 protected @Nullable String getProcessName(ITmfEvent event) {
242 /* Override to provide a process name */
243 return null;
244 }
245
246 /**
247 * Return the thread id of a function entry event.
248 *
249 * @param event
250 * The event
251 * @return The thread id
252 * @since 2.0
253 */
254 protected abstract long getThreadId(ITmfEvent event);
255
256 /**
257 * Return the thread name of a function entry or exit event.
258 *
259 * @param event
260 * The event
261 * @return The thread name (as will be shown in the view) or null to use the
262 * thread id formatted as a string
263 */
264 protected @Nullable String getThreadName(ITmfEvent event) {
265 /* Override to provide a thread name */
266 return null;
267 }
268 }
This page took 0.045754 seconds and 5 git commands to generate.