1 /*******************************************************************************
2 * Copyright (c) 2015 École Polytechnique de Montréal
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 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.handlers
;
12 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.LinuxValues
;
13 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.model
.HostThread
;
14 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
15 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
16 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.building
.LttngKernelExecGraphProvider
;
17 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.building
.LttngKernelExecGraphProvider
.ProcessStatus
;
18 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.model
.EventField
;
19 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.model
.LttngSystemModel
;
20 import org
.eclipse
.tracecompass
.internal
.lttng2
.kernel
.core
.analysis
.graph
.model
.LttngWorker
;
21 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
22 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
26 * Provides the current task running on a CPU according to scheduling events
28 * @author Francis Giraldeau
29 * @author Geneviève Bastien
31 public class TraceEventHandlerSched
extends BaseHandler
{
37 * The parent graph provider
39 public TraceEventHandlerSched(LttngKernelExecGraphProvider provider
) {
44 public void handleEvent(ITmfEvent ev
) {
45 String eventName
= ev
.getName();
46 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(ev
.getTrace());
48 if (eventName
.equals(eventLayout
.eventSchedSwitch())) {
49 handleSchedSwitch(ev
);
50 } else if (eventName
.equals(eventLayout
.eventSchedProcessFork())) {
51 handleSchedProcessFork(ev
);
52 } else if (eventName
.equals(eventLayout
.eventSchedProcessExit())) {
53 handleSchedProcessExit(ev
);
54 } else if (eventName
.equals(eventLayout
.eventSchedProcessExec())) {
55 handleSchedProcessExec(ev
);
56 } else if (isWakeupEvent(ev
)) {
57 handleSchedWakeup(ev
);
61 private void handleSchedSwitch(ITmfEvent event
) {
62 Integer cpu
= NonNullUtils
.checkNotNull(TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
));
63 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
64 LttngSystemModel system
= getProvider().getSystem();
66 Integer next
= EventField
.getInt(event
, eventLayout
.fieldNextTid());
67 Integer prev
= EventField
.getInt(event
, eventLayout
.fieldPrevTid());
68 long ts
= event
.getTimestamp().getValue();
69 long prev_state
= EventField
.getLong(event
, eventLayout
.fieldPrevState());
70 prev_state
= (long) ((int) prev_state
) & (LinuxValues
.TASK_STATE_RUNNING
| LinuxValues
.TASK_INTERRUPTIBLE
| LinuxValues
.TASK_UNINTERRUPTIBLE
);
71 String host
= event
.getTrace().getHostId();
73 system
.cacheTidOnCpu(cpu
, new HostThread(event
.getTrace().getHostId(), next
));
75 HostThread nextHt
= new HostThread(host
, next
);
76 LttngWorker nextTask
= system
.findWorker(nextHt
);
77 if (nextTask
== null) {
78 String name
= EventField
.getOrDefault(event
, eventLayout
.fieldNextComm(), NonNullUtils
.checkNotNull(Messages
.TraceEventHandlerSched_UnknownThreadName
));
79 nextTask
= new LttngWorker(nextHt
, name
, ts
);
80 system
.addWorker(nextTask
);
82 nextTask
.setStatus(ProcessStatus
.RUN
);
84 HostThread prevHt
= new HostThread(host
, prev
);
85 LttngWorker prevTask
= system
.findWorker(prevHt
);
86 if (prevTask
== null) {
87 String name
= EventField
.getOrDefault(event
, eventLayout
.fieldPrevComm(), NonNullUtils
.checkNotNull(Messages
.TraceEventHandlerSched_UnknownThreadName
));
88 prevTask
= new LttngWorker(prevHt
, name
, ts
);
89 system
.addWorker(prevTask
);
91 /* prev_state == 0 means runnable, thus waits for cpu */
92 if (prev_state
== 0) {
93 prevTask
.setStatus(ProcessStatus
.WAIT_CPU
);
95 prevTask
.setStatus(ProcessStatus
.WAIT_BLOCKED
);
99 private void handleSchedProcessFork(ITmfEvent event
) {
100 String host
= event
.getTrace().getHostId();
101 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
102 LttngSystemModel system
= getProvider().getSystem();
104 Integer childTid
= EventField
.getInt(event
, eventLayout
.fieldChildTid());
105 String name
= EventField
.getString(event
, eventLayout
.fieldChildComm());
106 long ts
= event
.getTimestamp().getValue();
108 HostThread childHt
= new HostThread(host
, childTid
);
110 LttngWorker childTask
= system
.findWorker(childHt
);
111 if (childTask
== null) {
112 childTask
= new LttngWorker(childHt
, name
, ts
);
113 system
.addWorker(childTask
);
116 childTask
.setStatus(ProcessStatus
.WAIT_FORK
);
119 private void handleSchedWakeup(ITmfEvent event
) {
120 String host
= event
.getTrace().getHostId();
121 Integer cpu
= NonNullUtils
.checkNotNull(TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
));
122 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
123 LttngSystemModel system
= getProvider().getSystem();
125 Integer tid
= EventField
.getInt(event
, eventLayout
.fieldTid());
126 HostThread targetHt
= new HostThread(host
, tid
);
128 LttngWorker target
= system
.findWorker(targetHt
);
129 LttngWorker current
= system
.getWorkerOnCpu(host
, cpu
);
131 if (target
== null) {
132 String name
= EventField
.getOrDefault(event
, eventLayout
.fieldComm(), NonNullUtils
.checkNotNull(Messages
.TraceEventHandlerSched_UnknownThreadName
));
133 target
= new LttngWorker(targetHt
, name
, event
.getTimestamp().getValue());
134 system
.addWorker(target
);
135 target
.setStatus(ProcessStatus
.WAIT_BLOCKED
);
138 ProcessStatus status
= target
.getStatus();
139 if ((current
!= null && target
.getHostThread().equals(current
.getHostThread())) ||
140 status
== ProcessStatus
.WAIT_CPU
) {
143 if (status
== ProcessStatus
.WAIT_BLOCKED
||
144 status
== ProcessStatus
.WAIT_FORK
||
145 status
== ProcessStatus
.UNKNOWN
) {
146 target
.setStatus(ProcessStatus
.WAIT_CPU
);
151 private void handleSchedProcessExit(ITmfEvent event
) {
152 String host
= event
.getTrace().getHostId();
153 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
154 LttngSystemModel system
= getProvider().getSystem();
156 Integer tid
= EventField
.getInt(event
, eventLayout
.fieldTid());
157 LttngWorker task
= system
.findWorker(new HostThread(host
, tid
));
161 task
.setStatus(ProcessStatus
.EXIT
);
164 private void handleSchedProcessExec(ITmfEvent event
) {
165 String host
= event
.getTrace().getHostId();
166 Integer cpu
= NonNullUtils
.checkNotNull(TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
));
167 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
168 LttngSystemModel system
= getProvider().getSystem();
170 String filename
= EventField
.getString(event
, eventLayout
.fieldFilename());
171 LttngWorker task
= system
.getWorkerOnCpu(host
, cpu
);
175 task
.setName(filename
);