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
diff --git a/lttng/org.lttng.scope.lttng.kernel.core/src/org/lttng/scope/lttng/kernel/core/analysis/os/handlers/internal/SchedSwitchHandler.java b/lttng/org.lttng.scope.lttng.kernel.core/src/org/lttng/scope/lttng/kernel/core/analysis/os/handlers/internal/SchedSwitchHandler.java
new file mode 100644 (file)
index 0000000..595de8e
--- /dev/null
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.lttng.scope.lttng.kernel.core.analysis.os.handlers.internal;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.lttng.scope.lttng.kernel.core.analysis.os.Attributes;
+import org.lttng.scope.lttng.kernel.core.analysis.os.LinuxValues;
+import org.lttng.scope.lttng.kernel.core.analysis.os.StateValues;
+import org.lttng.scope.lttng.kernel.core.trace.layout.ILttngKernelEventLayout;
+
+import ca.polymtl.dorsal.libdelorean.ITmfStateSystemBuilder;
+import ca.polymtl.dorsal.libdelorean.exceptions.AttributeNotFoundException;
+import ca.polymtl.dorsal.libdelorean.exceptions.StateValueTypeException;
+import ca.polymtl.dorsal.libdelorean.statevalue.ITmfStateValue;
+import ca.polymtl.dorsal.libdelorean.statevalue.TmfStateValue;
+
+/**
+ * Scheduler switch event handler
+ */
+public class SchedSwitchHandler extends KernelEventHandler {
+
+    /**
+     * Constructor
+     *
+     * @param layout
+     *            event layout
+     */
+    public SchedSwitchHandler(ILttngKernelEventLayout layout) {
+        super(layout);
+    }
+
+    @Override
+    public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
+        Integer cpu = KernelEventHandlerUtils.getCpu(event);
+        if (cpu == null) {
+            return;
+        }
+
+        ITmfEventField content = event.getContent();
+        String prevProcessName = requireNonNull((String) content.getField(getLayout().fieldPrevComm()).getValue());
+        Integer prevTid = ((Long) content.getField(getLayout().fieldPrevTid()).getValue()).intValue();
+        Long prevState = requireNonNull((Long) content.getField(getLayout().fieldPrevState()).getValue());
+        Integer prevPrio = ((Long) content.getField(getLayout().fieldPrevPrio()).getValue()).intValue();
+        String nextProcessName = requireNonNull((String) content.getField(getLayout().fieldNextComm()).getValue());
+        Integer nextTid = ((Long) content.getField(getLayout().fieldNextTid()).getValue()).intValue();
+        Integer nextPrio = ((Long) content.getField(getLayout().fieldNextPrio()).getValue()).intValue();
+
+        /* Will never return null since "cpu" is null checked */
+        String formerThreadAttributeName = Attributes.buildThreadAttributeName(prevTid, cpu);
+        String currenThreadAttributeName = Attributes.buildThreadAttributeName(nextTid, cpu);
+
+        int nodeThreads = KernelEventHandlerUtils.getNodeThreads(ss);
+        int formerThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, formerThreadAttributeName);
+        int newCurrentThreadNode = ss.getQuarkRelativeAndAdd(nodeThreads, currenThreadAttributeName);
+
+        long timestamp = KernelEventHandlerUtils.getTimestamp(event);
+        /*
+         * Set the status of the process that got scheduled out. This will also
+         * set it's current CPU run queue accordingly.
+         */
+        setOldProcessStatus(ss, prevState, formerThreadNode, cpu, timestamp);
+
+        /* Set the status of the new scheduled process */
+        KernelEventHandlerUtils.setProcessToRunning(timestamp, newCurrentThreadNode, ss);
+
+        /*
+         * Set the current CPU run queue of the new process. Should be already
+         * set if we've seen the previous sched_wakeup, but doesn't hurt to set
+         * it here too.
+         */
+        int quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.CURRENT_CPU_RQ);
+        ITmfStateValue value = TmfStateValue.newValueInt(cpu);
+        ss.modifyAttribute(timestamp, value, quark);
+
+        /* Set the exec name of the former process */
+        setProcessExecName(ss, prevProcessName, formerThreadNode, timestamp);
+
+        /* Set the exec name of the new process */
+        setProcessExecName(ss, nextProcessName, newCurrentThreadNode, timestamp);
+
+        /* Set the current prio for the former process */
+        setProcessPrio(ss, prevPrio, formerThreadNode, timestamp);
+
+        /* Set the current prio for the new process */
+        setProcessPrio(ss, nextPrio, newCurrentThreadNode, timestamp);
+
+        /* Set the current scheduled process on the relevant CPU */
+        int currentCPUNode = KernelEventHandlerUtils.getCurrentCPUNode(cpu, ss);
+        setCpuProcess(ss, nextTid, timestamp, currentCPUNode);
+
+        /* Set the status of the CPU itself */
+        setCpuStatus(ss, nextTid, newCurrentThreadNode, timestamp, currentCPUNode);
+    }
+
+    private static void setOldProcessStatus(ITmfStateSystemBuilder ss,
+            long prevState, int formerThreadNode, int cpu, long timestamp) {
+        ITmfStateValue value;
+        boolean staysOnRunQueue = false;
+        /*
+         * Empirical observations and look into the linux code have
+         * shown that the TASK_STATE_MAX flag is used internally and
+         * |'ed with other states, most often the running state, so it
+         * is ignored from the prevState value.
+         *
+         * Since Linux 4.1, the TASK_NOLOAD state was created and
+         * TASK_STATE_MAX is now 2048. We use TASK_NOLOAD as the new max
+         * because it does not modify the displayed state value.
+         */
+        int state = (int) (prevState & (LinuxValues.TASK_NOLOAD - 1));
+
+        if (isRunning(state)) {
+            value = StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE;
+            staysOnRunQueue = true;
+        } else if (isWaiting(state)) {
+            value = StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE;
+        } else if (isDead(state)) {
+            value = TmfStateValue.nullValue();
+        } else {
+            value = StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE;
+        }
+        ss.modifyAttribute(timestamp, value, formerThreadNode);
+
+        int quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.CURRENT_CPU_RQ);
+        if (staysOnRunQueue) {
+            /*
+             * Set the thread's run queue. This will often be redundant with
+             * previous events, but it may be the first time we see the
+             * information too.
+             */
+            value = TmfStateValue.newValueInt(cpu);
+        } else {
+            value = TmfStateValue.nullValue();
+        }
+        ss.modifyAttribute(timestamp, value, quark);
+    }
+
+    private static boolean isDead(int state) {
+        return (state & LinuxValues.TASK_DEAD) != 0;
+    }
+
+    private static boolean isWaiting(int state) {
+        return (state & (LinuxValues.TASK_INTERRUPTIBLE | LinuxValues.TASK_UNINTERRUPTIBLE)) != 0;
+    }
+
+    private static boolean isRunning(int state) {
+        // special case, this means ALL STATES ARE 0
+        // this is effectively an anti-state
+        return state == 0;
+    }
+
+    private static void setCpuStatus(ITmfStateSystemBuilder ss, Integer nextTid, Integer newCurrentThreadNode, long timestamp, int currentCPUNode)
+            throws StateValueTypeException, AttributeNotFoundException {
+        int quark;
+        ITmfStateValue value;
+        if (nextTid > 0) {
+            /* Check if the entering process is in kernel or user mode */
+            quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.SYSTEM_CALL);
+            ITmfStateValue queryOngoingState = ss.queryOngoingState(quark);
+            if (queryOngoingState.isNull()) {
+                value = StateValues.CPU_STATUS_RUN_USERMODE_VALUE;
+            } else {
+                value = StateValues.CPU_STATUS_RUN_SYSCALL_VALUE;
+            }
+        } else {
+            value = StateValues.CPU_STATUS_IDLE_VALUE;
+        }
+        ss.modifyAttribute(timestamp, value, currentCPUNode);
+    }
+
+    private static void setCpuProcess(ITmfStateSystemBuilder ss, Integer nextTid, long timestamp, int currentCPUNode)
+            throws StateValueTypeException, AttributeNotFoundException {
+        int quark;
+        ITmfStateValue value;
+        quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
+        value = TmfStateValue.newValueInt(nextTid);
+        ss.modifyAttribute(timestamp, value, quark);
+    }
+
+    private static void setProcessPrio(ITmfStateSystemBuilder ss, Integer prio, Integer threadNode, long timestamp)
+            throws StateValueTypeException, AttributeNotFoundException {
+        int quark;
+        ITmfStateValue value;
+        quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.PRIO);
+        value = TmfStateValue.newValueInt(prio);
+        ss.modifyAttribute(timestamp, value, quark);
+    }
+
+    private static void setProcessExecName(ITmfStateSystemBuilder ss, String processName, Integer threadNode, long timestamp)
+            throws StateValueTypeException, AttributeNotFoundException {
+        int quark;
+        ITmfStateValue value;
+        quark = ss.getQuarkRelativeAndAdd(threadNode, Attributes.EXEC_NAME);
+        value = TmfStateValue.newValueString(processName);
+        ss.modifyAttribute(timestamp, value, quark);
+    }
+
+}
This page took 0.026012 seconds and 5 git commands to generate.