diff mbox series

[23/24] kernel-shark: Clickable sched_event plugin shapes

Message ID 20210201172358.175407-24-y.karadz@gmail.com (mailing list archive)
State Superseded
Headers show
Series Complete the KernelShark v2 transformation | expand

Commit Message

Yordan Karadzhov Feb. 1, 2021, 5:23 p.m. UTC
Here we make the latency boxes plotted by the sched_event plugin
clickable. When the box is clicked, the two events determining
the latency (sched_waking and sched_switch) are selected with the
markers. This is achieved by providing an implementation of the
corresponding interface of virtual functions in the definition
of the LatencyBox class. We also need to provide the plugin with
a pointer to the KsMainWindow object (the GUI itself) such that
the plugin can manipulate the markers.
---
 src/plugins/CMakeLists.txt  | 25 ++++++++++++++--
 src/plugins/SchedEvents.cpp | 58 +++++++++++++++++++++++++++++++++++--
 src/plugins/sched_events.c  |  7 +++++
 src/plugins/sched_events.h  |  3 ++
 4 files changed, 89 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index dc0c320..f8ecba6 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -17,9 +17,30 @@  function(BUILD_PLUGIN)
 
 endfunction()
 
+function(BUILD_GUI_PLUGIN)
+    set(options)
+    set(oneValueArgs NAME MOC)
+    set(multiValueArgs SOURCE)
+    cmake_parse_arguments(ADD_PLUGIN "${options}"
+                                     "${oneValueArgs}"
+                                     "${multiValueArgs}"
+                                     ${ARGN})
+
+    message(STATUS ${ADD_PLUGIN_NAME})
+
+    QT5_WRAP_CPP(plugin_moc ${ADD_PLUGIN_MOC})
+
+    add_library(${ADD_PLUGIN_NAME} SHARED ${plugin_moc} ${ADD_PLUGIN_SOURCE})
+    set_target_properties(${ADD_PLUGIN_NAME} PROPERTIES PREFIX "plugin-")
+    target_link_libraries(${ADD_PLUGIN_NAME} kshark kshark-gui)
+
+endfunction()
+
 set(PLUGIN_LIST "")
-BUILD_PLUGIN(NAME sched_events
-             SOURCE sched_events.c SchedEvents.cpp)
+
+BUILD_GUI_PLUGIN(NAME sched_events
+                 SOURCE sched_events.c SchedEvents.cpp)
+
 list(APPEND PLUGIN_LIST "sched_events")
 
 BUILD_PLUGIN(NAME missed_events
diff --git a/src/plugins/SchedEvents.cpp b/src/plugins/SchedEvents.cpp
index c85a059..a81182e 100644
--- a/src/plugins/SchedEvents.cpp
+++ b/src/plugins/SchedEvents.cpp
@@ -20,15 +20,69 @@ 
 #include "plugins/sched_events.h"
 #include "KsPlotTools.hpp"
 #include "KsPlugins.hpp"
+#include "KsMainWindow.hpp"
 
 using namespace KsPlot;
 
+static KsMainWindow *ks_ptr;
+
+/**
+ * @brief Provide the plugin with a pointer to the KsMainWindow object (the GUI
+ * itself) such that the plugin can manipulate the GUI.
+ */
+void *plugin_set_gui_ptr(void *gui_ptr)
+{
+	ks_ptr = static_cast<KsMainWindow *>(gui_ptr);
+	return nullptr;
+}
+
+/**
+ * This class represents the graphical element visualizing the latency between
+ *  sched_waking and sched_switch events.
+ */
+class LatencyBox : public Rectangle
+{
+	/** On double click do. */
+	void _doubleClick() const override
+	{
+		ks_ptr->markEntry(_data[1]->entry, DualMarkerState::B);
+		ks_ptr->markEntry(_data[0]->entry, DualMarkerState::A);
+	}
+
+public:
+	/** The trace record data that corresponds to this LatencyBox. */
+	std::vector<kshark_data_field_int64 *>	_data;
+
+	/**
+	 * @brief Distance between the click and the shape. Used to decide if
+	 *	  the double click action must be executed.
+	 *
+	 * @param x: X coordinate of the click.
+	 * @param y: Y coordinate of the click.
+	 *
+	 * @returns If the click is inside the box, the distance is zero.
+	 *	    Otherwise infinity.
+	 */
+	double distance(int x, int y) const override
+	{
+		if (x < pointX(0) || x > pointX(2))
+			return std::numeric_limits<double>::max();
+
+		if (y < pointY(0) || y > pointY(1))
+			return std::numeric_limits<double>::max();
+
+		return 0;
+	}
+};
+
 static PlotObject *makeShape(std::vector<const Graph *> graph,
 			     std::vector<int> bins,
-			     std::vector<kshark_data_field_int64 *>,
+			     std::vector<kshark_data_field_int64 *> data,
 			     Color col, float size)
 {
-	Rectangle *rec = new KsPlot::Rectangle;
+	LatencyBox *rec = new LatencyBox;
+	rec->_data = data;
+
 	Point p0 = graph[0]->bin(bins[0])._base;
 	Point p1 = graph[0]->bin(bins[1])._base;
 	int height = graph[0]->height() * .3;
diff --git a/src/plugins/sched_events.c b/src/plugins/sched_events.c
index 1596880..ac4a7bf 100644
--- a/src/plugins/sched_events.c
+++ b/src/plugins/sched_events.c
@@ -216,3 +216,10 @@  int KSHARK_PLOT_PLUGIN_DEINITIALIZER(struct kshark_data_stream *stream)
 
 	return 1;
 }
+
+/** Initialize the control interface of the plugin. */
+void *KSHARK_MENU_PLUGIN_INITIALIZER(void *gui_ptr)
+{
+	printf("--> sched init menu\n");
+	return plugin_set_gui_ptr(gui_ptr);
+}
diff --git a/src/plugins/sched_events.h b/src/plugins/sched_events.h
index 4c57606..78cfda0 100644
--- a/src/plugins/sched_events.h
+++ b/src/plugins/sched_events.h
@@ -53,6 +53,7 @@  struct plugin_sched_context {
 	struct kshark_data_container	*sw_data;
 };
 
+/** A general purpose macro is used to define plugin context. */
 KS_DEFINE_PLUGIN_CONTEXT(struct plugin_sched_context);
 
 /** The type of the data field stored in the kshark_data_container object. */
@@ -65,6 +66,8 @@  int plugin_sched_get_prev_state(ks_num_field_t field);
 void plugin_draw(struct kshark_cpp_argv *argv, int sd, int pid,
 		 int draw_action);
 
+void *plugin_set_gui_ptr(void *gui_ptr);
+
 #ifdef __cplusplus
 }
 #endif