tmf: Introduce resolveIntEventAspectOfClassForEvent
[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;
26import org.eclipse.tracecompass.common.core.NonNullUtils;
27import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings;
28import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider;
29import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context;
30import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.ProcessStatus;
31import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.EventField;
32import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngInterruptContext;
33import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel;
34import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngWorker;
35import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout;
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);
df2597e0 77 fKernel = NonNullUtils.checkNotNull(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();
131 LttngEventLayout eventLayout = getProvider().getEventLayout();
132
133 if (eventName.equals(eventLayout.eventSchedSwitch())) {
134 handleSchedSwitch(ev);
135 } else if (eventName.equals(eventLayout.eventSchedProcessTTWU())) {
136 if (traceHasEventSchedTTWU(ev.getTrace())) {
137 handleSchedWakeup(ev);
138 }
139 } else if (eventName.equals(eventLayout.eventSchedProcessWakeup())) {
140 if (!traceHasEventSchedTTWU(ev.getTrace())) {
141 handleSchedWakeup(ev);
142 }
143 } else if (eventName.equals(eventLayout.eventSchedProcessWakeupNew())) {
144 if (!traceHasEventSchedTTWU(ev.getTrace())) {
145 handleSchedWakeup(ev);
146 }
147 } else if (eventName.equals(eventLayout.eventSoftIrqEntry())) {
148 handleSoftirqEntry(ev);
149 } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_IN) ||
150 eventName.equals(TcpEventStrings.NETIF_RECEIVE_SKB)) {
151 handleInetSockLocalIn(ev);
152 } else if (eventName.equals(TcpEventStrings.INET_SOCK_LOCAL_OUT) ||
153 eventName.equals(TcpEventStrings.NET_DEV_QUEUE)) {
154 handleInetSockLocalOut(ev);
155 }
156 }
157
158 private TmfVertex stateExtend(LttngWorker task, long ts) {
159 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
160 TmfVertex node = new TmfVertex(ts);
161 ProcessStatus status = task.getStatus();
162 graph.append(task, node, resolveProcessStatus(status));
163 return node;
164 }
165
166 private TmfVertex stateChange(LttngWorker task, long ts) {
167 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
168 TmfVertex node = new TmfVertex(ts);
169 ProcessStatus status = task.getOldStatus();
170 graph.append(task, node, resolveProcessStatus(status));
171 return node;
172 }
173
174 private static EdgeType resolveProcessStatus(ProcessStatus status) {
175 EdgeType ret = EdgeType.UNKNOWN;
176 switch (status) {
177 case DEAD:
178 break;
179 case EXIT:
180 case RUN:
181 ret = EdgeType.RUNNING;
182 break;
183 case UNKNOWN:
184 ret = EdgeType.UNKNOWN;
185 break;
186 case WAIT_BLOCKED:
187 ret = EdgeType.BLOCKED;
188 break;
189 case WAIT_CPU:
190 case WAIT_FORK:
191 ret = EdgeType.PREEMPTED;
192 break;
193 case ZOMBIE:
194 ret = EdgeType.UNKNOWN;
195 break;
196 default:
197 break;
198 }
199 return ret;
200 }
201
202 private void handleSchedSwitch(ITmfEvent event) {
203 String host = event.getTrace().getHostId();
204 long ts = event.getTimestamp().getValue();
205 LttngEventLayout eventLayout = getProvider().getEventLayout();
206 LttngSystemModel system = getProvider().getSystem();
207
208 Integer next = EventField.getInt(event, eventLayout.fieldNextTid());
209 Integer prev = EventField.getInt(event, eventLayout.fieldPrevTid());
210
211 LttngWorker nextTask = system.findWorker(new HostThread(host, next));
212 LttngWorker prevTask = system.findWorker(new HostThread(host, prev));
213
214 if (prevTask == null || nextTask == null) {
215 return;
216 }
217 stateChange(prevTask, ts);
218 stateChange(nextTask, ts);
219 }
220
221 private void handleSchedWakeup(ITmfEvent event) {
222 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
223 String host = event.getTrace().getHostId();
b3867ecc 224 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
225 LttngEventLayout eventLayout = getProvider().getEventLayout();
226 LttngSystemModel system = getProvider().getSystem();
227
228 long ts = event.getTimestamp().getValue();
229 Integer tid = EventField.getInt(event, eventLayout.fieldTid());
230
231 LttngWorker target = system.findWorker(new HostThread(host, tid));
232 LttngWorker current = system.getWorkerOnCpu(host, cpu);
233 if (target == null) {
234 return;
235 }
236
237 ProcessStatus status = target.getOldStatus();
238 switch (status) {
239 case WAIT_FORK:
240 waitFork(graph, ts, target, current);
241 break;
242 case WAIT_BLOCKED:
243 waitBlocked(event, graph, host, cpu, eventLayout, system, ts, target, current);
244 break;
245 case DEAD:
246 case EXIT:
247 case RUN:
248 case UNKNOWN:
249 case WAIT_CPU:
250 case ZOMBIE:
251 break;
252 default:
253 break;
254 }
255 }
256
257 private void waitBlocked(ITmfEvent event, TmfGraph graph, String host, Integer cpu, LttngEventLayout eventLayout, LttngSystemModel system, long ts, LttngWorker target, @Nullable LttngWorker current) {
258 LttngInterruptContext context = system.peekContextStack(host, cpu);
259 switch (context.getContext()) {
260 case HRTIMER:
261 // shortcut of appendTaskNode: resolve blocking source in situ
262 graph.append(target, new TmfVertex(ts), EdgeType.TIMER);
263 break;
264 case IRQ:
265 irq(graph, eventLayout, ts, target, context);
266 break;
267 case SOFTIRQ:
268 softIrq(event, graph, cpu, eventLayout, ts, target, context);
269 break;
270 case NONE:
271 none(ts, target, current);
272 break;
273 default:
274 break;
275 }
276 }
277
278 private void softIrq(ITmfEvent event, TmfGraph graph, Integer cpu, LttngEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) {
279 TmfVertex wup = new TmfVertex(ts);
280 TmfEdge l2 = graph.append(target, wup);
281 if (l2 != null) {
282 int vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec()).intValue();
283 l2.setType(resolveSoftirq(vec));
284 }
285 // special case for network related softirq
286 Long vec = EventField.getLong(context.getEvent(), eventLayout.fieldVec());
287 if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) {
288 // create edge if wake up is caused by incoming packet
289 LttngWorker k = getOrCreateKernelWorker(event, cpu);
290 TmfVertex tail = graph.getTail(k);
291 if (tail != null && tail.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE) != null) {
292 TmfVertex kwup = stateExtend(k, event.getTimestamp().getValue());
293 kwup.linkVertical(wup);
294 }
295 }
296 }
297
298 private void none(long ts, LttngWorker target, @Nullable LttngWorker current) {
299 // task context wakeup
300 if (current != null) {
301 TmfVertex n0 = stateExtend(current, ts);
302 TmfVertex n1 = stateChange(target, ts);
303 n0.linkVertical(n1);
304 } else {
305 stateChange(target, ts);
306 }
307 }
308
309 private static void irq(TmfGraph graph, LttngEventLayout eventLayout, long ts, LttngWorker target, LttngInterruptContext context) {
310 TmfEdge link = graph.append(target, new TmfVertex(ts));
311 if (link != null) {
312 int vec = EventField.getLong(context.getEvent(), eventLayout.fieldIrq()).intValue();
313 link.setType(resolveIRQ(vec));
314 }
315 }
316
317 private void waitFork(TmfGraph graph, long ts, LttngWorker target, @Nullable LttngWorker current) {
318 if (current != null) {
319 TmfVertex n0 = stateExtend(current, ts);
320 TmfVertex n1 = stateChange(target, ts);
321 graph.link(n0, n1);
322 } else {
323 stateChange(target, ts);
324 }
325 }
326
327 private static EdgeType resolveIRQ(int vec) {
328 EdgeType ret = EdgeType.UNKNOWN;
329 switch (vec) {
330 case IRQ_TIMER:
331 ret = EdgeType.INTERRUPTED;
332 break;
333 default:
334 ret = EdgeType.UNKNOWN;
335 break;
336 }
337 return ret;
338 }
339
340 private static EdgeType resolveSoftirq(int vec) {
341 EdgeType ret = EdgeType.UNKNOWN;
342 switch (vec) {
343 case LinuxValues.SOFTIRQ_HRTIMER:
344 case LinuxValues.SOFTIRQ_TIMER:
345 ret = EdgeType.TIMER;
346 break;
347 case LinuxValues.SOFTIRQ_BLOCK:
348 case LinuxValues.SOFTIRQ_BLOCK_IOPOLL:
349 ret = EdgeType.BLOCK_DEVICE;
350 break;
351 case LinuxValues.SOFTIRQ_NET_RX:
352 case LinuxValues.SOFTIRQ_NET_TX:
353 ret = EdgeType.NETWORK;
354 break;
355 case LinuxValues.SOFTIRQ_SCHED:
356 ret = EdgeType.INTERRUPTED;
357 break;
358 default:
359 ret = EdgeType.UNKNOWN;
360 break;
361 }
362 return ret;
363 }
364
365 private void handleInetSockLocalIn(ITmfEvent event) {
b3867ecc 366 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
367 String host = event.getTrace().getHostId();
368 LttngSystemModel system = getProvider().getSystem();
369
370 LttngInterruptContext intCtx = system.peekContextStack(host, cpu);
371 Context context = intCtx.getContext();
372 if (context == Context.SOFTIRQ) {
373 LttngWorker k = getOrCreateKernelWorker(event, cpu);
374 TmfVertex endpoint = stateExtend(k, event.getTimestamp().getValue());
375 fTcpNodes.put(event, endpoint);
376 // TODO add actual progress monitor
377 fTcpMatching.matchEvent(event, event.getTrace(), DEFAULT_PROGRESS_MONITOR);
378 }
379 }
380
381 private void handleInetSockLocalOut(ITmfEvent event) {
b3867ecc 382 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
383 String host = event.getTrace().getHostId();
384 LttngSystemModel system = getProvider().getSystem();
385
386 LttngInterruptContext intCtx = system.peekContextStack(host, cpu);
387 Context context = intCtx.getContext();
388
389 LttngWorker sender = null;
390 if (context == Context.NONE) {
391 sender = system.getWorkerOnCpu(event.getTrace().getHostId(), cpu);
392 } else if (context == Context.SOFTIRQ) {
393 sender = getOrCreateKernelWorker(event, cpu);
394 }
395 if (sender == null) {
396 return;
397 }
398 TmfVertex endpoint = stateExtend(sender, event.getTimestamp().getValue());
399 fTcpNodes.put(event, endpoint);
400 // TODO, add actual progress monitor
401 fTcpMatching.matchEvent(event, event.getTrace(), new NullProgressMonitor());
402 }
403
404 private void handleSoftirqEntry(ITmfEvent event) {
405 LttngEventLayout eventLayout = getProvider().getEventLayout();
406 TmfGraph graph = NonNullUtils.checkNotNull(getProvider().getAssignedGraph());
407 Long vec = EventField.getLong(event, eventLayout.fieldVec());
408 if (vec == LinuxValues.SOFTIRQ_NET_RX || vec == LinuxValues.SOFTIRQ_NET_TX) {
b3867ecc 409 Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
af7f72ce
FG
410 LttngWorker k = getOrCreateKernelWorker(event, cpu);
411 graph.add(k, new TmfVertex(event.getTimestamp().getValue()));
412 }
413 }
414
415}
This page took 0.042674 seconds and 5 git commands to generate.