a30d37ca59cef17dd42e9968b9d9b931985e763e
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / internal / analysis / os / linux / core / kernel / handlers / 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.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.handlers;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.LinuxValues;
18 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
19 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
20 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
21 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
22 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
23 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
24 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
25 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
26 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
27
28 /**
29 * Scheduler switch event handler
30 */
31 public class SchedSwitchHandler extends KernelEventHandler {
32
33 /**
34 * Constructor
35 *
36 * @param layout
37 * event layout
38 */
39 public SchedSwitchHandler(IKernelAnalysisEventLayout layout) {
40 super(layout);
41 }
42
43 @Override
44 public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
45 Integer cpu = KernelEventHandlerUtils.getCpu(event);
46 if (cpu == null) {
47 return;
48 }
49
50 ITmfEventField content = event.getContent();
51 String prevProcessName = checkNotNull((String) content.getField(getLayout().fieldPrevComm()).getValue());
52 Integer prevTid = ((Long) content.getField(getLayout().fieldPrevTid()).getValue()).intValue();
53 Long prevState = checkNotNull((Long) content.getField(getLayout().fieldPrevState()).getValue());
54 Integer prevPrio = ((Long) content.getField(getLayout().fieldPrevPrio()).getValue()).intValue();
55 String nextProcessName = checkNotNull((String) content.getField(getLayout().fieldNextComm()).getValue());
56 Integer nextTid = ((Long) content.getField(getLayout().fieldNextTid()).getValue()).intValue();
57 Integer nextPrio = ((Long) content.getField(getLayout().fieldNextPrio()).getValue()).intValue();
58
59 /* Will never return null since "cpu" is null checked */
60 String formerThreadAttributeName = Attributes.buildThreadAttributeName(prevTid, cpu);
61 String currenThreadAttributeName = Attributes.buildThreadAttributeName(nextTid, cpu);
62
63 int nodeThreads = KernelEventHandlerUtils.getNodeThreads(ss);
64 int formerThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, formerThreadAttributeName);
65 int newCurrentThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, currenThreadAttributeName);
66
67 long timestamp = KernelEventHandlerUtils.getTimestamp(event);
68 /* Set the status of the process that got scheduled out. */
69 setOldProcessStatus(ss, prevState, formerThreadNode, timestamp);
70
71 /* Set the status of the new scheduled process */
72 KernelEventHandlerUtils.setProcessToRunning(timestamp, newCurrentThreadNode, ss);
73
74 /* Set the exec name of the former process */
75 setProcessExecName(ss, prevProcessName, formerThreadNode, timestamp);
76
77 /* Set the exec name of the new process */
78 setProcessExecName(ss, nextProcessName, newCurrentThreadNode, timestamp);
79
80 /* Set the current prio for the former process */
81 setProcessPrio(ss, prevPrio, formerThreadNode, timestamp);
82
83 /* Set the current prio for the new process */
84 setProcessPrio(ss, nextPrio, newCurrentThreadNode, timestamp);
85
86 /* Make sure the PPID and system_call sub-attributes exist */
87 ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
88 ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.PPID);
89
90 /* Set the current scheduled process on the relevant CPU */
91 int currentCPUNode = KernelEventHandlerUtils.getCurrentCPUNode(cpu, ss);
92 setCpuProcess(ss, nextTid, timestamp, currentCPUNode);
93
94 /* Set the status of the CPU itself */
95 setCpuStatus(ss, nextTid, newCurrentThreadNode, timestamp, currentCPUNode);
96 }
97
98 private static void setOldProcessStatus(ITmfStateSystemBuilder ss, Long prevState, Integer formerThreadNode, long timestamp) {
99 ITmfStateValue value;
100 /*
101 * Empirical observations and look into the linux code have
102 * shown that the TASK_STATE_MAX flag is used internally and
103 * |'ed with other states, most often the running state, so it
104 * is ignored from the prevState value.
105 *
106 * Since Linux 4.1, the TASK_NOLOAD state was created and
107 * TASK_STATE_MAX is now 2048. We use TASK_NOLOAD as the new max
108 * because it does not modify the displayed state value.
109 */
110 int state = (int) (prevState & (LinuxValues.TASK_NOLOAD - 1));
111
112 if (isRunning(state)) {
113 value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
114 } else if (isWaiting(state)) {
115 value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE;
116 } else if (isDead(state)) {
117 value = TmfStateValue.nullValue();
118 } else {
119 value = StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE;
120 }
121 int quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS);
122 ss.modifyAttribute(timestamp, value, quark);
123
124 }
125
126 private static boolean isDead(int state) {
127 return (state & LinuxValues.TASK_DEAD) != 0;
128 }
129
130 private static boolean isWaiting(int state) {
131 return (state & (LinuxValues.TASK_INTERRUPTIBLE | LinuxValues.TASK_UNINTERRUPTIBLE)) != 0;
132 }
133
134 private static boolean isRunning(int state) {
135 // special case, this means ALL STATES ARE 0
136 // this is effectively an anti-state
137 return state == 0;
138 }
139
140 private static void setCpuStatus(ITmfStateSystemBuilder ss, Integer nextTid, Integer newCurrentThreadNode, long timestamp, int currentCPUNode) {
141 int quark;
142 ITmfStateValue value;
143 if (nextTid > 0) {
144 /* Check if the entering process is in kernel or user mode */
145 quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
146 ITmfStateValue queryOngoingState = ss.queryOngoingState(quark);
147 if (queryOngoingState.isNull()) {
148 value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
149 } else {
150 value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
151 }
152 } else {
153 value = StateValues.CPU_STATUS_IDLE_VALUE;
154 }
155 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
156 ss.modifyAttribute(timestamp, value, quark);
157 }
158
159 private static void setCpuProcess(ITmfStateSystemBuilder ss, Integer nextTid, long timestamp, int currentCPUNode) {
160 int quark;
161 ITmfStateValue value;
162 quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
163 value = TmfStateValue.newValueInt(nextTid);
164 ss.modifyAttribute(timestamp, value, quark);
165 }
166
167 private static void setProcessPrio(ITmfStateSystemBuilder ss, Integer prio, Integer threadNode, long timestamp) {
168 int quark;
169 ITmfStateValue value;
170 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.PRIO);
171 value = TmfStateValue.newValueInt(prio);
172 ss.modifyAttribute(timestamp, value, quark);
173 }
174
175 private static void setProcessExecName(ITmfStateSystemBuilder ss, String processName, Integer threadNode, long timestamp) {
176 int quark;
177 ITmfStateValue value;
178 quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.EXEC_NAME);
179 value = TmfStateValue.newValueString(processName);
180 ss.modifyAttribute(timestamp, value, quark);
181 }
182
183 }
This page took 0.037313 seconds and 4 git commands to generate.