[PATCH v2 1/4] kernelshark: Adding infrastructure for GUI plugins

From: Yordan Karadzhov (VMware)
Date: Fri Nov 10 2017 - 07:30:30 EST


Makefile modified in order to support building of GUI plugins.

kshark_plugin_loader and kshark_plugin_unloader are modified

kshark_plugin_reloader is defined and is called when the user
loads a new trace data file.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx>
---
Makefile | 31 ++++++++++--
kernel-shark.c | 150 +++++++++++++++++++++++++++++++++++++-------------------
kshark-plugin.h | 22 ++++++++-
3 files changed, 146 insertions(+), 57 deletions(-)

diff --git a/Makefile b/Makefile
index 5c35143..8d0f16f 100644
--- a/Makefile
+++ b/Makefile
@@ -293,6 +293,8 @@ else
print_shared_lib_compile = echo ' $(GUI)COMPILE SHARED LIB '$(GOBJ);
print_plugin_obj_compile = echo ' $(GUI)COMPILE PLUGIN OBJ '$(GOBJ);
print_plugin_build = echo ' $(GUI)BUILD PLUGIN '$(GOBJ);
+ print_gui_plugin_obj_compile = echo ' $(GUI)COMPILE GUI_PLUGIN OBJ '$(GOBJ);
+ print_gui_plugin_build = echo ' $(GUI)BUILD GUI_PLUGIN '$(GOBJ);
print_static_lib_build = echo ' $(GUI)BUILD STATIC LIB '$(GOBJ);
print_install = echo ' $(GUI)INSTALL '$(GSPACE)$1' to $(DESTDIR_SQ)$2';
endif
@@ -317,6 +319,14 @@ do_plugin_build = \
($(print_plugin_build) \
$(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $<)

+do_compile_gui_plugin_obj = \
+ ($(print_gui_plugin_obj_compile) \
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ $<)
+
+do_gui_plugin_build = \
+ ($(print_gui_plugin_build) \
+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $<)
+
do_build_static_lib = \
($(print_static_lib_build) \
$(RM) $@; $(AR) rcs $@ $^)
@@ -373,13 +383,17 @@ PLUGIN_OBJS += plugin_tlb.o

PLUGINS := $(PLUGIN_OBJS:.o=.so)

+GUI_PLUGIN_OBJS =
+
+GUI_PLUGINS := $(GUI_PLUGIN_OBJS:.o=.so)
+
ALL_OBJS = $(TRACE_CMD_OBJS) $(KERNEL_SHARK_OBJS) $(TRACE_VIEW_MAIN_OBJS) \
- $(TRACE_GRAPH_MAIN_OBJS) $(TCMD_LIB_OBJS) $(PLUGIN_OBJS)
+ $(TRACE_GRAPH_MAIN_OBJS) $(TCMD_LIB_OBJS) $(PLUGIN_OBJS) $(GUI_PLUGIN_OBJS)

CMD_TARGETS = trace_plugin_dir trace_python_dir tc_version.h libparsevent.a $(LIB_FILE) \
trace-cmd $(PLUGINS) $(BUILD_PYTHON)

-GUI_TARGETS = ks_version.h trace-graph trace-view kernelshark
+GUI_TARGETS = ks_version.h trace-graph trace-view kernelshark $(GUI_PLUGINS)

TARGETS = $(CMD_TARGETS) $(GUI_TARGETS)

@@ -401,7 +415,7 @@ gui: $(CMD_TARGETS)

all_gui: $(GUI_TARGETS) show_gui_done

-GUI_OBJS = $(KERNEL_SHARK_OBJS) $(TRACE_VIEW_MAIN_OBJS) $(TRACE_GRAPH_MAIN_OBJS)
+GUI_OBJS = $(KERNEL_SHARK_OBJS) $(TRACE_VIEW_MAIN_OBJS) $(TRACE_GRAPH_MAIN_OBJS) $(GUI_PLUGIN_OBJS)

gui_objs := $(sort $(GUI_OBJS))

@@ -447,6 +461,12 @@ $(PLUGIN_OBJS): %.o : $(src)/%.c
$(PLUGINS): %.so: %.o
$(Q)$(do_plugin_build)

+$(GUI_PLUGIN_OBJS): %.o : $(src)/%.c
+ $(Q)$(do_compile_gui_plugin_obj)
+
+$(GUI_PLUGINS): %.so: %.o
+ $(Q)$(do_gui_plugin_build)
+
define make_version.h
(echo '/* This file is automatically generated. Do not modify. */'; \
echo \#define VERSION_CODE $(shell \
@@ -549,7 +569,10 @@ cscope: force
$(RM) cscope*
find . -name '*.[ch]' | cscope -b -q

-PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS)) $(subst .so,.install,$(PYTHON_PLUGINS))
+PLUGINS_INSTALL =
+PLUGINS_INSTALL += $(subst .so,.install,$(PLUGINS))
+PLUGINS_INSTALL += $(subst .so,.install,$(GUI_PLUGINS))
+PLUGINS_INSTALL += $(subst .so,.install,$(PYTHON_PLUGINS))

define do_install
$(print_install) \
diff --git a/kernel-shark.c b/kernel-shark.c
index 89723c3..79b387a 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -339,6 +339,96 @@ int kernelshark_load_file(struct shark_info *info, const char *file)
return 0;
}

+static struct plugin_list {
+ struct plugin_list *next;
+ const char *file;
+} *plugins;
+static struct plugin_list **plugin_next = &plugins;
+
+static void add_plugin(const char *file)
+{
+ struct stat st;
+ int ret;
+
+ ret = stat(file, &st);
+ if (ret < 0) {
+ warning("plugin %s not found", file);
+ return;
+ }
+
+ *plugin_next = calloc(sizeof(struct plugin_list), 1);
+ if (!*plugin_next) {
+ warning("failed to allocat memory for plugin");
+ return;
+ }
+
+ (*plugin_next)->file = file;
+ plugin_next = &(*plugin_next)->next;
+}
+
+static void handle_plugins(struct shark_info *info,
+ struct trace_view_store *store,
+ int task_id)
+{
+ kshark_plugin_load_func func;
+ struct plugin_list *plugin;
+ void *handle;
+ char* func_name;
+ int fn_size = 0;
+
+ switch (task_id) {
+ case KSHARK_PLUGIN_LOAD:
+ fn_size = asprintf(&func_name, KSHARK_PLUGIN_LOADER_NAME);
+ break;
+
+ case KSHARK_PLUGIN_RELOAD:
+ fn_size = asprintf(&func_name, KSHARK_PLUGIN_RELOADER_NAME);
+ break;
+
+ case KSHARK_PLUGIN_UNLOAD:
+ fn_size = asprintf(&func_name, KSHARK_PLUGIN_UNLOADER_NAME);
+ break;
+
+ default:
+ return;
+ }
+
+ if (fn_size <= 0) {
+ warning("failed to allocat memory for plugin function name");
+ return;
+ }
+
+ for (plugin = plugins; plugin; plugin = plugin->next) {
+ handle = dlopen(plugin->file, RTLD_NOW | RTLD_GLOBAL);
+
+ if (!handle) {
+ warning("cound not load plugin '%s'\n%s\n",
+ plugin->file, dlerror());
+ continue;
+ }
+
+ func = dlsym(handle, func_name);
+ if (!func) {
+ warning("cound not find func '%s' in plugin '%s'\n%s\n",
+ func_name, plugin->file, dlerror());
+ continue;
+ }
+
+ func(info, store);
+ }
+
+ if (task_id == KSHARK_PLUGIN_UNLOAD) {
+ while ((plugin = plugins)) {
+ plugins = plugin->next;
+ free(plugin);
+ }
+
+ plugin_next = &plugins;
+ }
+
+ free(func_name);
+}
+
static void
/* Callback for the clicked signal of the Load button */
load_clicked (gpointer data)
@@ -353,6 +443,9 @@ load_clicked (gpointer data)

kernelshark_load_file(info, filename);

+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->treeview));
+ handle_plugins(info, TRACE_VIEW_STORE(model), KSHARK_PLUGIN_RELOAD);
+
g_free(filename);
}

@@ -1805,56 +1898,6 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
return FALSE;
}

-static struct plugin_list {
- struct plugin_list *next;
- const char *file;
-} *plugins;
-static struct plugin_list **plugin_next = &plugins;
-
-static void add_plugin(const char *file)
-{
- struct stat st;
- int ret;
-
- ret = stat(file, &st);
- if (ret < 0) {
- warning("plugin %s not found", file);
- return;
- }
-
- *plugin_next = calloc(sizeof(struct plugin_list), 1);
- if (!*plugin_next)
- die("failed to allocat memory for plugin");
-
- (*plugin_next)->file = file;
- plugin_next = &(*plugin_next)->next;
-}
-
-static void handle_plugins(struct shark_info *info)
-{
- kshark_plugin_load_func func;
- struct plugin_list *plugin;
- void *handle;
-
- while ((plugin = plugins)) {
- plugins = plugin->next;
-
- handle = dlopen(plugin->file, RTLD_NOW | RTLD_GLOBAL);
- free(plugin);
- if (!handle) {
- warning("cound not load plugin '%s'\n%s\n",
- plugin->file, dlerror());
- continue;
- }
- func = dlsym(handle, KSHARK_PLUGIN_LOADER_NAME);
- if (!func) {
- warning("cound not find func '%s' in plugin '%s'\n%s\n",
- KSHARK_PLUGIN_LOADER_NAME, plugin->file, dlerror());
- continue;
- }
- func(info);
- }
-}

static void sig_end(int sig)
{
@@ -1882,6 +1925,7 @@ void kernel_shark(int argc, char **argv)
GtkWidget *spin;
GtkWidget *check;
GtkWidget *statusbar;
+ GtkTreeModel *model;
int ret;
int c;

@@ -2495,7 +2539,8 @@ void kernel_shark(int argc, char **argv)

gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT);

- handle_plugins(info);
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->treeview));
+ handle_plugins(info, TRACE_VIEW_STORE(model), KSHARK_PLUGIN_LOAD);

gdk_threads_enter();

@@ -2510,6 +2555,9 @@ void kernel_shark(int argc, char **argv)
info->ginfo->no_draw = FALSE;
gtk_main ();
gdk_threads_leave();
+
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->treeview));
+ handle_plugins(info, TRACE_VIEW_STORE(model), KSHARK_PLUGIN_UNLOAD);
}

int main(int argc, char **argv)
diff --git a/kshark-plugin.h b/kshark-plugin.h
index 95ba797..81c09b5 100644
--- a/kshark-plugin.h
+++ b/kshark-plugin.h
@@ -17,19 +17,37 @@
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
+
+#include <limits.h>
+
+#include "event-parse.h"
+
#ifndef _KSHARK_PLUGIN_H
#define _KSHARK_PLUGIN_H

#define KSHARK_PLUGIN_LOADER kshark_plugin_loader
+#define KSHARK_PLUGIN_RELOADER kshark_plugin_reloader
#define KSHARK_PLUGIN_UNLOADER kshark_plugin_unloader

#define _MAKE_STR(x) #x
#define MAKE_STR(x) _MAKE_STR(x)
#define KSHARK_PLUGIN_LOADER_NAME MAKE_STR(KSHARK_PLUGIN_LOADER)
+#define KSHARK_PLUGIN_RELOADER_NAME MAKE_STR(KSHARK_PLUGIN_RELOADER)
#define KSHARK_PLUGIN_UNLOADER_NAME MAKE_STR(KSHARK_PLUGIN_UNLOADER)

-typedef int (*kshark_plugin_load_func)(void *info);
-typedef int (*kshark_plugin_unload_func)(void *info);
+typedef int (*kshark_plugin_load_func)(void *info, void *store);
+typedef int (*kshark_plugin_unload_func)(void *info, void *store);
+
+typedef int (*kshark_plugin_event_handler_func)(struct pevent_record *record,
+ int task_id,
+ void *val);
+
+typedef int (*kshark_plugin_context_update_func)(struct pevent *pevent, int task_id);

+enum gui_plugin_actions {
+ KSHARK_PLUGIN_LOAD,
+ KSHARK_PLUGIN_RELOAD,
+ KSHARK_PLUGIN_UNLOAD,
+};

#endif
--
2.15.0.rc0