| /******************************************************************************* |
| * 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 |
| } |
| |
| } |