blob: 4daea79709a1647f5a057b5905ab0563e7efb09a [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1 */
/*
* Copyright (C) 2019 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
*/
/**
* @file VirtComboPlotTools.hpp
* @brief Tools for plotting Virt Combs.
*/
// C++
#include <iostream>
// KernelShark
#include "KsPlugins.hpp"
#include "KsPlotTools.hpp"
static void drawVirt(kshark_trace_histo *histo,
KsPlot::Graph *hostGraph,
int sdHost, int pidHost,
int vcpuEntryId, int vcpuExitId,
KsPlot::PlotObjList *shapes)
{
int guestBaseY = hostGraph->bin(0)._base.y() - hostGraph->height();
int gapHeight = hostGraph->height() * .3;
KsPlot::VirtBridge *bridge = new KsPlot::VirtBridge();
KsPlot::VirtGap *gap = new KsPlot::VirtGap(gapHeight);
const kshark_entry *entry, *exit;
ssize_t indexEntry, indexExit;
int values[2] = {-1, pidHost};
bridge->_size = 2;
bridge->_visible = false;
bridge->setEntryHost(hostGraph->bin(0)._base.x(), guestBaseY);
bridge->setEntryGuest(hostGraph->bin(0)._base.x(), guestBaseY);
gap->_size = 2;
gap->_visible = false;
gap->_exitPoint = KsPlot::Point(hostGraph->bin(0)._base.x(),
guestBaseY);
auto lamStartBridg = [&] (int bin) {
if (!bridge)
bridge = new KsPlot::VirtBridge();
bridge->setEntryHost(hostGraph->bin(bin)._base.x(),
hostGraph->bin(bin)._base.y());
bridge->setEntryGuest(hostGraph->bin(bin)._base.x(),
guestBaseY);
bridge->_color = hostGraph->bin(bin)._color;
};
auto lamCloseBridg = [&] (int bin) {
if (!bridge)
return;
bridge->setExitGuest(hostGraph->bin(bin)._base.x(),
guestBaseY);
bridge->setExitHost(hostGraph->bin(bin)._base.x(),
hostGraph->bin(bin)._base.y());
bridge->_color = hostGraph->bin(bin)._color;
bridge->_visible = true;
bridge->_size = -1; // Default size
shapes->push_front(bridge);
bridge = nullptr;
};
auto lamStartGap = [&] (int bin) {
if (!gap)
gap = new KsPlot::VirtGap(gapHeight);
gap->_exitPoint =
KsPlot::Point(hostGraph->bin(bin)._base.x(),
guestBaseY);
};
auto lamCloseGap = [&] (int bin) {
if (!gap)
return;
gap->_entryPoint =
KsPlot::Point(hostGraph->bin(bin)._base.x(),
guestBaseY);
gap->_visible = true;
gap->_size = -1; // Default size
shapes->push_front(gap);
gap = nullptr;
};
for (int bin = 0; bin < histo->n_bins; ++bin) {
values[0] = vcpuEntryId;
entry = ksmodel_get_entry_back(histo, bin, true,
kshark_match_event_and_pid,
sdHost, values,
nullptr, &indexEntry);
values[0] = vcpuExitId;
exit = ksmodel_get_entry_back(histo, bin, true,
kshark_match_event_and_pid,
sdHost, values,
nullptr, &indexExit);
if (entry && !exit) {
lamStartBridg(bin);
lamCloseGap(bin);
}
if (exit && !entry) {
lamCloseBridg(bin);
lamStartGap(bin);
}
if (exit && entry) {
if (bridge && bridge->_visible)
lamCloseBridg(bin);
if (gap && gap->_visible)
lamCloseGap(bin);
if (indexEntry > indexExit) {
lamStartBridg(bin);
} else {
lamStartBridg(bin);
lamCloseBridg(bin);
lamStartGap(bin);
}
}
}
if (bridge && bridge->_visible) {
bridge->setExitGuest(hostGraph->bin(histo->n_bins - 1)._base.x(),
guestBaseY);
bridge->setExitHost(hostGraph->bin(histo->n_bins - 1)._base.x(),
guestBaseY);
bridge->_size = -1; // Default size
shapes->push_front(bridge);
}
}
static void drawVirtCombos(kshark_cpp_argv *argv_c,
int sdHost, int pidHost,
int entryId, int exitId,
int draw_action)
{
KsCppArgV *argvCpp;
if (!(draw_action & KSHARK_HOST_DRAW) || pidHost == 0)
return;
argvCpp = KS_ARGV_TO_CPP(argv_c);
try {
drawVirt(argvCpp->_histo,
argvCpp->_graph,
sdHost, pidHost,
entryId,
exitId,
argvCpp->_shapes);
} catch (const std::exception &exc) {
std::cerr << "Exception in drawVirtCombos()\n" << exc.what();
}
}