common: Annotate HashBasedTable.create()
[deliverable/tracecompass.git] / lttng / org.eclipse.tracecompass.lttng2.kernel.core / src / org / eclipse / tracecompass / internal / lttng2 / kernel / core / analysis / graph / handlers / TraceEventHandlerExecutionGraph.java
CommitLineData
af7f72ce
FG
1/*******************************************************************************
2 * Copyright (c) 2015 École Polytechnique de Montréal
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
10package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers;
11
12import java.util.Collection;
13import java.util.Collections;
14import java.util.HashMap;
4c4e2816 15import java.util.Map;
af7f72ce
FG
16
17import org.eclipse.core.runtime.NullProgressMonitor;
18import org.eclipse.jdt.annotation.Nullable;
19import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge;
20import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge.EdgeType;
21import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph;
22import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex;
23import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex.EdgeDirection;
24import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.LinuxValues;
25import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread;
5aa7fe19 26import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
af7f72ce
FG
27import org.eclipse.tracecompass.common.core.NonNullUtils;
28import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings;
29import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider;
30import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context;
31import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus;
32import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.EventField;
33import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngInterruptContext;
34import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel;
35import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker;
af7f72ce
FG
36import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
37import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
38import org.eclipse.tracecompass.tmf.core.event.matching.IMatchProcessingUnit;
39import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventDependency;
40import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching;
41import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
42import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
43
44import com.google.common.collect.HashBasedTable;
45import com.google.common.collect.Table;
46
47/**
48 * Event handler that actually builds the execution graph from the events
49 *
50 * @author Francis Giraldeau
51 * @author Geneviève Bastien
52 */
53public class TraceEventHandlerExecutionGraph extends BaseHandler {
54
55 /*
56 * The following IRQ constants was found empirically.
57 *
58 * TODO: other IRQ values should be determined from the lttng_statedump_interrupt events.
59 */
60 private static final int IRQ_TIMER = 0;
61
62 private static final NullProgressMonitor DEFAULT_PROGRESS_MONITOR = new NullProgressMonitor();
63
64 private final Table<String, Integer, LttngWorker> fKernel;
65 private final IMatchProcessingUnit fMatchProcessing;
4c4e2816 66 private Map<ITmfEvent, TmfVertex> fTcpNodes;
af7f72ce
FG
67 private TmfEventMatching fTcpMatching;
68
69 /**
70 * Constructor
71 *
72 * @param provider
73 * The parent graph provider
74 */
75 public TraceEventHandlerExecutionGraph(LttngKernelExecGraphProvider provider) {
76 super(provider);
dc303fab 77 fKernel = HashBasedTable.create();
af7f72ce
FG
78
79 fTcpNodes = new HashMap<>();
80 fMatchProcessing = new IMatchProcessingUnit() {
81
82 @Override
83 public void matchingEnded() {
84 }
85
86 @Override
87 public int countMatches() {
88 return 0;
89 }
90
91 @Override
92 public void addMatch(@Nullable TmfEventDependency match) {
93 if (match == null) {
94 return;
95 }
96 TmfVertex output = fTcpNodes.remove(match.getSourceEvent());
97 TmfVertex input = fTcpNodes.remove(match.getDestinationEvent());
98 if (output != null && input != null) {
99 output.linkVertical(input).setType(EdgeType.NETWORK);
100 }
101 }
102
103 @Override
4c4e2816 104 public void init(Collection<ITmfTrace> fTraces) {
af7f72ce
FG
105
106 }
107
108 };
109
110 ITmfTrace trace = provider.getTrace();
111 fTcpMatching = new TmfEventMatching(Collections.singleton(trace), fMatchProcessing);
112 fTcpMatching.initMatching();
113 }
114
115 private LttngWorker getOrCreateKernelWorker(ITmfEvent event, Integer cpu) {
116 String host = event.getTrace().getHostId();
117 LttngWorker worker = fKernel.get(host, cpu);
118 if (worker == null) {
119 HostThread ht = new HostThread(host, -1);
120 worker = new LttngWorker(ht, "kernel/" + cpu, event.getTimestamp().getValue()); //$NON-NLS-1$
121 worker.setStatus(ProcessStatus.RUN);
122
123 fKernel.put(host, cpu, worker);
124 }
125 return worker;
126 }
127
128 @Override
129 public void handleEvent(ITmfEvent ev) {
130 String eventName = ev.getName();
5aa7fe19 131 IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(ev.getTrace());
af7f72ce
FG
132
133 if (eventName.equals(eventLayout.eventSchedSwitch())) {
134 handleSchedSwitch(ev);
af7f72ce
FG
135 } else if (eventName.equals(eventLayout.eventSoftIrqEntry())) {
136 handleSoftirqEntry(ev);
137 } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_IN) ||
138 eventName.equals(TcpEventStrings.NETIF_RECEIVE_SKB)) {
139 handleInetSockLocalIn(ev);
140 } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_OUT) ||
141 eventName.equals(TcpEventStrings.NET_DEV_QUEUE)) {
142 handleInetSockLocalOut(ev);
5aa7fe19
FG
143 } else if (isWakeupEvent(ev)) {
144 handleSchedWakeup(ev);
af7f72ce
FG
145 }
146 }
147
148 private TmfVertex stateExtend(LttngWorker task, long ts) {
149 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
150 TmfVertex node = new TmfVertex(ts);
151 ProcessStatus status = task.getStatus();
152 graph.append(task, node, resolveProcessStatus(status));
153 return node;
154 }
155
156 private TmfVertex stateChange(LttngWorker task, long ts) {
157 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
158 TmfVertex node = new TmfVertex(ts);
159 ProcessStatus status = task.getOldStatus();
160 graph.append(task, node, resolveProcessStatus(status));
161 return node;
162 }
163
164 private static EdgeType resolveProcessStatus(ProcessStatus status) {
165 EdgeType ret = EdgeType.UNKNOWN;
166 switch (status) {
167 case DEAD:
168 break;
169 case EXIT:
170 case RUN:
171 ret = EdgeType.RUNNING;
172 break;
173 case UNKNOWN:
174 ret = EdgeType.UNKNOWN;
175 break;
176 case WAIT_BLOCKED:
177 ret = EdgeType.BLOCKED;
178 break;
179 case WAIT_CPU:
180 case WAIT_FORK:
181 ret = EdgeType.PREEMPTED;
182 break;
183 case ZOMBIE:
184 ret = EdgeType.UNKNOWN;
185 break;
186 default:
187 break;
188 }
189 return ret;
190 }
191
192 private void handleSchedSwitch(ITmfEvent event) {
193 String host = event.getTrace().getHostId();
194 long ts = event.getTimestamp().getValue();
5aa7fe19 195 IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(event.getTrace());
af7f72ce
FG
196 LttngSystemModel system = getProvider().getSystem();
197
198 Integer next = EventField.getInt(event, eventLayout.fieldNextTid());
199 Integer prev = EventField.getInt(event, eventLayout.fieldPrevTid());
200
201 LttngWorker nextTask = system.findWorker(new HostThread(host, next));
202 LttngWorker prevTask = system.findWorker(new HostThread(host, prev));
203
204 if (prevTask == null || nextTask == null) {
205 return;
206 }
207 stateChange(prevTask, ts);
208 stateChange(nextTask, ts);
209 }
210
211 private void handleSchedWakeup(ITmfEvent event) {
212 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
213 String host = event.getTrace().getHostId();
b3867ecc 214 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
5aa7fe19 215 IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(event.getTrace());
af7f72ce
FG
216 LttngSystemModel system = getProvider().getSystem();
217
218 long ts = event.getTimestamp().getValue();
219 Integer tid = EventField.getInt(event, eventLayout.fieldTid());
220
221 LttngWorker target = system.findWorker(new HostThread(host, tid));
222 LttngWorker current = system.getWorkerOnCpu(host, cpu);
223 if (target == null) {
224 return;
225 }
226
227 ProcessStatus status = target.getOldStatus();
228 switch (status) {
229 case WAIT_FORK:
230 waitFork(graph, ts, target, current);
231 break;
232 case WAIT_BLOCKED:
233 waitBlocked(event, graph, host, cpu, eventLayout, system, ts, target, current);
234 break;
235 case DEAD:
236 case EXIT:
237 case RUN:
238 case UNKNOWN:
239 case WAIT_CPU:
240 case ZOMBIE:
241 break;
242 default:
243 break;
244 }
245 }
246
5aa7fe19 247 private void waitBlocked(ITmfEvent event, TmfGraph graph, String host, Integer cpu, IKernelAnalysisEventLayout eventLayout, LttngSystemModel system, long ts, LttngWorker target, @Nullable LttngWorker current) {
af7f72ce
FG
248 LttngInterruptContext context = system.peekContextStack(host, cpu);
249 switch (context.getContext()) {
250 case HRTIMER:
251 // shortcut of appendTaskNode: resolve blocking source in situ
252 graph.append(target, new TmfVertex(ts), EdgeType.TIMER);
253 break;
254 case IRQ:
255 irq(graph, eventLayout, ts, target, context);
256 break;
257 case SOFTIRQ:
258 softIrq(event, graph, cpu, eventLayout, ts, target, context);
259 break;
5aa7fe19
FG
260 case IPI:
261 graph.append(target, new TmfVertex(ts), EdgeType.IPI);
262 break;
af7f72ce
FG
263 case NONE:
264 none(ts, target, current);
265 break;
266 default:
267 break;
268 }
269 }
270
5aa7fe19 271 private void softIrq(ITmfEvent event, TmfGraph graph, Integer cpu, IKernelAnalysisEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) {
af7f72ce
FG
272 TmfVertex wup = new TmfVertex(ts);
273 TmfEdge l2 = graph.append(target, wup);
274 if (l2 != null) {
275 int vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec()).intValue();
276 l2.setType(resolveSoftirq(vec));
277 }
278 // special case for network related softirq
279 Long vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec());
280 if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) {
281 // create edge if wake up is caused by incoming packet
282 LttngWorker k = getOrCreateKernelWorker(event, cpu);
283 TmfVertex tail = graph.getTail(k);
284 if (tail != null && tail.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE) != null) {
285 TmfVertex kwup = stateExtend(k, event.getTimestamp().getValue());
286 kwup.linkVertical(wup);
287 }
288 }
289 }
290
291 private void none(long ts, LttngWorker target, @Nullable LttngWorker current) {
292 // task context wakeup
293 if (current != null) {
294 TmfVertex n0 = stateExtend(current, ts);
295 TmfVertex n1 = stateChange(target, ts);
296 n0.linkVertical(n1);
297 } else {
298 stateChange(target, ts);
299 }
300 }
301
5aa7fe19 302 private static void irq(TmfGraph graph, IKernelAnalysisEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) {
af7f72ce
FG
303 TmfEdge link = graph.append(target, new TmfVertex(ts));
304 if (link != null) {
305 int vec = EventField.getLong(context.getEvent(), eventLayout.fieldIrq()).intValue();
306 link.setType(resolveIRQ(vec));
307 }
308 }
309
310 private void waitFork(TmfGraph graph, long ts, LttngWorker target, @Nullable LttngWorker current) {
311 if (current != null) {
312 TmfVertex n0 = stateExtend(current, ts);
313 TmfVertex n1 = stateChange(target, ts);
314 graph.link(n0, n1);
315 } else {
316 stateChange(target, ts);
317 }
318 }
319
320 private static EdgeType resolveIRQ(int vec) {
321 EdgeType ret = EdgeType.UNKNOWN;
322 switch (vec) {
323 case IRQ_TIMER:
324 ret = EdgeType.INTERRUPTED;
325 break;
326 default:
327 ret = EdgeType.UNKNOWN;
328 break;
329 }
330 return ret;
331 }
332
333 private static EdgeType resolveSoftirq(int vec) {
334 EdgeType ret = EdgeType.UNKNOWN;
335 switch (vec) {
336 case LinuxValues.SOFTIRQ_HRTIMER:
337 case LinuxValues.SOFTIRQ_TIMER:
338 ret = EdgeType.TIMER;
339 break;
340 case LinuxValues.SOFTIRQ_BLOCK:
341 case LinuxValues.SOFTIRQ_BLOCK_IOPOLL:
342 ret = EdgeType.BLOCK_DEVICE;
343 break;
344 case LinuxValues.SOFTIRQ_NET_RX:
345 case LinuxValues.SOFTIRQ_NET_TX:
346 ret = EdgeType.NETWORK;
347 break;
348 case LinuxValues.SOFTIRQ_SCHED:
349 ret = EdgeType.INTERRUPTED;
350 break;
351 default:
352 ret = EdgeType.UNKNOWN;
353 break;
354 }
355 return ret;
356 }
357
358 private void handleInetSockLocalIn(ITmfEvent event) {
b3867ecc 359 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
360 String host = event.getTrace().getHostId();
361 LttngSystemModel system = getProvider().getSystem();
362
363 LttngInterruptContext intCtx = system.peekContextStack(host, cpu);
364 Context context = intCtx.getContext();
365 if (context == Context.SOFTIRQ) {
366 LttngWorker k = getOrCreateKernelWorker(event, cpu);
367 TmfVertex endpoint = stateExtend(k, event.getTimestamp().getValue());
368 fTcpNodes.put(event, endpoint);
369 // TODO add actual progress monitor
370 fTcpMatching.matchEvent(event, event.getTrace(), DEFAULT_PROGRESS_MONITOR);
371 }
372 }
373
374 private void handleInetSockLocalOut(ITmfEvent event) {
b3867ecc 375 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
376 String host = event.getTrace().getHostId();
377 LttngSystemModel system = getProvider().getSystem();
378
379 LttngInterruptContext intCtx = system.peekContextStack(host, cpu);
380 Context context = intCtx.getContext();
381
382 LttngWorker sender = null;
383 if (context == Context.NONE) {
384 sender = system.getWorkerOnCpu(event.getTrace().getHostId(), cpu);
385 } else if (context == Context.SOFTIRQ) {
386 sender = getOrCreateKernelWorker(event, cpu);
387 }
388 if (sender == null) {
389 return;
390 }
391 TmfVertex endpoint = stateExtend(sender, event.getTimestamp().getValue());
392 fTcpNodes.put(event, endpoint);
393 // TODO, add actual progress monitor
394 fTcpMatching.matchEvent(event, event.getTrace(), new NullProgressMonitor());
395 }
396
397 private void handleSoftirqEntry(ITmfEvent event) {
5aa7fe19 398 IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(event.getTrace());
af7f72ce
FG
399 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
400 Long vec = EventField.getLong(event, eventLayout.fieldVec());
401 if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) {
b3867ecc 402 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
403 LttngWorker k = getOrCreateKernelWorker(event, cpu);
404 graph.add(k, new TmfVertex(event.getTimestamp().getValue()));
405 }
406 }
407
408}
This page took 0.063349 seconds and 5 git commands to generate.