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 String name
= EventField
.getOrDefault(event
, eventLayout
.fieldPrevComm(), NonNullUtils
.checkNotNull(Messages
.TraceEventHandlerSched_UnknownThreadName
));
87 if (prevTask
== null) {
88 prevTask
= new LttngWorker(prevHt
, name
, ts
);
89 system
.addWorker(prevTask
);
90 } else if (prev
!= 0) {
91 /* update the process name if changed at runtime */
92 prevTask
.setName(name
);
94 /* prev_state == 0 means runnable, thus waits for cpu */
95 if (prev_state
== 0) {
96 prevTask
.setStatus(ProcessStatus
.WAIT_CPU
);
98 prevTask
.setStatus(ProcessStatus
.WAIT_BLOCKED
);
102 private void handleSchedProcessFork(ITmfEvent event
) {
103 String host
= event
.getTrace().getHostId();
104 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
105 LttngSystemModel system
= getProvider().getSystem();
107 Integer childTid
= EventField
.getInt(event
, eventLayout
.fieldChildTid());
108 String name
= EventField
.getString(event
, eventLayout
.fieldChildComm());
109 long ts
= event
.getTimestamp().getValue();
111 HostThread childHt
= new HostThread(host
, childTid
);
113 LttngWorker childTask
= system
.findWorker(childHt
);
114 if (childTask
== null) {
115 childTask
= new LttngWorker(childHt
, name
, ts
);
116 system
.addWorker(childTask
);
119 childTask
.setStatus(ProcessStatus
.WAIT_FORK
);
122 private void handleSchedWakeup(ITmfEvent event
) {
123 String host
= event
.getTrace().getHostId();
124 Integer cpu
= NonNullUtils
.checkNotNull(TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
));
125 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
126 LttngSystemModel system
= getProvider().getSystem();
128 Integer tid
= EventField
.getInt(event
, eventLayout
.fieldTid());
129 HostThread targetHt
= new HostThread(host
, tid
);
131 LttngWorker target
= system
.findWorker(targetHt
);
132 LttngWorker current
= system
.getWorkerOnCpu(host
, cpu
);
134 if (target
== null) {
135 String name
= EventField
.getOrDefault(event
, eventLayout
.fieldComm(), NonNullUtils
.checkNotNull(Messages
.TraceEventHandlerSched_UnknownThreadName
));
136 target
= new LttngWorker(targetHt
, name
, event
.getTimestamp().getValue());
137 system
.addWorker(target
);
138 target
.setStatus(ProcessStatus
.WAIT_BLOCKED
);
141 ProcessStatus status
= target
.getStatus();
142 if ((current
!= null && target
.getHostThread().equals(current
.getHostThread())) ||
143 status
== ProcessStatus
.WAIT_CPU
) {
146 if (status
== ProcessStatus
.WAIT_BLOCKED
||
147 status
== ProcessStatus
.WAIT_FORK
||
148 status
== ProcessStatus
.UNKNOWN
) {
149 target
.setStatus(ProcessStatus
.WAIT_CPU
);
154 private void handleSchedProcessExit(ITmfEvent event
) {
155 String host
= event
.getTrace().getHostId();
156 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
157 LttngSystemModel system
= getProvider().getSystem();
159 Integer tid
= EventField
.getInt(event
, eventLayout
.fieldTid());
160 LttngWorker task
= system
.findWorker(new HostThread(host
, tid
));
164 task
.setStatus(ProcessStatus
.EXIT
);
167 private void handleSchedProcessExec(ITmfEvent event
) {
168 String host
= event
.getTrace().getHostId();
169 Integer cpu
= NonNullUtils
.checkNotNull(TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
));
170 IKernelAnalysisEventLayout eventLayout
= getProvider().getEventLayout(event
.getTrace());
171 LttngSystemModel system
= getProvider().getSystem();
173 String filename
= EventField
.getString(event
, eventLayout
.fieldFilename());
174 LttngWorker task
= system
.getWorkerOnCpu(host
, cpu
);
178 task
.setName(filename
);