Import lttng.kernel.core plugins from Scope
[deliverable/tracecompass.git] / lttng / org.lttng.scope.lttng.kernel.core / src / org / lttng / scope / lttng / kernel / core / analysis / os / handlers / internal / SchedSwitchHandler.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
12
13 package org.lttng.scope.lttng.kernel.core.analysis.os.handlers.internal;
14
15 import static java.util.Objects.requireNonNull;
16
17 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
18 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
19 import org.lttng.scope.lttng.kernel.core.analysis.os.Attributes;
20 import org.lttng.scope.lttng.kernel.core.analysis.os.LinuxValues;
21 import org.lttng.scope.lttng.kernel.core.analysis.os.StateValues;
22 import org.lttng.scope.lttng.kernel.core.trace.layout.ILttngKernelEventLayout;
23
24 import ca.polymtl.dorsal.libdelorean.ITmfStateSystemBuilder;
25 import ca.polymtl.dorsal.libdelorean.exceptions.AttributeNotFoundException;
26 import ca.polymtl.dorsal.libdelorean.exceptions.StateValueTypeException;
27 import ca.polymtl.dorsal.libdelorean.statevalue.ITmfStateValue;
28 import ca.polymtl.dorsal.libdelorean.statevalue.TmfStateValue;
29
30 /**
31 * Scheduler switch event handler
32 */
33 public class SchedSwitchHandler extends KernelEventHandler {
34
35 /**
36 * Constructor
37 *
38 * @param layout
39 * event layout
40 */
41 public SchedSwitchHandler(ILttngKernelEventLayout layout) {
42 super(layout);
43 }
44
45 @Override
46 public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
47 Integer cpu = KernelEventHandlerUtils.getCpu(event);
48 if (cpu == null) {
49 return;
50 }
51
52 ITmfEventField content = event.getContent();
53 String prevProcessName = requireNonNull((String) content.getField(getLayout().fieldPrevComm()).getValue());
54 Integer prevTid = ((Long) content.getField(getLayout().fieldPrevTid()).getValue()).intValue();
55 Long prevState = requireNonNull((Long) content.getField(getLayout().fieldPrevState()).getValue());
56 Integer prevPrio = ((Long) content.getField(getLayout().fieldPrevPrio()).getValue()).intValue();
57 String nextProcessName = requireNonNull((String) content.getField(getLayout().fieldNextComm()).getValue());
58 Integer nextTid = ((Long) content.getField(getLayout().fieldNextTid()).getValue()).intValue();
59 Integer nextPrio = ((Long) content.getField(getLayout().fieldNextPrio()).getValue()).intValue();
60
61 /* Will never return null since "cpu" is null checked */
62 String formerThreadAttributeName = Attributes.buildThreadAttributeName(prevTid, cpu);
63 String currenThreadAttributeName = Attributes.buildThreadAttributeName(nextTid, cpu);
64
65 int nodeThreads = KernelEventHandlerUtils.getNodeThreads(ss);
66 int formerThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, formerThreadAttributeName);
67 int newCurrentThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, currenThreadAttributeName);
68
69 long timestamp = KernelEventHandlerUtils.getTimestamp(event);
70 /*
71 * Set the status of the process that got scheduled out. This will also
72 * set it's current CPU run queue accordingly.
73 */
74 setOldProcessStatus(ss, prevState, formerThreadNode, cpu, timestamp);
75
76 /* Set the status of the new scheduled process */
77 KernelEventHandlerUtils.setProcessToRunning(timestamp, newCurrentThreadNode, ss);
78
79 /*
80 * Set the current CPU run queue of the new process. Should be already
81 * set if we've seen the previous sched_wakeup, but doesn't hurt to set
82 * it here too.
83 */
84 int quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.CURRENT_CPU_RQ);
85 ITmfStateValue value = TmfStateValue.newValueInt(cpu);
86 ss.modifyAttribute(timestamp, value, quark);
87
88 /* Set the exec name of the former process */
89 setProcessExecName(ss, prevProcessName, formerThreadNode, timestamp);
90
91 /* Set the exec name of the new process */
92 setProcessExecName(ss, nextProcessName, newCurrentThreadNode, timestamp);
93
94 /* Set the current prio for the former process */
95 setProcessPrio(ss, prevPrio, formerThreadNode, timestamp);
96
97 /* Set the current prio for the new process */
98 setProcessPrio(ss, nextPrio, newCurrentThreadNode, timestamp);
99
100 /* Set the current scheduled process on the relevant CPU */
101 int currentCPUNode = KernelEventHandlerUtils.getCurrentCPUNode(cpu, ss);
102 setCpuProcess(ss, nextTid, timestamp, currentCPUNode);
103
104 /* Set the status of the CPU itself */
105 setCpuStatus(ss, nextTid, newCurrentThreadNode, timestamp, currentCPUNode);
106 }
107
108 private static void setOldProcessStatus(ITmfStateSystemBuilder ss,
109 long prevState, int formerThreadNode, int cpu, long timestamp) {
110 ITmfStateValue value;
111 boolean staysOnRunQueue = false;
112 /*
113 * Empirical observations and look into the linux code have
114 * shown that the TASK_STATE_MAX flag is used internally and
115 * |'ed with other states, most often the running state, so it
116 * is ignored from the prevState value.
117 *
118 * Since Linux 4.1, the TASK_NOLOAD state was created and
119 * TASK_STATE_MAX is now 2048. We use TASK_NOLOAD as the new max
120 * because it does not modify the displayed state value.
121 */
122 int state = (int) (prevState & (LinuxValues.TASK_NOLOAD - 1));
123
124 if (isRunning(state)) {
125 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
126 staysOnRunQueue = true;
127 } else if (isWaiting(state)) {
128 value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE;
129 } else if (isDead(state)) {
130 value = TmfStateValue.nullValue();
131 } else {
132 value = StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE;
133 }
134 ss.modifyAttribute(timestamp, value, formerThreadNode);
135
136 int quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.CURRENT_CPU_RQ);
137 if (staysOnRunQueue) {
138 /*
139 * Set the thread's run queue. This will often be redundant with
140 * previous events, but it may be the first time we see the
141 * information too.
142 */
143 value = TmfStateValue.newValueInt(cpu);
144 } else {
145 value = TmfStateValue.nullValue();
146 }
147 ss.modifyAttribute(timestamp, value, quark);
148 }
149
150 private static boolean isDead(int state) {
151 return (state & LinuxValues.TASK_DEAD) != 0;
152 }
153
154 private static boolean isWaiting(int state) {
155 return (state & (LinuxValues.TASK_INTERRUPTIBLE | LinuxValues.TASK_UNINTERRUPTIBLE)) != 0;
156 }
157
158 private static boolean isRunning(int state) {
159 // special case, this means ALL STATES ARE 0
160 // this is effectively an anti-state
161 return state == 0;
162 }
163
164 private static void setCpuStatus(ITmfStateSystemBuilder ss, Integer nextTid, Integer newCurrentThreadNode, long timestamp, int currentCPUNode)
165 throws StateValueTypeException, AttributeNotFoundException {
166 int quark;
167 ITmfStateValue value;
168 if (nextTid > 0) {
169 /* Check if the entering process is in kernel or user mode */
170 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
171 ITmfStateValue queryOngoingState = ss.queryOngoingState(quark);
172 if (queryOngoingState.isNull()) {
173 value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
174 } else {
175 value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
176 }
177 } else {
178 value = StateValues.CPU_STATUS_IDLE_VALUE;
179 }
180 ss.modifyAttribute(timestamp, value, currentCPUNode);
181 }
182
183 private static void setCpuProcess(ITmfStateSystemBuilder ss, Integer nextTid, long timestamp, int currentCPUNode)
184 throws StateValueTypeException, AttributeNotFoundException {
185 int quark;
186 ITmfStateValue value;
187 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
188 value = TmfStateValue.newValueInt(nextTid);
189 ss.modifyAttribute(timestamp, value, quark);
190 }
191
192 private static void setProcessPrio(ITmfStateSystemBuilder ss, Integer prio, Integer threadNode, long timestamp)
193 throws StateValueTypeException, AttributeNotFoundException {
194 int quark;
195 ITmfStateValue value;
196 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.PRIO);
197 value = TmfStateValue.newValueInt(prio);
198 ss.modifyAttribute(timestamp, value, quark);
199 }
200
201 private static void setProcessExecName(ITmfStateSystemBuilder ss, String processName, Integer threadNode, long timestamp)
202 throws StateValueTypeException, AttributeNotFoundException {
203 int quark;
204 ITmfStateValue value;
205 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.EXEC_NAME);
206 value = TmfStateValue.newValueString(processName);
207 ss.modifyAttribute(timestamp, value, quark);
208 }
209
210 }
This page took 0.035279 seconds and 5 git commands to generate.