/*******************************************************************************
* 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 v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.handlers;
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.analysis.graph.building.LttngKernelExecGraphProvider;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.building.LttngKernelExecGraphProvider.Context;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngInterruptContext;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.graph.model.LttngSystemModel;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
/**
* Event Handler to handle the interrupt context stack of the model
*
* @author Francis Giraldeau
* @author Geneviève Bastien
*/
public class EventContextHandler extends BaseHandler {
/**
* Constructor
*
* @param provider
* The parent graph provider
*/
public EventContextHandler(LttngKernelExecGraphProvider provider) {
super(provider);
}
@Override
public void handleEvent(ITmfEvent event) {
String eventName = event.getName();
IKernelAnalysisEventLayout eventLayout = getProvider().getEventLayout(event.getTrace());
if (eventName.equals(eventLayout.eventSoftIrqEntry())) {
handleSoftirqEntry(event);
} else if (eventName.equals(eventLayout.eventSoftIrqExit())) {
handleSoftirqExit(event);
} else if (eventName.equals(eventLayout.eventHRTimerExpireEntry())) {
handleHrtimerExpireEntry(event);
} else if (eventName.equals(eventLayout.eventHRTimerExpireExit())) {
handleHrtimerExpireExit(event);
} else if (eventName.equals(eventLayout.eventIrqHandlerEntry())) {
handleIrqHandlerEntry(event);
} else if (eventName.equals(eventLayout.eventIrqHandlerExit())) {
handleIrqHandlerExit(event);
} else if (isIpiEntry(event)) {
handleIpiEntry(event);
} else if (isIpiExit(event)) {
handleIpiExit(event);
}
}
private void pushInterruptContext(ITmfEvent event, Context ctx) {
Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
LttngSystemModel system = getProvider().getSystem();
LttngInterruptContext interruptCtx = new LttngInterruptContext(event, ctx);
system.pushContextStack(event.getTrace().getHostId(), cpu, interruptCtx);
}
private void popInterruptContext(ITmfEvent event, Context ctx) {
Integer cpu = NonNullUtils.checkNotNull(TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event));
LttngSystemModel system = getProvider().getSystem();
/* TODO: add a warning bookmark if the interrupt context is not coherent */
LttngInterruptContext interruptCtx = system.peekContextStack(event.getTrace().getHostId(), cpu);
if (interruptCtx.getContext() == ctx) {
system.popContextStack(event.getTrace().getHostId(), cpu);
}
}
private void handleSoftirqEntry(ITmfEvent event) {
pushInterruptContext(event, Context.SOFTIRQ);
}
private void handleSoftirqExit(ITmfEvent event) {
popInterruptContext(event, Context.SOFTIRQ);
}
private void handleIrqHandlerEntry(ITmfEvent event) {
pushInterruptContext(event, Context.IRQ);
}
private void handleIrqHandlerExit(ITmfEvent event) {
popInterruptContext(event, Context.IRQ);
}
private void handleHrtimerExpireEntry(ITmfEvent event) {
pushInterruptContext(event, Context.HRTIMER);
}
private void handleHrtimerExpireExit(ITmfEvent event) {
popInterruptContext(event, Context.HRTIMER);
}
private void handleIpiEntry(ITmfEvent event) {
pushInterruptContext(event, Context.IPI);
}
private void handleIpiExit(ITmfEvent event) {
popInterruptContext(event, Context.IPI);
}
}