blob: 3784d784ee7c6246fd0a43ea749b3a458404deca [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.tracecompass.analysis.graph.core.building.AbstractTraceEventHandler;
import org.eclipse.tracecompass.analysis.os.linux.core.execution.graph.OsExecutionGraphProvider;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.Lttng28EventLayout;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.trace.layout.LttngEventLayout;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventType;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
import org.eclipse.tracecompass.tmf.core.trace.TmfEventTypeCollectionHelper;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
/**
* Holds the fields commons to all handler classes.
*
* @author Francis Giraldeau <francis.giraldeau@gmail.com>
*
*/
public class BaseHandler extends AbstractTraceEventHandler {
private final OsExecutionGraphProvider fProvider;
/**
* The fWakeupEventMap is populated with the prefered wake-up event for a
* given trace. Here is the possible values for LTTng, that are in priority
* order:
*
* <pre>
* - linux all versions and lttng all versions: sched_ttwu
* - linux >= 4.3 and lttng >= 2.8: sched_waking + sched_wakeup_new
* - linux < 3.8.0: sched_wakeup + sched_wakeup_new
* </pre>
*
* The acronym ttwu stands for "Try To Wake Up". The sched_ttwu requires
* lttng-modules addons and works with all versions of linux and LTTng. This
* event alone is sufficient, because it a placeholder for both sched_wakeup
* and sched_wakeup_new. The event sched_wakeup_new is a special case, and
* is emitted when a process is created and is scheduled for the first time.
* Therefore, we use in priority sched_ttwu if available, then sched_waking
* and as a last resort, we use sched_wakup, but this last option will work
* only for older kernels.
*
* If the trace has more than one type of wake-up event enabled, we ensure
* that only one type will be processed.
*/
private Map<ITmfTrace, String> fWakeupEventMap;
BaseHandler(OsExecutionGraphProvider provider, int priority) {
super(priority);
fProvider = provider;
fWakeupEventMap = new HashMap<>();
ITmfTrace trace = getProvider().getTrace();
Collection<ITmfTrace> traceSet = TmfTraceManager.getTraceSet(trace);
for (ITmfTrace traceItem : traceSet) {
IKernelAnalysisEventLayout layout = getProvider().getEventLayout(traceItem);
/* default wake-up event */
String wakeupEvent = layout.eventSchedProcessWakeup();
if (traceItem instanceof ITmfTraceWithPreDefinedEvents) {
Set<? extends ITmfEventType> content = ((ITmfTraceWithPreDefinedEvents) traceItem).getContainedEventTypes();
Set<String> traceEvents = TmfEventTypeCollectionHelper.getEventNames(content);
/*
* FIXME: downcast in the client should be avoided
*/
if (layout instanceof LttngEventLayout) {
LttngEventLayout lttngLayout = (LttngEventLayout) layout;
if (traceEvents.contains(lttngLayout.eventSchedProcessTTWU())) {
/* use sched_ttwu if available */
wakeupEvent = lttngLayout.eventSchedProcessTTWU();
} else if (layout instanceof Lttng28EventLayout) {
/* use sched_waking if available */
Lttng28EventLayout layout28 = (Lttng28EventLayout) layout;
if (traceEvents.contains(layout28.eventSchedProcessWaking())) {
wakeupEvent = layout28.eventSchedProcessWaking();
}
}
}
}
fWakeupEventMap.put(traceItem, wakeupEvent);
}
}
/**
* Returns the parent graph provider
*
* @return the graph provider
*/
public OsExecutionGraphProvider getProvider() {
return fProvider;
}
/**
* Return if this event is a wake-up event for this trace
*
* @param event
* the trace to check
* @return true if this is a wake-up event to process, false otherwise
*/
public boolean isWakeupEvent(ITmfEvent event) {
String eventName = event.getName();
ITmfTrace trace = event.getTrace();
IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(event.getTrace());
String wakeupEventName = NonNullUtils.nullToEmptyString(fWakeupEventMap.get(trace));
/*
* First, check if sched_ttwu is the current wake-up event for this
* trace
*/
if (eventLayout instanceof LttngEventLayout) {
LttngEventLayout layoutDefault = (LttngEventLayout) eventLayout;
if (wakeupEventName.equals(layoutDefault.eventSchedProcessTTWU())) {
return eventName.equals(layoutDefault.eventSchedProcessTTWU());
}
}
/* Fall back to built-in sched_waking and sched_wakeup_new */
if (eventLayout instanceof Lttng28EventLayout) {
Lttng28EventLayout layout28 = (Lttng28EventLayout) eventLayout;
if (wakeupEventName.equals(layout28.eventSchedProcessWaking())) {
return (eventName.equals(layout28.eventSchedProcessWaking()) ||
eventName.equals(layout28.eventSchedProcessWakeupNew()));
}
}
/* Legacy support using built-in sched_wakeup and sched_wakeup_new */
if (wakeupEventName.equals(eventLayout.eventSchedProcessWakeup())) {
return eventLayout.eventsSchedWakeup().contains(eventName);
}
return false;
}
@Override
public void handleEvent(ITmfEvent event) {
// Do nothing
}
}