lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed,  1 Nov 2017 13:04:23 +0200
From:   "Yordan Karadzhov (VMware)" <y.karadz@...il.com>
To:     rostedt@...dmis.org
Cc:     jan.kiszka@...mens.com, linux-kernel@...r.kernel.org,
        "Yordan Karadzhov (VMware)" <y.karadz@...il.com>
Subject: [PATCH 2/2] kernelshark: Adding a GUI plugin for xenomai events

Makefile modified in order to support building of gui plugins.

Function handlers for processing of plugin-specific events (xenomai
events "cobalt_switch_context" and "cobalt_thread_resume" in this case)
are addet to trace_view_store and graph_info.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@...il.com>
---
 Makefile             |  35 +++++--
 kernel-shark.c       |   8 +-
 kshark-plugin.c      |  65 +++++++++++++
 kshark-plugin.h      |  49 +++++++++-
 plugin_xenomai_gui.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++
 trace-graph.c        |  48 ++++++++++
 trace-graph.h        |   7 ++
 trace-plot-task.c    |  17 +++-
 trace-view-store.c   |  24 +++++
 trace-view-store.h   |   5 +
 10 files changed, 500 insertions(+), 15 deletions(-)
 create mode 100644 kshark-plugin.c
 create mode 100644 plugin_xenomai_gui.c

diff --git a/Makefile b/Makefile
index 5c35143..96f30e2 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 $@ $^)
@@ -338,17 +348,17 @@ $(obj)/%.o: $(src)/%.c
 	$(Q)$(call check_gui)
 
 TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-filter-hash.o trace-dialog.o \
-		trace-xml.o
+		trace-xml.o kshark-plugin.o
 TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \
 	 trace-stack.o trace-hist.o trace-mem.o trace-snapshot.o trace-stat.o \
 	 trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o \
 	 trace-check-events.o trace-show.o trace-list.o
-TRACE_VIEW_OBJS = trace-view.o trace-view-store.o
+TRACE_VIEW_OBJS = trace-view.o trace-view-store.o kshark-plugin.o
 TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o
 TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS)
 TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS)
 KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \
-	trace-capture.o kernel-shark.o
+	trace-capture.o kernel-shark.o kshark-plugin.o
 
 PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o str_error_r.o
 TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
@@ -373,13 +383,19 @@ PLUGIN_OBJS += plugin_tlb.o
 
 PLUGINS := $(PLUGIN_OBJS:.o=.so)
 
+
+GUI_PLUGIN_OBJS =
+GUI_PLUGIN_OBJS += plugin_xenomai_gui.o
+
+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 +417,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 +463,13 @@ $(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						\
diff --git a/kernel-shark.c b/kernel-shark.c
index 89723c3..9454ea0 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -1830,7 +1830,7 @@ static void add_plugin(const char *file)
 	plugin_next = &(*plugin_next)->next;
 }
 
-static void handle_plugins(struct shark_info *info)
+static void handle_plugins(struct shark_info *info, struct trace_view_store *store)
 {
 	kshark_plugin_load_func func;
 	struct plugin_list *plugin;
@@ -1852,7 +1852,7 @@ static void handle_plugins(struct shark_info *info)
 				KSHARK_PLUGIN_LOADER_NAME, plugin->file, dlerror());
 			continue;
 		}
-		func(info);
+		func(info, store);
 	}
 }
 
@@ -2495,7 +2495,9 @@ void kernel_shark(int argc, char **argv)
 
 	gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT);
 
-	handle_plugins(info);
+	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->treeview));
+	handle_plugins(info, TRACE_VIEW_STORE(model));
+
 
 	gdk_threads_enter();
 
diff --git a/kshark-plugin.c b/kshark-plugin.c
new file mode 100644
index 0000000..07d1a87
--- /dev/null
+++ b/kshark-plugin.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@...il.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <stdlib.h>
+
+#include "kshark-plugin.h"
+
+struct gui_event_handler *make_gui_event_handler(int event_id, int type,
+						 kshark_plugin_event_handler_func evt_func,
+						 kshark_plugin_context_update_func ctx_func)
+{
+	struct gui_event_handler *handler = malloc(sizeof(struct gui_event_handler));
+	handler->next = NULL;
+	handler->id = event_id;
+	handler->type = type;
+	handler->event_func = evt_func;
+	handler->context_func = ctx_func;
+
+	return handler;
+}
+
+struct gui_event_handler *find_gui_event_handler(struct gui_event_handler *handlers,
+						 int event_id)
+{
+	while (handlers) {
+		if (handlers->id == event_id)
+			return handlers;
+
+		handlers = handlers->next;
+	}
+
+	return NULL;
+}
+
+void remove_gui_event_handler(struct gui_event_handler **handlers, int event_id)
+{
+	struct gui_event_handler *list = *handlers;
+	if (list == NULL)
+		return;
+
+	if (list->id == event_id) {
+		*handlers = list->next;
+		return;
+	}
+
+	remove_gui_event_handler(&list->next, event_id);
+}
+
diff --git a/kshark-plugin.h b/kshark-plugin.h
index 95ba797..65e1e93 100644
--- a/kshark-plugin.h
+++ b/kshark-plugin.h
@@ -17,6 +17,9 @@
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
+
+#include "event-parse.h"
+
 #ifndef _KSHARK_PLUGIN_H
 #define _KSHARK_PLUGIN_H
 
@@ -28,8 +31,50 @@
 #define KSHARK_PLUGIN_LOADER_NAME MAKE_STR(KSHARK_PLUGIN_LOADER)
 #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 val);
+
+enum gui_plugin_actions {
+	KSHARK_PLUGIN_GET_PID,
+	KSHARK_PLUGIN_GET_PREV_STATE,
+	KSHARK_PLUGIN_GET_COMMAND
+};
+
+enum gui_plugin_ctx_updates {
+	KSHARK_PLUGIN_UPDATE_SWITCH_EVENT = 0x1,
+	KSHARK_PLUGIN_UPDATE_WAKEUP_EVENT = 0x2,
+	KSHARK_PLUGIN_UPDATE_WAKEUP_PID = 0x4,
+	KSHARK_PLUGIN_UPDATE_SWITCH_PID = 0x8,
+	KSHARK_PLUGIN_UPDATE_PREV_STATE = 0x10,
+	KSHARK_PLUGIN_UPDATE_NEXT_NAME = 0x20
+};
+
+enum gui_event_types {
+	KSHARK_PLUGIN_SWITCH_EVENT,
+	KSHARK_PLUGIN_WAKEUP_EVENT
+};
+
+struct gui_event_handler {
+	struct gui_event_handler		*next;
+	int					id;
+	int 					type;
+	kshark_plugin_event_handler_func	event_func;
+	kshark_plugin_context_update_func       context_func;
+};
+
+struct gui_event_handler *make_gui_event_handler(int event_id, int type,
+						 kshark_plugin_event_handler_func evt_func,
+						 kshark_plugin_context_update_func ctx_func);
+
+struct gui_event_handler *find_gui_event_handler(struct gui_event_handler *handlers,
+						 int event_id);
 
+void remove_gui_event_handler(struct gui_event_handler **handlers, int event_id);
 
 #endif
diff --git a/plugin_xenomai_gui.c b/plugin_xenomai_gui.c
new file mode 100644
index 0000000..f22a7a7
--- /dev/null
+++ b/plugin_xenomai_gui.c
@@ -0,0 +1,257 @@
+/*
+ *  Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@...il.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "event-parse.h"
+#include "kernel-shark.h"
+#include "kshark-plugin.h"
+
+struct xenomai_context {
+	struct shark_info	*info;
+	struct trace_view_store *store;
+	struct pevent 		*pevent;
+
+	struct event_format	*cobalt_switch_event;
+	struct format_field     *cobalt_switch_next_pid_field;
+	struct format_field     *cobalt_switch_prev_state_field;
+	struct format_field     *cobalt_switch_next_name_field;
+
+	struct event_format	*cobalt_wakeup_event;
+	struct format_field	*cobalt_wakeup_pid_field;
+};
+
+struct xenomai_context *xenomai_context_handler = NULL;
+
+static gboolean xenomai_update_context(struct pevent *pevent, int task_id)
+{
+	struct xenomai_context *ctx = xenomai_context_handler;
+	if (!ctx)
+		return FALSE;
+
+	struct event_format *event;
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_SWITCH_EVENT) {
+		event = pevent_find_event_by_name(xenomai_context_handler->pevent,
+						  "cobalt_core",
+						  "cobalt_switch_context");
+		if (!event)
+			return FALSE;
+
+		ctx->cobalt_switch_event = event;
+	}
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_WAKEUP_EVENT) {
+		event = pevent_find_event_by_name(xenomai_context_handler->pevent,
+						  "cobalt_core",
+						  "cobalt_thread_resume");
+		if (!event)
+			return FALSE;
+
+		ctx->cobalt_wakeup_event = event;
+	}
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_SWITCH_PID) {
+		ctx->cobalt_switch_next_pid_field =
+		pevent_find_field(ctx->cobalt_switch_event, "next_pid");
+	}
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_PREV_STATE) {
+		ctx->cobalt_switch_prev_state_field =
+		pevent_find_field(ctx->cobalt_switch_event, "prev_state");
+	}
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_NEXT_NAME) {
+		ctx->cobalt_switch_next_name_field =
+		pevent_find_field(ctx->cobalt_switch_event, "next_name");
+	}
+
+	if (task_id & KSHARK_PLUGIN_UPDATE_WAKEUP_PID) {
+		ctx->cobalt_wakeup_pid_field =
+		pevent_find_field(ctx->cobalt_wakeup_event, "pid");
+	}
+
+	return TRUE;
+}
+
+static void xenomai_context_new(struct shark_info *info, struct trace_view_store *store)
+{
+	if (!xenomai_context_handler) {
+		xenomai_context_handler =
+		(struct xenomai_context*) malloc(sizeof(struct xenomai_context));
+	}
+
+	xenomai_context_handler->info = info;
+	xenomai_context_handler->store = store;
+	xenomai_context_handler->pevent = tracecmd_get_pevent(info->handle);
+
+	int status = xenomai_update_context(xenomai_context_handler->pevent,
+					    KSHARK_PLUGIN_UPDATE_SWITCH_EVENT |
+					    KSHARK_PLUGIN_UPDATE_WAKEUP_EVENT);
+	if (status == FALSE) {
+		free(xenomai_context_handler);
+		xenomai_context_handler = NULL;
+	}
+}
+
+static int cobalt_get_next_pid(struct xenomai_context *ctx,
+				struct pevent_record *record,
+				int *pid)
+{
+	long long unsigned int val;
+	int status = pevent_read_number_field(ctx->cobalt_switch_next_pid_field,
+					      record->data, &val);
+	if (pid)
+		*pid = val;
+
+	return status;
+}
+
+
+static int cobalt_get_prev_state(struct xenomai_context *ctx,
+				 struct pevent_record *record,
+				 int *state)
+{
+	long long unsigned int val;
+	pevent_read_number_field(ctx->cobalt_switch_prev_state_field,
+				 record->data, &val);
+
+	if (state)
+		*state = val;
+
+	return (val & 0x00000008) ? 1 : 0;
+}
+
+static void cobalt_get_command(struct xenomai_context *ctx,
+				struct pevent_record *record,
+				const char **comm)
+{
+	int offset =
+	data2host4(ctx->pevent, record->data + ctx->cobalt_switch_next_name_field->offset);
+
+	offset &= 0xffff;
+	*comm = record->data + offset;
+}
+
+static gboolean xenomai_switch_handler(struct pevent_record *record,
+					int task_id,
+					void *output)
+{
+	struct xenomai_context *ctx = xenomai_context_handler;
+	switch (task_id) {
+		case KSHARK_PLUGIN_GET_PID:
+			cobalt_get_next_pid(ctx, record, output);
+			return TRUE;
+
+		case KSHARK_PLUGIN_GET_PREV_STATE:
+			return cobalt_get_prev_state(ctx, record, output);
+
+		case KSHARK_PLUGIN_GET_COMMAND:
+			cobalt_get_command(ctx, record, (const char**) output);
+			return TRUE;
+
+		default:
+			return FALSE;
+	}
+}
+
+static int cobalt_get_wakeup_pid(struct xenomai_context *ctx,
+				 struct pevent_record *record,
+				 int *pid)
+{
+	long long unsigned int val;
+	int status =
+	pevent_read_number_field(ctx->cobalt_wakeup_pid_field, record->data, &val);
+
+	if (pid)
+		*pid = val;
+
+	return status;
+}
+
+static gboolean xenomai_wakeup_handler(struct pevent_record *record,
+					int task_id,
+					void *output)
+{
+	struct xenomai_context *ctx = xenomai_context_handler;
+	switch (task_id) {
+		case KSHARK_PLUGIN_GET_PID:
+			cobalt_get_wakeup_pid(ctx, record, output);
+			return TRUE;
+
+		default:
+			return FALSE;
+	}
+}
+
+
+void KSHARK_PLUGIN_LOADER(void *info, void *store)
+{
+	struct shark_info *ks_info = info;
+	struct trace_view_store *ks_store = store;
+
+	xenomai_context_new(ks_info, ks_store);
+	if (!xenomai_context_handler)
+		return;
+
+	struct xenomai_context *ctx = xenomai_context_handler;
+
+	struct gui_event_handler *switch_handler =
+	make_gui_event_handler(ctx->cobalt_switch_event->id,
+			       KSHARK_PLUGIN_SWITCH_EVENT,
+			       xenomai_switch_handler,
+			       xenomai_update_context);
+
+	struct gui_event_handler *wakeup_handler =
+	make_gui_event_handler(ctx->cobalt_wakeup_event->id,
+			       KSHARK_PLUGIN_WAKEUP_EVENT,
+			       xenomai_wakeup_handler,
+			       xenomai_update_context);
+
+	trace_view_store_register_gui_handler(ks_store, switch_handler);
+	trace_view_store_register_gui_handler(ks_store, wakeup_handler);
+
+	trace_graph_register_gui_handler(ks_info->ginfo, switch_handler);
+	trace_graph_register_gui_handler(ks_info->ginfo, wakeup_handler);
+}
+
+void KSHARK_PLUGIN_UNLOADER(void *info, void *store)
+{
+	struct shark_info *ks_info = info;
+	struct trace_view_store *ks_store = store;
+	struct xenomai_context *ctx = xenomai_context_handler;
+
+	remove_gui_event_handler(&ks_store->event_handlers,
+				 ctx->cobalt_switch_event->id);
+
+	remove_gui_event_handler(&ks_store->event_handlers,
+				 ctx->cobalt_wakeup_event->id);
+
+	remove_gui_event_handler(&ks_info->ginfo->event_handlers,
+				 ctx->cobalt_switch_event->id);
+
+	remove_gui_event_handler(&ks_info->ginfo->event_handlers,
+				 ctx->cobalt_wakeup_event->id);
+
+	free(ctx);
+	xenomai_context_handler = NULL;
+}
+
diff --git a/trace-graph.c b/trace-graph.c
index 1db342f..19f02c0 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -129,6 +129,12 @@ static void free_task_hash(struct graph_info *ginfo)
 	}
 }
 
+void trace_graph_register_gui_handler(struct graph_info *info,
+				      struct gui_event_handler *handler) {
+	handler->next = info->event_handlers;
+	info->event_handlers = handler;
+}
+
 /**
  * trace_graph_task_list - return an allocated list of all found tasks
  * @ginfo: The graph info structure
@@ -1053,6 +1059,12 @@ int trace_graph_check_sched_wakeup(struct graph_info *ginfo,
 
 	id = pevent_data_type(ginfo->pevent, record);
 
+	struct gui_event_handler *handler = find_gui_event_handler(ginfo->event_handlers, id);
+	if (handler) {
+		if (handler->type == KSHARK_PLUGIN_WAKEUP_EVENT)
+			handler->context_func(ginfo->pevent, KSHARK_PLUGIN_UPDATE_WAKEUP_PID);
+	}
+
 	if (id == ginfo->event_wakeup_id) {
 		/* We only want those that actually woke up the task */
 		if (ginfo->wakeup_success_field) {
@@ -1079,6 +1091,16 @@ int trace_graph_check_sched_wakeup(struct graph_info *ginfo,
 		return 1;
 	}
 
+	if (handler) {
+		if (handler->type == KSHARK_PLUGIN_WAKEUP_EVENT) {
+			handler->event_func(record, KSHARK_PLUGIN_GET_PID, &val);
+			if (pid)
+				*pid = val;
+
+			return 1;
+		}
+	}
+
 	return 0;
 }
 
@@ -1118,7 +1140,20 @@ int trace_graph_check_sched_switch(struct graph_info *ginfo,
 		}
 	}
 
+
 	id = pevent_data_type(ginfo->pevent, record);
+	struct gui_event_handler *handler =
+	find_gui_event_handler(ginfo->event_handlers, id);
+
+	if (handler) {
+		if (handler->type == KSHARK_PLUGIN_SWITCH_EVENT) {
+			handler->context_func(ginfo->pevent,
+					      KSHARK_PLUGIN_UPDATE_SWITCH_PID |
+					      KSHARK_PLUGIN_UPDATE_PREV_STATE |
+					      KSHARK_PLUGIN_UPDATE_NEXT_NAME);
+		}
+	}
+
 	if (id == ginfo->event_sched_switch_id) {
 		pevent_read_number_field(ginfo->event_pid_field, record->data, &val);
 		if (comm)
@@ -1139,6 +1174,17 @@ int trace_graph_check_sched_switch(struct graph_info *ginfo,
 		goto out;
 	}
 
+	if (handler) {
+		if (handler->type == KSHARK_PLUGIN_SWITCH_EVENT) {
+			handler->event_func(record, KSHARK_PLUGIN_GET_PID, &val);
+			if (pid)
+				*pid = val;
+			if(comm)
+				handler->event_func(record, KSHARK_PLUGIN_GET_COMMAND, &comm);
+			goto out;
+		}
+	}
+
 	ret = 0;
  out:
 	if (ret && comm && ginfo->read_comms) {
@@ -2781,6 +2827,8 @@ trace_graph_create_with_callbacks(struct tracecmd_input *handle,
 
 	ginfo->callbacks = cbs;
 
+	ginfo->event_handlers = NULL;
+
 	ginfo->task_filter = filter_task_hash_alloc();
 	ginfo->hide_tasks = filter_task_hash_alloc();
 
diff --git a/trace-graph.h b/trace-graph.h
index 7e66838..21e8feb 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -24,6 +24,7 @@
 #include "trace-cmd.h"
 #include "trace-filter-hash.h"
 #include "trace-xml.h"
+#include "kshark-plugin.h"
 
 struct graph_info;
 
@@ -258,6 +259,8 @@ struct graph_info {
 	gint			plot_data_y;
 	gint			plot_data_w;
 	gint			plot_data_h;
+
+	struct gui_event_handler *event_handlers;
 };
 
 
@@ -266,6 +269,10 @@ trace_graph_create(struct tracecmd_input *handle);
 struct graph_info *
 trace_graph_create_with_callbacks(struct tracecmd_input *handle,
 				  struct graph_callbacks *cbs);
+
+void trace_graph_register_gui_handler(struct graph_info *info,
+				      struct gui_event_handler *handler);
+
 void trace_graph_select_by_time(struct graph_info *ginfo, guint64 time);
 
 void trace_graph_event_filter_callback(gboolean accept,
diff --git a/trace-plot-task.c b/trace-plot-task.c
index 3b7e81f..56c3e96 100644
--- a/trace-plot-task.c
+++ b/trace-plot-task.c
@@ -68,11 +68,20 @@ static gboolean is_running(struct graph_info *ginfo, struct pevent_record *recor
 	int id;
 
 	id = pevent_data_type(ginfo->pevent, record);
-	if (id != ginfo->event_sched_switch_id)
-		return FALSE;
 
-	pevent_read_number_field(ginfo->event_prev_state, record->data, &val);
-	return val & ((1 << 11) - 1)? FALSE : TRUE;
+	if (id == ginfo->event_sched_switch_id) {
+		pevent_read_number_field(ginfo->event_prev_state, record->data, &val);
+		return val & ((1 << 11) - 1)? FALSE : TRUE;
+	}
+
+	struct gui_event_handler *handler =
+	find_gui_event_handler(ginfo->event_handlers, id);
+	if (handler) {
+		if (handler->type == KSHARK_PLUGIN_SWITCH_EVENT)
+			return handler->event_func(record, KSHARK_PLUGIN_GET_PREV_STATE, NULL);
+	}
+
+	return FALSE;
 }
 
 static gboolean record_matches_pid(struct graph_info *ginfo,
diff --git a/trace-view-store.c b/trace-view-store.c
index f5d0a04..d7293c3 100644
--- a/trace-view-store.c
+++ b/trace-view-store.c
@@ -70,6 +70,12 @@ static gboolean		trace_view_store_iter_parent	(GtkTreeModel	*tree_model,
 static GObjectClass *parent_class = NULL;	/* GObject stuff - nothing to worry about */
 
 
+void trace_view_store_register_gui_handler(TraceViewStore *store, struct gui_event_handler *handler)
+{
+	handler->next = store->event_handlers;
+	store->event_handlers = handler;
+}
+
 /*****************************************************************************
  *
  *	trace_view_store_get_type: here we register our new type and its interfaces
@@ -866,6 +872,7 @@ trace_view_store_new (struct tracecmd_input *handle)
 
 	g_assert( newstore != NULL );
 
+	newstore->event_handlers = NULL;
 	newstore->handle = handle;
 	newstore->cpus = tracecmd_cpus(handle);
 	tracecmd_ref(handle);
@@ -1224,6 +1231,14 @@ static gboolean show_task(TraceViewStore *store, struct pevent *pevent,
 			return TRUE;
 	}
 
+	struct gui_event_handler *handler =
+	find_gui_event_handler(store->event_handlers, event_id);
+	if (handler) {
+		handler->event_func(record, KSHARK_PLUGIN_GET_PID, &pid);
+		if (view_task(store, pid))
+			return TRUE;
+	}
+
 	return FALSE;
 }
 
@@ -1261,6 +1276,15 @@ static void update_filter_tasks(TraceViewStore *store)
 						      "pid");
 	}
 
+	struct gui_event_handler *handler = store->event_handlers;
+	while (handler) {
+		handler->context_func(	pevent,
+					KSHARK_PLUGIN_UPDATE_SWITCH_PID |
+					KSHARK_PLUGIN_UPDATE_WAKEUP_PID);
+
+		handler = handler->next;
+	}
+
 	for (cpu = 0; cpu < store->cpus; cpu++) {
 		record = tracecmd_read_cpu_first(handle, cpu);
 
diff --git a/trace-view-store.h b/trace-view-store.h
index 03141b1..333116c 100644
--- a/trace-view-store.h
+++ b/trace-view-store.h
@@ -23,6 +23,7 @@
 #include <gtk/gtk.h>
 #include "trace-cmd.h"
 #include "trace-filter-hash.h"
+#include "kshark-plugin.h"
 
 /* Some boilerplate GObject defines. 'klass' is used
  *   instead of 'class', because 'class' is a C++ keyword */
@@ -125,8 +126,12 @@ struct trace_view_store
 	guint64			*cpu_mask;  /* cpus that are enabled */
 
 	gint		stamp;	/* Random integer to check whether an iter belongs to our model */
+
+	struct gui_event_handler *event_handlers;
 };
 
+void trace_view_store_register_gui_handler(TraceViewStore *store, struct gui_event_handler *handler);
+
 gboolean trace_view_store_cpu_isset(TraceViewStore *store, gint cpu);
 
 void trace_view_store_set_all_cpus(TraceViewStore *store);
-- 
2.15.0.rc0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ