All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] Add infrastructure for plugins.
@ 2018-09-04 15:52 Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

The infrastructure for plugins used by the Qt-based version of KernelShark
is introduced in this series of patches. This is the last major component
of the C API. The last patch adds a plugin for dealing with "sched" events.

This is the second version of this series of patches. The major changes
from v1 are in the C++ source file of [PATCH 7/7].

Yordan Karadzhov (VMware) (7):
  kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset
    KS.
  kernel-shark-qt: Add Plugin event handlers to session.
  kernel-shark-qt: Add C++/C conversion for args of a plugin draw
    function.
  kernel-shark-qt: Make kshark_read_at() non-static.
  kernel-shark-qt: Add src/plugins dir. to hold the source code of the
    plugins
  kernel-shark-qt: Tell Doxygen to enter ../src/plugins/
  kernel-shark-qt: Add a plugin for sched events.

 kernel-shark-qt/doc/dox_config              |   2 +-
 kernel-shark-qt/src/CMakeLists.txt          |   3 +
 kernel-shark-qt/src/KsPlugins.hpp           |  51 ++++
 kernel-shark-qt/src/libkshark-plugin.c      | 304 ++++++++++++++++++++
 kernel-shark-qt/src/libkshark-plugin.h      | 171 +++++++++++
 kernel-shark-qt/src/libkshark.c             |  33 ++-
 kernel-shark-qt/src/libkshark.h             |  18 ++
 kernel-shark-qt/src/plugins/CMakeLists.txt  |  27 ++
 kernel-shark-qt/src/plugins/SchedEvents.cpp | 263 +++++++++++++++++
 kernel-shark-qt/src/plugins/sched_events.c  | 304 ++++++++++++++++++++
 kernel-shark-qt/src/plugins/sched_events.h  |  79 +++++
 11 files changed, 1252 insertions(+), 3 deletions(-)
 create mode 100644 kernel-shark-qt/src/KsPlugins.hpp
 create mode 100644 kernel-shark-qt/src/libkshark-plugin.c
 create mode 100644 kernel-shark-qt/src/libkshark-plugin.h
 create mode 100644 kernel-shark-qt/src/plugins/CMakeLists.txt
 create mode 100644 kernel-shark-qt/src/plugins/SchedEvents.cpp
 create mode 100644 kernel-shark-qt/src/plugins/sched_events.c
 create mode 100644 kernel-shark-qt/src/plugins/sched_events.h

-- 
2.17.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS.
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-05  2:09   ` Steven Rostedt
  2018-09-04 15:52 ` [PATCH 2/7] kernel-shark-qt: Add Plugin event handlers to session Yordan Karadzhov (VMware)
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

This patch adds infrastructure for loading/unloading of plugins. Each
plugin is coupled to a specific type of trace event and is allowed to
perform two types of actions.

The first action is executed once for each kshark_entry only at the time
when the data is loaded. This action can modify (even completely rewrite)
the content of the kshark_entrys generated from the trace events having
the type of the plugin.

The second action can add graphical elements on top of the existing graphs
generated by the Visualization model. This will become clear in the
following patches. This action is executed once for each graph and this is
happening every time when the Visualization model changes its state. It is
very powerful and can be used not only for drawing, but also for performing
arbitrary modifications on the data. The pointer to the model descriptor
object can access the entire array of kshark_entries, which, in turn, could
be used to modify those entries.

The plugin infrastructure of the Qt-baset KernelShark reuses the system
of macros for loading/unloading, implemented for the original GTK version.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/CMakeLists.txt     |   1 +
 kernel-shark-qt/src/libkshark-plugin.c | 304 +++++++++++++++++++++++++
 kernel-shark-qt/src/libkshark-plugin.h | 171 ++++++++++++++
 kernel-shark-qt/src/libkshark.h        |   3 +
 4 files changed, 479 insertions(+)
 create mode 100644 kernel-shark-qt/src/libkshark-plugin.c
 create mode 100644 kernel-shark-qt/src/libkshark-plugin.h

diff --git a/kernel-shark-qt/src/CMakeLists.txt b/kernel-shark-qt/src/CMakeLists.txt
index ac2847ab..cdc28c4c 100644
--- a/kernel-shark-qt/src/CMakeLists.txt
+++ b/kernel-shark-qt/src/CMakeLists.txt
@@ -3,6 +3,7 @@ message("\n src ...")
 message(STATUS "libkshark")
 add_library(kshark SHARED libkshark.c
                           libkshark-model.c
+                          libkshark-plugin.c
                           libkshark-configio.c
                           libkshark-collection.c)
 
diff --git a/kernel-shark-qt/src/libkshark-plugin.c b/kernel-shark-qt/src/libkshark-plugin.c
new file mode 100644
index 00000000..037d5908
--- /dev/null
+++ b/kernel-shark-qt/src/libkshark-plugin.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+ /**
+  *  @file    libkshark-plugin.c
+  *  @brief   KernelShark plugins.
+  */
+
+// C
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <errno.h>
+
+// KernelShark
+#include "libkshark-plugin.h"
+#include "libkshark.h"
+
+static struct kshark_event_handler *
+gui_event_handler_alloc(int event_id,
+			kshark_plugin_event_handler_func evt_func,
+			kshark_plugin_draw_handler_func dw_func)
+{
+	struct kshark_event_handler *handler = malloc(sizeof(*handler));
+
+	if (!handler) {
+		fprintf(stderr,
+			"failed to allocate memory for gui eventhandler");
+		return NULL;
+	}
+
+	handler->next = NULL;
+	handler->id = event_id;
+	handler->event_func = evt_func;
+	handler->draw_func = dw_func;
+
+	return handler;
+}
+
+/**
+ * @brief Search the list of event handlers for a handle associated with a given event type.
+ *
+ * @param handlers: Input location for the Event handler list.
+ * @param event_id: Event Id to search for.
+ */
+struct kshark_event_handler *
+find_event_handler(struct kshark_event_handler *handlers, int event_id)
+{
+	for (; handlers; handlers = handlers->next)
+		if (handlers->id == event_id)
+			return handlers;
+
+	return NULL;
+}
+
+/**
+ * @brief Add new event handler to an existing list of handlers.
+ *
+ * @param handlers: Input location for the Event handler list.
+ * @param event_id: Event Id.
+ * @param evt_func: Input location for an Event action provided by the plugin.
+ * @param dw_func: Input location for a Draw action provided by the plugin.
+ *
+ * @returns Zero on success, or a negative error code on failure.
+ */
+int kshark_register_event_handler(struct kshark_event_handler **handlers,
+				  int event_id,
+				  kshark_plugin_event_handler_func evt_func,
+				  kshark_plugin_draw_handler_func dw_func)
+{
+	struct kshark_event_handler *handler =
+		gui_event_handler_alloc(event_id, evt_func, dw_func);
+
+	if(!handler)
+		return -ENOMEM;
+
+	handler->next = *handlers;
+	*handlers = handler;
+	return 0;
+}
+
+/**
+ * @brief Search the list for a specific plugin handle. If such a plugin handle
+ *	  exists, unregister (remove and free) this handle from the list.
+ *
+ * @param handlers: Input location for the Event handler list.
+ * @param event_id: Event Id of the plugin handler to be unregistered.
+ * @param evt_func: Event action function of the handler to be unregistered.
+ * @param dw_func: Draw action function of the handler to be unregistered.
+ */
+void kshark_unregister_event_handler(struct kshark_event_handler **handlers,
+				     int event_id,
+				     kshark_plugin_event_handler_func evt_func,
+				     kshark_plugin_draw_handler_func dw_func)
+{
+	struct kshark_event_handler **last = handlers;
+	struct kshark_event_handler *list;
+
+	for (list = *handlers; list; list = list->next) {
+		if (list->id == event_id &&
+		    list->event_func == evt_func &&
+		    list->draw_func == dw_func) {
+			*last = list->next;
+			free(list);
+			return;
+		}
+
+		last = &list->next;
+	}
+}
+
+/**
+ * @brief Free all Event handlers in a given list.
+ *
+ * @param handlers: Input location for the Event handler list.
+ */
+void kshark_free_event_handler_list(struct kshark_event_handler *handlers)
+{
+	struct kshark_event_handler *last;
+
+	while (handlers) {
+		last = handlers;
+		handlers = handlers->next;
+		free(last);
+	}
+}
+
+/**
+ * @brief Allocate memory for a new plugin. Add this plugin to the list of
+ *	  plugins used by the session.
+ *
+ * @param kshark_ctx: Input location for the session context pointer.
+ * @param file: The plugin object file to load.
+ *
+ * @returns Zero on success, or a negative error code on failure.
+ */
+int kshark_register_plugin(struct kshark_context *kshark_ctx,
+			   const char *file)
+{
+	struct kshark_plugin_list *plugin = kshark_ctx->plugins;
+	struct stat st;
+	int ret;
+
+	while (plugin) {
+		if (strcmp(plugin->file, file) == 0)
+			return -EEXIST;
+
+		plugin = plugin->next;
+	}
+
+	ret = stat(file, &st);
+	if (ret < 0) {
+		fprintf(stderr, "plugin %s not found\n", file);
+		return -ENODEV;
+	}
+
+	plugin = calloc(sizeof(struct kshark_plugin_list), 1);
+	if (!plugin) {
+		fprintf(stderr, "failed to allocate memory for plugin\n");
+		return -ENOMEM;
+	}
+
+	asprintf(&plugin->file, "%s", file);
+	plugin->handle = NULL;
+
+	plugin->next = kshark_ctx->plugins;
+	kshark_ctx->plugins = plugin;
+
+	return 0;
+}
+
+/**
+ * @brief Register a new plugin..
+ *
+ * @param kshark_ctx: Input location for context pointer.
+ * @param file: The plugin object file to load.
+ */
+void kshark_unregister_plugin(struct kshark_context *kshark_ctx,
+			      const char *file)
+{
+	struct kshark_plugin_list **last = &kshark_ctx->plugins;
+	struct kshark_plugin_list *list;
+
+	for (list = kshark_ctx->plugins; list; list = list->next) {
+		if (strcmp(list->file, file) == 0) {
+			*last = list->next;
+			free(list->file);
+			free(list);
+			return;
+		}
+
+		last = &list->next;
+	}
+}
+
+/**
+ * @brief Free all plugins in a given list.
+ *
+ * @param plugins: Input location for the plugins list.
+ */
+void kshark_free_plugin_list(struct kshark_plugin_list *plugins)
+{
+	struct kshark_plugin_list *last;
+
+	while (plugins) {
+		last = plugins;
+		plugins = plugins->next;
+		free(last->file);
+		free(last);
+	}
+}
+
+/**
+ * @brief Use this function to load/reload/unload all registered plugins.
+ *
+ * @param kshark_ctx: Input location for context pointer.
+ * @param task_id: Action identifier specifying the action to be executed.
+ *
+ * @returns The number of successful operations on success, or a negative error
+ *	    code on failure.
+ */
+int kshark_handle_plugins(struct kshark_context *kshark_ctx,
+			  int task_id)
+{
+	kshark_plugin_load_func func;
+	struct kshark_plugin_list *plugin;
+	int fn_size = 0, plugin_count = 0;
+	char* func_name;
+
+	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 -EINVAL;
+	}
+
+	if (fn_size <= 0) {
+		fprintf(stderr,
+			"failed to allocate memory for plugin function name");
+		return -ENOMEM;
+	}
+
+	for (plugin = kshark_ctx->plugins; plugin; plugin = plugin->next) {
+		if (task_id == KSHARK_PLUGIN_LOAD) {
+			plugin->handle =
+				dlopen(plugin->file, RTLD_NOW | RTLD_GLOBAL);
+
+			if (!plugin->handle) {
+				fprintf(stderr,
+					"cannot load plugin '%s'\n%s\n",
+					plugin->file,
+					dlerror());
+
+				continue;
+			}
+		}
+
+		if (plugin->handle) {
+			func = dlsym(plugin->handle, func_name);
+			if (!func) {
+				fprintf(stderr,
+					"cannot find func '%s' in plugin '%s'\n%s\n",
+					func_name,
+					plugin->file,
+					dlerror());
+
+				dlclose(plugin->handle);
+				plugin->handle = NULL;
+				continue;
+			}
+
+			func();
+			++plugin_count;
+
+			if (task_id == KSHARK_PLUGIN_UNLOAD) {
+				dlclose(plugin->handle);
+				plugin->handle = NULL;
+			}
+		}
+	}
+
+	free(func_name);
+
+	return plugin_count;
+}
diff --git a/kernel-shark-qt/src/libkshark-plugin.h b/kernel-shark-qt/src/libkshark-plugin.h
new file mode 100644
index 00000000..34143204
--- /dev/null
+++ b/kernel-shark-qt/src/libkshark-plugin.h
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+
+/*
+ * Copyright (C) 2016 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ */
+
+ /**
+  *  @file    libkshark-plugin.h
+  *  @brief   KernelShark plugins.
+  */
+
+#ifndef _KSHARK_PLUGIN_H
+#define _KSHARK_PLUGIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// trace-cmd
+#include "event-parse.h"
+
+/* Quiet warnings over documenting simple structures */
+//! @cond Doxygen_Suppress
+
+#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)
+
+struct kshark_context;
+struct kshark_entry;
+
+//! @endcond
+
+/**
+ * A function type to be used when defining load/reload/unload plugin
+ * functions.
+ */
+typedef int (*kshark_plugin_load_func)(void);
+
+struct kshark_trace_histo;
+
+/**
+ * Structure representing the C arguments of the drawing function of
+ * a plugin.
+ */
+struct kshark_cpp_argv {
+	/** Pointer to the model descriptor object. */
+	struct kshark_trace_histo	*histo;
+};
+
+/** A function type to be used when defining plugin functions for drawing. */
+typedef void
+(*kshark_plugin_draw_handler_func)(struct kshark_cpp_argv *argv,
+				   int val, int draw_action);
+
+/**
+ * A function type to be used when defining plugin functions for data
+ * manipulation.
+ */
+typedef void
+(*kshark_plugin_event_handler_func)(struct kshark_context *kshark_ctx,
+				    struct tep_record *rec,
+				    struct kshark_entry *e);
+
+/** Plugin action identifier. */
+enum kshark_plugin_actions {
+	/**
+	 * Load plugins action. This action identifier is used when handling
+	 * plugins.
+	 */
+	KSHARK_PLUGIN_LOAD,
+
+	/**
+	 * Reload plugins action. This action identifier is used when handling
+	 * plugins.
+	 */
+	KSHARK_PLUGIN_RELOAD,
+
+	/**
+	 * Unload plugins action. This action identifier is used when handling
+	 * plugins.
+	 */
+	KSHARK_PLUGIN_UNLOAD,
+
+	/**
+	 * Task draw action. This action identifier is used by the plugin draw
+	 * function.
+	 */
+	KSHARK_PLUGIN_TASK_DRAW,
+
+	/**
+	 * CPU draw action. This action identifier is used by the plugin draw
+	 * function.
+	 */
+	KSHARK_PLUGIN_CPU_DRAW,
+};
+
+/**
+ * Plugin Event handler structure, defining the properties of the required
+ * kshark_entry.
+ */
+struct kshark_event_handler {
+	/** Pointer to the next Plugin Event handler. */
+	struct kshark_event_handler		*next;
+
+	/** Unique Id ot the trace event type. */
+	int					id;
+
+	/**
+	 * Event action function. This action can be used to modify the content
+	 * of all kshark_entries having Event Ids equal to "id".
+	 */
+	kshark_plugin_event_handler_func	event_func;
+
+	/**
+	 * Draw action function. This action can be used to draw additional
+	 * graphical elements (shapes) for all kshark_entries having Event Ids
+	 * equal to "id".
+	 */
+	kshark_plugin_draw_handler_func		draw_func;
+};
+
+struct kshark_event_handler *
+find_event_handler(struct kshark_event_handler *handlers,
+						int event_id);
+
+int kshark_register_event_handler(struct kshark_event_handler **handlers,
+				  int event_id,
+				  kshark_plugin_event_handler_func evt_func,
+				  kshark_plugin_draw_handler_func dw_func);
+
+void kshark_unregister_event_handler(struct kshark_event_handler **handlers,
+				     int event_id,
+				     kshark_plugin_event_handler_func evt_func,
+				     kshark_plugin_draw_handler_func dw_func);
+
+void kshark_free_event_handler_list(struct kshark_event_handler *handlers);
+
+/** Linked list of plugins. */
+struct kshark_plugin_list {
+	/** Pointer to the next Plugin. */
+	struct kshark_plugin_list	*next;
+
+	/** The plugin object file to load. */
+	char			*file;
+
+	/** Plugin Event handler. */
+	void			*handle;
+};
+
+int kshark_register_plugin(struct kshark_context *kshark_ctx,
+			   const char *file);
+
+void kshark_unregister_plugin(struct kshark_context *kshark_ctx,
+			      const char *file);
+
+void kshark_free_plugin_list(struct kshark_plugin_list *plugins);
+
+int kshark_handle_plugins(struct kshark_context *kshark_ctx, int task_id);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _KSHARK_PLUGIN_H
diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h
index 2580449a..fda133c8 100644
--- a/kernel-shark-qt/src/libkshark.h
+++ b/kernel-shark-qt/src/libkshark.h
@@ -121,6 +121,9 @@ struct kshark_context {
 
 	/** List of Data collections. */
 	struct kshark_entry_collection *collections;
+
+	/** List of Plugins. */
+	struct kshark_plugin_list	*plugins;
 };
 
 bool kshark_instance(struct kshark_context **kshark_ctx);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/7] kernel-shark-qt: Add Plugin event handlers to session.
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 3/7] kernel-shark-qt: Add C++/C conversion for args of a plugin draw function Yordan Karadzhov (VMware)
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

Plugin event handlers are added to the Session context descriptor.
The handlers are used to execute plugin-specific action (callback
function) during the processing of the trace data.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/libkshark.c | 21 +++++++++++++++++++++
 kernel-shark-qt/src/libkshark.h | 12 ++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/kernel-shark-qt/src/libkshark.c b/kernel-shark-qt/src/libkshark.c
index b4a76ae8..eef02368 100644
--- a/kernel-shark-qt/src/libkshark.c
+++ b/kernel-shark-qt/src/libkshark.c
@@ -33,6 +33,9 @@ static bool kshark_default_context(struct kshark_context **context)
 	if (!kshark_ctx)
 		return false;
 
+	kshark_ctx->event_handlers = NULL;
+	kshark_ctx->plugins = NULL;
+
 	kshark_ctx->show_task_filter = tracecmd_filter_id_hash_alloc();
 	kshark_ctx->hide_task_filter = tracecmd_filter_id_hash_alloc();
 
@@ -217,6 +220,12 @@ void kshark_free(struct kshark_context *kshark_ctx)
 	tracecmd_filter_id_hash_free(kshark_ctx->show_event_filter);
 	tracecmd_filter_id_hash_free(kshark_ctx->hide_event_filter);
 
+	if(kshark_ctx->plugins) {
+		kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_UNLOAD);
+		kshark_free_plugin_list(kshark_ctx->plugins);
+		kshark_free_event_handler_list(kshark_ctx->event_handlers);
+	}
+
 	kshark_free_task_list(kshark_ctx);
 
 	if (seq.buffer)
@@ -564,6 +573,7 @@ static void free_rec_list(struct rec_list **rec_list, int n_cpus,
 static size_t get_records(struct kshark_context *kshark_ctx,
 			  struct rec_list ***rec_list, enum rec_type type)
 {
+	struct kshark_event_handler *evt_handler;
 	struct event_filter *adv_filter;
 	struct kshark_task_list *task;
 	struct tep_record *rec;
@@ -608,6 +618,17 @@ static size_t get_records(struct kshark_context *kshark_ctx,
 
 				entry = &temp_rec->entry;
 				kshark_set_entry_values(kshark_ctx, rec, entry);
+
+				/* Execute all plugin-provided actions (if any). */
+				evt_handler = kshark_ctx->event_handlers;
+				while ((evt_handler = find_event_handler(evt_handler,
+									 entry->event_id))) {
+					evt_handler->event_func(kshark_ctx, rec, entry);
+
+					if ((evt_handler = evt_handler->next))
+						entry->visible &= ~KS_PLUGIN_UNTOUCHED_MASK;
+				}
+
 				pid = entry->pid;
 				/* Apply event filtering. */
 				ret = FILTER_MATCH;
diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h
index fda133c8..203c8122 100644
--- a/kernel-shark-qt/src/libkshark.h
+++ b/kernel-shark-qt/src/libkshark.h
@@ -29,6 +29,9 @@ extern "C" {
 #include "event-parse.h"
 #include "trace-filter-hash.h"
 
+// KernelShark
+#include "libkshark-plugin.h"
+
 /**
  * Kernel Shark entry contains all information from one trace record needed
  * in order to  visualize the time-series of trace records. The part of the
@@ -124,6 +127,9 @@ struct kshark_context {
 
 	/** List of Plugins. */
 	struct kshark_plugin_list	*plugins;
+
+	/** List of Plugin Event handlers. */
+	struct kshark_event_handler	*event_handlers;
 };
 
 bool kshark_instance(struct kshark_context **kshark_ctx);
@@ -160,6 +166,12 @@ enum kshark_filter_masks {
 
 	/** Special mask used whene filtering events. */
 	KS_EVENT_VIEW_FILTER_MASK	= 1 << 2,
+
+	/**
+	 * Use this mask to check if the content of the entry has been accessed
+	 * by a plugin-defined function.
+	 */
+	KS_PLUGIN_UNTOUCHED_MASK	= 1 << 7
 };
 
 /** Filter type identifier. */
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/7] kernel-shark-qt: Add C++/C conversion for args of a plugin draw function.
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 2/7] kernel-shark-qt: Add Plugin event handlers to session Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 4/7] kernel-shark-qt: Make kshark_read_at() non-static Yordan Karadzhov (VMware)
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

The draw function of a plugin has a type declared in C. However, the
function needs to access some high level objects, defined in the C++
libraries. This patch adds instruments for converting the arguments
of the plugin's draw function from C++ to C and from C to C++.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/KsPlugins.hpp | 51 +++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 kernel-shark-qt/src/KsPlugins.hpp

diff --git a/kernel-shark-qt/src/KsPlugins.hpp b/kernel-shark-qt/src/KsPlugins.hpp
new file mode 100644
index 00000000..3955cdfd
--- /dev/null
+++ b/kernel-shark-qt/src/KsPlugins.hpp
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+
+/*
+ * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+/**
+  *  @file    KsPlugins.hpp
+  *  @brief   KernelShark C++ plugin declarations.
+  */
+
+#ifndef _KS_PLUGINS_H
+#define _KS_PLUGINS_H
+
+// KernelShark
+#include "libkshark-model.h"
+#include "KsPlotTools.hpp"
+
+/**
+ * Structure representing the vector of C++ arguments of the drawing function
+ * of a plugin.
+ */
+struct KsCppArgV {
+	/** Pointer to the model descriptor object. */
+	kshark_trace_histo	*_histo;
+
+	/** Pointer to the graph object. */
+	KsPlot::Graph		*_graph;
+
+	/**
+	 * Pointer to the list of shapes. All shapes created by the plugin
+	 * will be added to this list.
+	 */
+	KsPlot::PlotObjList	*_shapes;
+
+	/**
+	 * Convert the "this" pointer of the C++ argument vector into a
+	 * C pointer.
+	 */
+	kshark_cpp_argv *toC()
+	{
+		return reinterpret_cast<kshark_cpp_argv *>(this);
+	}
+};
+
+/**
+ * Macro used to convert a C pointer into a pointer to KsCppArgV (C++ struct).
+ */
+#define KS_ARGV_TO_CPP(a) (reinterpret_cast<KsCppArgV *>(a))
+
+#endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/7] kernel-shark-qt: Make kshark_read_at() non-static.
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
                   ` (2 preceding siblings ...)
  2018-09-04 15:52 ` [PATCH 3/7] kernel-shark-qt: Add C++/C conversion for args of a plugin draw function Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 5/7] kernel-shark-qt: Add src/plugins dir. to hold the source code of the plugins Yordan Karadzhov (VMware)
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

kshark_read_at() function provides a thread-safe read of a record from
a specific offset inside the trace.dat file. So far this function was
used only in libkshark.c and was defined static. This patch makes the
function non-static in order to make possible to use it from a plugin.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/libkshark.c | 12 ++++++++++--
 kernel-shark-qt/src/libkshark.h |  3 +++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/kernel-shark-qt/src/libkshark.c b/kernel-shark-qt/src/libkshark.c
index eef02368..91138527 100644
--- a/kernel-shark-qt/src/libkshark.c
+++ b/kernel-shark-qt/src/libkshark.c
@@ -830,8 +830,16 @@ ssize_t kshark_load_data_records(struct kshark_context *kshark_ctx,
 	return -ENOMEM;
 }
 
-static struct tep_record *kshark_read_at(struct kshark_context *kshark_ctx,
-					 uint64_t offset)
+/**
+ * @brief A thread-safe read of a record from a specific offset.
+ *
+ * @param kshark_ctx: Input location for the session context pointer.
+ * @param offset: the offset into the file to find the record.
+ *
+ * @returns The returned pevent_record must be freed.
+ */
+struct tep_record *kshark_read_at(struct kshark_context *kshark_ctx,
+				  uint64_t offset)
 {
 	/*
 	 * It turns that tracecmd_read_at() is not thread-safe.
diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h
index 203c8122..ba5ea6cb 100644
--- a/kernel-shark-qt/src/libkshark.h
+++ b/kernel-shark-qt/src/libkshark.h
@@ -150,6 +150,9 @@ void kshark_free(struct kshark_context *kshark_ctx);
 
 char* kshark_dump_entry(const struct kshark_entry *entry);
 
+struct tep_record *kshark_read_at(struct kshark_context *kshark_ctx,
+				  uint64_t offset);
+
 /** Bit masks used to control the visibility of the entry after filtering. */
 enum kshark_filter_masks {
 	/**
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/7] kernel-shark-qt: Add src/plugins dir. to hold the source code of the plugins
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
                   ` (3 preceding siblings ...)
  2018-09-04 15:52 ` [PATCH 4/7] kernel-shark-qt: Make kshark_read_at() non-static Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/ Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events Yordan Karadzhov (VMware)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

Tell Cmake to enter src/plugins. Add a Cmake function for building plugin
libraries.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/CMakeLists.txt         |  2 ++
 kernel-shark-qt/src/plugins/CMakeLists.txt | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 kernel-shark-qt/src/plugins/CMakeLists.txt

diff --git a/kernel-shark-qt/src/CMakeLists.txt b/kernel-shark-qt/src/CMakeLists.txt
index cdc28c4c..3365413e 100644
--- a/kernel-shark-qt/src/CMakeLists.txt
+++ b/kernel-shark-qt/src/CMakeLists.txt
@@ -28,5 +28,7 @@ if (OPENGL_FOUND AND GLUT_FOUND)
 
 endif (OPENGL_FOUND AND GLUT_FOUND)
 
+add_subdirectory(plugins)
+
 configure_file( ${KS_DIR}/build/deff.h.cmake
                 ${KS_DIR}/src/KsDeff.h)
diff --git a/kernel-shark-qt/src/plugins/CMakeLists.txt b/kernel-shark-qt/src/plugins/CMakeLists.txt
new file mode 100644
index 00000000..565f1cb3
--- /dev/null
+++ b/kernel-shark-qt/src/plugins/CMakeLists.txt
@@ -0,0 +1,22 @@
+message("\n src/plugins ...")
+
+function(BUILD_PLUGIN)
+    set(options )
+    set(oneValueArgs NAME)
+    set(multiValueArgs SOURCE)
+    cmake_parse_arguments(ADD_PLUGIN "${options}"
+                                     ${oneValueArgs}
+                                     ${multiValueArgs}
+                                     ${ARGN})
+
+    message(STATUS ${ADD_PLUGIN_NAME})
+
+    add_library(${ADD_PLUGIN_NAME} SHARED ${ADD_PLUGIN_SOURCE})
+    set_target_properties(${ADD_PLUGIN_NAME} PROPERTIES PREFIX "plugin-")
+    target_link_libraries(${ADD_PLUGIN_NAME} kshark)
+
+endfunction()
+
+set(PLUGIN_LIST "")
+
+set(PLUGINS ${PLUGIN_LIST} PARENT_SCOPE)
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
                   ` (4 preceding siblings ...)
  2018-09-04 15:52 ` [PATCH 5/7] kernel-shark-qt: Add src/plugins dir. to hold the source code of the plugins Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  2018-09-04 15:52 ` [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events Yordan Karadzhov (VMware)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

This Patch adds ../src/plugins/ to the list of input locations used by
Doxygen to search for documented source files.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/doc/dox_config | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel-shark-qt/doc/dox_config b/kernel-shark-qt/doc/dox_config
index b982baa6..acc9083e 100644
--- a/kernel-shark-qt/doc/dox_config
+++ b/kernel-shark-qt/doc/dox_config
@@ -4,7 +4,7 @@
 DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "kernel-shark-qt"
 PROJECT_BRIEF = "Kernel Shark is a front-end reader of the Linux kernel tracing data."
-INPUT                  = "../src/"
+INPUT                  = ../src/ ../src/plugins/
 SOURCE_BROWSER         = YES
 QT_AUTOBRIEF           = YES
 TAB_SIZE               = 8
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events.
  2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
                   ` (5 preceding siblings ...)
  2018-09-04 15:52 ` [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/ Yordan Karadzhov (VMware)
@ 2018-09-04 15:52 ` Yordan Karadzhov (VMware)
  6 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-09-04 15:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

The plugin is responsible for the following actions, specific for
"sched" events:

1. Changes the value of the "pid" field of the "sched_switch" entries.
   This alows the sched_switch entry to be plotted as part of the "next"
   task.

2. On "sched_switch" event, the plugin registers the "next" task (if not
   registered already).

3. Plots in green the wake up latency of the task and in red the time
   the task was preempted by another task.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/src/plugins/CMakeLists.txt  |   5 +
 kernel-shark-qt/src/plugins/SchedEvents.cpp | 263 +++++++++++++++++
 kernel-shark-qt/src/plugins/sched_events.c  | 304 ++++++++++++++++++++
 kernel-shark-qt/src/plugins/sched_events.h  |  79 +++++
 4 files changed, 651 insertions(+)
 create mode 100644 kernel-shark-qt/src/plugins/SchedEvents.cpp
 create mode 100644 kernel-shark-qt/src/plugins/sched_events.c
 create mode 100644 kernel-shark-qt/src/plugins/sched_events.h

diff --git a/kernel-shark-qt/src/plugins/CMakeLists.txt b/kernel-shark-qt/src/plugins/CMakeLists.txt
index 565f1cb3..88fd93cf 100644
--- a/kernel-shark-qt/src/plugins/CMakeLists.txt
+++ b/kernel-shark-qt/src/plugins/CMakeLists.txt
@@ -19,4 +19,9 @@ endfunction()
 
 set(PLUGIN_LIST "")
 
+BUILD_PLUGIN(NAME sched_events
+             SOURCE sched_events.c SchedEvents.cpp)
+list(APPEND PLUGIN_LIST "sched_events default") # This plugin will be loaded by default
+# list(APPEND PLUGIN_LIST "sched_events") # This plugin isn't loaded by default
+
 set(PLUGINS ${PLUGIN_LIST} PARENT_SCOPE)
diff --git a/kernel-shark-qt/src/plugins/SchedEvents.cpp b/kernel-shark-qt/src/plugins/SchedEvents.cpp
new file mode 100644
index 00000000..04d9a506
--- /dev/null
+++ b/kernel-shark-qt/src/plugins/SchedEvents.cpp
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+/**
+ *  @file    SchedEvents.cpp
+ *  @brief   Defines a callback function for Sched events used to plot in green
+ *	     the wake up latency of the task and in red the time the task was
+ *	     preempted by another task.
+ */
+
+// C++
+#include<iostream>
+
+// C++ 11
+#include<functional>
+
+// KernelShark
+#include "libkshark.h"
+#include "plugins/sched_events.h"
+#include "KsPlotTools.hpp"
+#include "KsPlugins.hpp"
+
+//! @cond Doxygen_Suppress
+
+#define PLUGIN_MIN_BOX_SIZE 4
+
+#define PLUGIN_MAX_ENTRIES_PER_BIN 500
+
+//! @endcond
+
+extern struct plugin_sched_context *plugin_sched_context_handler;
+
+static int plugin_get_wakeup_pid(kshark_context *kshark_ctx,
+				 plugin_sched_context *plugin_ctx,
+				 const struct kshark_entry *e)
+{
+	struct tep_record *record;
+	unsigned long long val;
+
+	record = kshark_read_at(kshark_ctx, e->offset);
+	tep_read_number_field(plugin_ctx->sched_wakeup_pid_field,
+			      record->data, &val);
+	free(record);
+
+	return val;
+}
+
+/** Sched Event identifier. */
+enum class SchedEvent {
+	/** Sched Switch Event. */
+	Switch,
+
+	/** Sched Wakeup Event. */
+	Wakeup,
+};
+
+static void pluginDraw(plugin_sched_context *plugin_ctx,
+		       kshark_context *kshark_ctx,
+		       kshark_trace_histo *histo,
+		       kshark_entry_collection *col,
+		       SchedEvent e,
+		       int pid,
+		       KsPlot::Graph *graph,
+		       KsPlot::PlotObjList *shapes)
+{
+	std::function<void(int)> ifSchedBack;
+	KsPlot::Rectangle *rec = nullptr;
+	int height = graph->getHeight() * .3;
+
+	auto openBox = [&] (const KsPlot::Point &p)
+	{
+		/*
+		 * First check if we already have an open box. If we don't
+		 * have, open a new one.
+		 */
+		if (!rec)
+			rec = new KsPlot::Rectangle;
+
+		rec->setFill(false);
+		rec->setPoint(0, p.x() - 1, p.y() - height);
+		rec->setPoint(1, p.x() - 1, p.y() - 1);
+	};
+
+	auto closeBox = [&] (const KsPlot::Point &p)
+	{
+		if (rec == nullptr)
+			return;
+
+		int boxSize = rec->getPoint(0)->x;
+		if (boxSize < PLUGIN_MIN_BOX_SIZE) {
+			/* This box is too small. Don't try to plot it. */
+			delete rec;
+			rec = nullptr;
+			return;
+		}
+
+		rec->setPoint(3, p.x() - 1, p.y() - height);
+		rec->setPoint(2, p.x() - 1, p.y() - 1);
+
+		shapes->push_front(rec);
+		rec = nullptr;
+	};
+
+	auto lamIfSchSwitchFront = [&] (int bin)
+	{
+		/*
+		 * Starting from the first element in this bin, go forward
+		 * in time until you find a trace entry that satisfies the
+		 * condition defined by kshark_match_pid.
+		 */
+		const kshark_entry *entryF =
+			ksmodel_get_entry_front(histo, bin, false,
+						kshark_match_pid, pid,
+						col, nullptr);
+
+		if (entryF &&
+		    entryF->pid == pid &&
+		    plugin_ctx->sched_switch_event &&
+		    entryF->event_id == plugin_ctx->sched_switch_event->id) {
+			/*
+			 * entryF is sched_switch_event. Close the box and add
+			 * it to the list of shapes to be ploted.
+			 */
+			closeBox(graph->getBin(bin)._base);
+		}
+	};
+
+	auto lamIfSchWakeupBack = [&] (int bin)
+	{
+		/*
+		 * Starting from the last element in this bin, go backward
+		 * in time until you find a trace entry that satisfies the
+		 * condition defined by plugin_wakeup_match_pid.
+		 */
+		const kshark_entry *entryB =
+			ksmodel_get_entry_back(histo, bin, false,
+					       plugin_wakeup_match_pid, pid,
+					       col, nullptr);
+		int wakeup_pid;
+
+		if (entryB &&
+		    plugin_ctx->sched_wakeup_event &&
+		    entryB->event_id == plugin_ctx->sched_wakeup_event->id) {
+			wakeup_pid =
+				plugin_get_wakeup_pid(kshark_ctx, plugin_ctx, entryB);
+			if (wakeup_pid == pid) {
+				/*
+				 * entryB is a sched_wakeup_event. Open a
+				 * green box here.
+				 */
+				openBox(graph->getBin(bin)._base);
+
+				 /* Green */
+				rec->_color = KsPlot::Color(0, 255, 0);
+			}
+		}
+	};
+
+	auto lamIfSchSwitchBack = [&] (int bin)
+	{
+		/*
+		 * Starting from the last element in this bin, go backward
+		 * in time until you find a trace entry that satisfies the
+		 * condition defined by plugin_switch_match_pid.
+		 */
+		const kshark_entry *entryB =
+			ksmodel_get_entry_back(histo, bin, false,
+					       plugin_switch_match_pid, pid,
+					       col, nullptr);
+
+		if (entryB &&
+		    entryB->pid != pid &&
+		    plugin_ctx->sched_switch_event &&
+		    entryB->event_id == plugin_ctx->sched_switch_event->id) {
+			/*
+			 * entryB is a sched_switch_event. Open a
+			 * red box here.
+			 */
+			openBox(graph->getBin(bin)._base);
+
+			/* Red */
+			rec->_color = KsPlot::Color(255, 0, 0);
+		}
+	};
+
+	if (e == SchedEvent::Switch)
+		ifSchedBack = lamIfSchSwitchBack;
+	else
+		ifSchedBack = lamIfSchWakeupBack;
+
+	for (int bin = 0; bin < graph->size(); ++bin) {
+		/**
+		 * Plotting the latencies makes sense only in the case of a
+		 * deep zoom. Here we set a naive threshold based on the number
+		 * of entries inside the current bin. This cut seems to work
+		 * well in all cases I tested so far, but it may result in
+		 * unexpected behavior with some unusual trace data-sets.
+		 * TODO: find a better criteria for deciding when to start
+		 * plotting latencies.
+		 */
+		if (ksmodel_bin_count(histo, bin) > PLUGIN_MAX_ENTRIES_PER_BIN)
+			continue;
+
+		lamIfSchSwitchFront(bin);
+
+		ifSchedBack(bin);
+	}
+
+	if (rec)
+		delete rec;
+
+	return;
+}
+
+/**
+ * @brief Plugin's draw function.
+ *
+ * @param argv_c: A C pointer to be converted to KsCppArgV (C++ struct).
+ * @param pid: Process Id.
+ * @param draw_action: Draw action identifier.
+ *
+ * @returns True if the Pid of the entry matches the value of "pid".
+ *	    Otherwise false.
+ */
+void plugin_draw(kshark_cpp_argv *argv_c, int pid, int draw_action)
+{
+	plugin_sched_context *plugin_ctx;
+	kshark_context *kshark_ctx(NULL);
+	kshark_entry_collection *col;
+
+	if (draw_action != KSHARK_PLUGIN_TASK_DRAW || pid == 0)
+		return;
+
+	plugin_ctx = plugin_sched_context_handler;
+	if (!plugin_ctx || !kshark_instance(&kshark_ctx))
+		return;
+
+	KsCppArgV *argvCpp = KS_ARGV_TO_CPP(argv_c);
+
+	/*
+	 * Try to find a collections for this task. It is OK if
+	 * coll = NULL.
+	 */
+	col = kshark_find_data_collection(kshark_ctx->collections,
+					  kshark_match_pid, pid);
+
+	try {
+		pluginDraw(plugin_ctx, kshark_ctx,
+			   argvCpp->_histo, col,
+			   SchedEvent::Switch, pid,
+			   argvCpp->_graph, argvCpp->_shapes);
+
+		pluginDraw(plugin_ctx, kshark_ctx,
+			   argvCpp->_histo, col,
+			   SchedEvent::Wakeup, pid,
+			   argvCpp->_graph, argvCpp->_shapes);
+	} catch (const std::exception &exc) {
+		std::cerr << "Exception in SchedEvents\n" << exc.what();
+	}
+}
diff --git a/kernel-shark-qt/src/plugins/sched_events.c b/kernel-shark-qt/src/plugins/sched_events.c
new file mode 100644
index 00000000..bc42c30a
--- /dev/null
+++ b/kernel-shark-qt/src/plugins/sched_events.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+/**
+ *  @file    sched_events.c
+ *  @brief   Defines a callback function for Sched events used to registers the
+ *	     "next" task (if not registered already) and to changes the value
+ *	     of the "pid" field of the "sched_switch" entries such that, it
+ *	     will be ploted as part of the "next" task.
+ */
+
+// C
+#include <stdlib.h>
+#include <stdio.h>
+
+// KernelShark
+#include "plugins/sched_events.h"
+
+/** Plugin context instance. */
+struct plugin_sched_context *plugin_sched_context_handler = NULL;
+
+static bool plugin_sched_update_context(struct kshark_context *kshark_ctx)
+{
+	struct plugin_sched_context *plugin_ctx;
+	struct event_format *event;
+
+	if (!plugin_sched_context_handler) {
+		plugin_sched_context_handler =
+		 malloc(sizeof(*plugin_sched_context_handler));
+	}
+
+	plugin_ctx = plugin_sched_context_handler;
+	plugin_ctx->handle = kshark_ctx->handle;
+	plugin_ctx->pevent = kshark_ctx->pevent;
+
+	event = tep_find_event_by_name(plugin_ctx->pevent,
+				       "sched", "sched_switch");
+	if (!event)
+		return false;
+
+	plugin_ctx->sched_switch_event = event;
+	plugin_ctx->sched_switch_next_field =
+		tep_find_any_field(event, "next_pid");
+
+	plugin_ctx->sched_switch_comm_field =
+		tep_find_field(event, "next_comm");
+
+	event = tep_find_event_by_name(plugin_ctx->pevent,
+				      "sched", "sched_wakeup");
+	if (!event)
+		return false;
+
+	plugin_ctx->sched_wakeup_event = event;
+	plugin_ctx->sched_wakeup_pid_field =
+		tep_find_any_field(event, "pid");
+
+	plugin_ctx->sched_wakeup_success_field =
+		tep_find_field(event, "success");
+
+	event = tep_find_event_by_name(plugin_ctx->pevent,
+				       "sched", "sched_wakeup_new");
+	if (!event)
+		return false;
+
+	plugin_ctx->sched_wakeup_new_event = event;
+	plugin_ctx->sched_wakeup_new_pid_field =
+		tep_find_any_field(event, "pid");
+
+	plugin_ctx->sched_wakeup_new_success_field =
+		tep_find_field(event, "success");
+
+	return true;
+}
+
+/**
+ * @brief Get the Process Id of the next scheduled task.
+ *
+ * @param record: Input location for a sched_switch record.
+ */
+int plugin_get_next_pid(struct tep_record *record)
+{
+	struct plugin_sched_context *plugin_ctx =
+		plugin_sched_context_handler;
+	unsigned long long val;
+
+	tep_read_number_field(plugin_ctx->sched_switch_next_field,
+			      record->data, &val);
+	return val;
+}
+
+/**
+ * @brief Get the Process Id of the task being woke up.
+ *
+ * @param record: Input location for a sched_wakeup record.
+ */
+int plugin_get_wakeup_pid(struct tep_record *record)
+{
+	struct plugin_sched_context *plugin_ctx =
+		plugin_sched_context_handler;
+	unsigned long long val;
+
+	tep_read_number_field(plugin_ctx->sched_wakeup_pid_field,
+			      record->data, &val);
+	return val;
+}
+
+static void plugin_register_command(struct kshark_context *kshark_ctx,
+				    struct tep_record *record,
+				    int pid)
+{
+	struct plugin_sched_context *plugin_ctx =
+		plugin_sched_context_handler;
+	const char *comm;
+
+	if (plugin_ctx->sched_switch_comm_field) {
+			comm = record->data +
+			       plugin_ctx->sched_switch_comm_field->offset;
+	}
+
+	if (!tep_pid_is_registered(kshark_ctx->pevent, pid))
+			tep_register_comm(kshark_ctx->pevent, comm, pid);
+}
+
+static int plugin_get_wakeup_new_pid(struct tep_record *record)
+{
+	struct plugin_sched_context *plugin_ctx =
+		plugin_sched_context_handler;
+	unsigned long long val;
+
+	tep_read_number_field(plugin_ctx->sched_wakeup_new_pid_field,
+				 record->data, &val);
+
+	return val;
+}
+
+/**
+ * @brief Process Id matching function adapted for sched_wakeup and
+ *	  sched_wakeup_new events.
+ *
+ * @param kshark_ctx: Input location for the session context pointer.
+ * @param e: kshark_entry to be checked.
+ * @param pid: Matching condition value.
+ *
+ * @returns True if the Pid of the entry matches the value of "pid".
+ *	    Otherwise false.
+ */
+bool plugin_wakeup_match_pid(struct kshark_context *kshark_ctx,
+			     struct kshark_entry *e,
+			     int pid)
+{
+	struct plugin_sched_context *plugin_ctx;
+	struct tep_record *record = NULL;
+	unsigned long long val;
+	int wakeup_pid = -1;
+
+	if (e->pid == pid)
+		return true;
+
+	plugin_ctx = plugin_sched_context_handler;
+	if (!plugin_ctx)
+		return false;
+
+	if (plugin_ctx->sched_wakeup_event &&
+	    e->event_id == plugin_ctx->sched_wakeup_event->id) {
+		record = kshark_read_at(kshark_ctx, e->offset);
+
+		/* We only want those that actually woke up the task. */
+		tep_read_number_field(plugin_ctx->sched_wakeup_success_field,
+				      record->data, &val);
+
+		if (val)
+			wakeup_pid = plugin_get_wakeup_pid(record);
+	}
+
+	if (plugin_ctx->sched_wakeup_new_event &&
+	    e->event_id == plugin_ctx->sched_wakeup_new_event->id) {
+		record = kshark_read_at(kshark_ctx, e->offset);
+
+		/* We only want those that actually woke up the task. */
+		tep_read_number_field(plugin_ctx->sched_wakeup_new_success_field,
+				      record->data, &val);
+
+		if (val)
+			wakeup_pid = plugin_get_wakeup_new_pid(record);
+	}
+
+	free(record);
+
+	if (wakeup_pid >= 0 && wakeup_pid == pid)
+		return true;
+
+	return false;
+}
+
+/**
+ * @brief Process Id matching function adapted for sched_switch events.
+ *
+ * @param kshark_ctx: Input location for the session context pointer.
+ * @param e: kshark_entry to be checked.
+ * @param pid: Matching condition value.
+ *
+ * @returns True if the Pid of the entry matches the value of "pid".
+ *	    Otherwise false.
+ */
+bool plugin_switch_match_pid(struct kshark_context *kshark_ctx,
+			     struct kshark_entry *e,
+			     int pid)
+{
+	struct plugin_sched_context *plugin_ctx;
+	struct tep_record *record = NULL;
+	int switch_pid = -1;
+
+	if (e->pid == pid)
+		return true;
+
+	plugin_ctx = plugin_sched_context_handler;
+
+	if (plugin_ctx->sched_switch_event &&
+	    e->event_id == plugin_ctx->sched_switch_event->id) {
+		record = kshark_read_at(kshark_ctx, e->offset);
+
+		switch_pid = tep_data_pid(plugin_ctx->pevent, record);
+	}
+
+	free(record);
+
+	if (switch_pid >= 0 && switch_pid == pid)
+		return true;
+
+	return false;
+}
+
+static void plugin_sched_action(struct kshark_context *kshark_ctx,
+				struct tep_record *rec,
+				struct kshark_entry *entry)
+{
+	entry->pid = plugin_get_next_pid(rec);
+	plugin_register_command(kshark_ctx, rec, entry->pid);
+}
+
+static void plugin_sched_load()
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct plugin_sched_context *plugin_ctx;
+
+	kshark_instance(&kshark_ctx);
+
+	if (!plugin_sched_update_context(kshark_ctx)) {
+		free(plugin_sched_context_handler);
+		plugin_sched_context_handler = NULL;
+		return;
+	}
+
+	plugin_ctx = plugin_sched_context_handler;
+
+	kshark_register_event_handler(&kshark_ctx->event_handlers,
+				      plugin_ctx->sched_switch_event->id,
+				      plugin_sched_action,
+				      plugin_draw);
+}
+
+static void plugin_sched_unload()
+{
+	struct kshark_context *kshark_ctx = NULL;
+	struct plugin_sched_context *plugin_ctx;
+
+	if (!plugin_sched_context_handler)
+		return;
+
+	plugin_ctx = plugin_sched_context_handler;
+	kshark_instance(&kshark_ctx);
+
+	if (kshark_ctx) {
+		kshark_unregister_event_handler(&kshark_ctx->event_handlers,
+						plugin_ctx->sched_switch_event->id,
+						plugin_sched_action,
+						plugin_draw);
+	}
+
+	free(plugin_ctx);
+	plugin_sched_context_handler = NULL;
+}
+
+/** Load this plugin. */
+void KSHARK_PLUGIN_LOADER()
+{
+	plugin_sched_load();
+}
+
+/** Reload this plugin. */
+void KSHARK_PLUGIN_RELOADER()
+{
+	plugin_sched_unload();
+	plugin_sched_load();
+}
+
+/** Unload this plugin. */
+void KSHARK_PLUGIN_UNLOADER()
+{
+	plugin_sched_unload();
+}
diff --git a/kernel-shark-qt/src/plugins/sched_events.h b/kernel-shark-qt/src/plugins/sched_events.h
new file mode 100644
index 00000000..d0c125af
--- /dev/null
+++ b/kernel-shark-qt/src/plugins/sched_events.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+
+/*
+ * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+/**
+ *  @file    sched_events.h
+ *  @brief   Plugin for Sched events.
+ */
+
+#ifndef _KS_PLUGIN_SHED_H
+#define _KS_PLUGIN_SHED_H
+
+// trace-cmd
+#include "event-parse.h"
+
+// KernelShark
+#include "libkshark.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Structure representing a plugin-specific context. */
+struct plugin_sched_context {
+	/** Input handle for the trace data file. */
+	struct tracecmd_input	*handle;
+
+	/** Page event used to parse the page. */
+	struct tep_handle	*pevent;
+
+	/** Pointer to the sched_switch_event object. */
+	struct event_format	*sched_switch_event;
+
+	/** Pointer to the sched_switch_next_field format descriptor. */
+	struct format_field	*sched_switch_next_field;
+
+	/** Pointer to the sched_switch_comm_field format descriptor. */
+	struct format_field	*sched_switch_comm_field;
+
+	/** Pointer to the sched_wakeup_event object. */
+	struct event_format	*sched_wakeup_event;
+
+	/** Pointer to the sched_wakeup_pid_field format descriptor. */
+	struct format_field	*sched_wakeup_pid_field;
+
+	/** Pointer to the sched_wakeup_success_field format descriptor. */
+	struct format_field	*sched_wakeup_success_field;
+
+	/** Pointer to the sched_wakeup_new_event object. */
+	struct event_format	*sched_wakeup_new_event;
+
+	/** Pointer to the sched_wakeup_new_pid_field format descriptor. */
+	struct format_field	*sched_wakeup_new_pid_field;
+
+	/**
+	 * Pointer to the sched_wakeup_new_success_field format descriptor.
+	 */
+	struct format_field	*sched_wakeup_new_success_field;
+};
+
+int plugin_get_next_pid(struct tep_record *record);
+
+int plugin_get_wakeup_pid(struct tep_record *record);
+
+bool plugin_wakeup_match_pid(struct kshark_context *kshark_ctx,
+			     struct kshark_entry *e, int pid);
+
+bool plugin_switch_match_pid(struct kshark_context *kshark_ctx,
+			     struct kshark_entry *e, int pid);
+
+void plugin_draw(struct kshark_cpp_argv *argv, int pid, int draw_action);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS.
  2018-09-04 15:52 ` [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
@ 2018-09-05  2:09   ` Steven Rostedt
  0 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2018-09-05  2:09 UTC (permalink / raw)
  To: Yordan Karadzhov (VMware); +Cc: linux-trace-devel

On Tue,  4 Sep 2018 18:52:12 +0300
"Yordan Karadzhov (VMware)" <y.karadz@gmail.com> wrote:

> +/**
> + * @brief Use this function to load/reload/unload all registered plugins.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param task_id: Action identifier specifying the action to be executed.
> + *
> + * @returns The number of successful operations on success, or a negative error
> + *	    code on failure.
> + */
> +int kshark_handle_plugins(struct kshark_context *kshark_ctx,
> +			  int task_id)

task_id should be of type enum kshark_plugin_actions.

> +{
> +	kshark_plugin_load_func func;
> +	struct kshark_plugin_list *plugin;
> +	int fn_size = 0, plugin_count = 0;
> +	char* func_name;
> +
> +	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;

Why are you allocating the func_name?

			func_name = KSHARK_PLUGIN_UNLOADER_NAME;

should work.

> +
> +		default:
> +			return -EINVAL;
> +	}
> +
> +	if (fn_size <= 0) {
> +		fprintf(stderr,
> +			"failed to allocate memory for plugin function name");
> +		return -ENOMEM;
> +	}
> +
> +	for (plugin = kshark_ctx->plugins; plugin; plugin = plugin->next) {
> +		if (task_id == KSHARK_PLUGIN_LOAD) {
> +			plugin->handle =
> +				dlopen(plugin->file, RTLD_NOW | RTLD_GLOBAL);
> +
> +			if (!plugin->handle) {
> +				fprintf(stderr,
> +					"cannot load plugin '%s'\n%s\n",
> +					plugin->file,
> +					dlerror());
> +
> +				continue;
> +			}
> +		}
> +
> +		if (plugin->handle) {
> +			func = dlsym(plugin->handle, func_name);
> +			if (!func) {
> +				fprintf(stderr,
> +					"cannot find func '%s' in plugin '%s'\n%s\n",
> +					func_name,
> +					plugin->file,
> +					dlerror());
> +
> +				dlclose(plugin->handle);
> +				plugin->handle = NULL;
> +				continue;
> +			}
> +
> +			func();

These functions need to take in two parameters and also return a value;

			ret = func(&plugin->private_data, kshark_ctx);

Otherwise the plugins will only be initializing global data and wont be
able to initialize per file. If we load two files, how are the plugins
going to know what event is for which file?

The plugin structure should have a "private_data" field that the plugin
can allocate to (that's why we pass in the address), and it should be
of type void *, that way the plugin can make any data structure it
wants to be associated to this kshark_ctx, and create its own data
scope per the file.

A plugin can also simply ignore that field if it doesn't need to
save any kind of state.

The function should also return a value to let the this context know if
it succeeded or simply should be ignored.

 < 0 return value is an error,
 = 0 return value is "ignore this plugin for this kshark_ctx"
 > 0 return value means, everything is good.

This is what I was trying to say in our meeting.

-- Steve


> +			++plugin_count;
> +
> +			if (task_id == KSHARK_PLUGIN_UNLOAD) {
> +				dlclose(plugin->handle);
> +				plugin->handle = NULL;
> +			}
> +		}
> +	}
> +
> +	free(func_name);
> +
> +	return plugin_count;
> +}
> diff --git a/kernel-shark-qt/src/libkshark-plugin.h b/kernel-shark-qt/src/libkshark-plugin.h
> new file mode 100644
> index 00000000..34143204
> --- /dev/null
> +++ b/kernel-shark-qt/src/libkshark-plugin.h
> @@ -0,0 +1,171 @@
> +/* SPDX-License-Identifier: LGPL-2.1 */
> +
> +/*
> + * Copyright (C) 2016 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
> + */
> +
> + /**
> +  *  @file    libkshark-plugin.h
> +  *  @brief   KernelShark plugins.
> +  */
> +
> +#ifndef _KSHARK_PLUGIN_H
> +#define _KSHARK_PLUGIN_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif // __cplusplus
> +
> +// trace-cmd
> +#include "event-parse.h"
> +
> +/* Quiet warnings over documenting simple structures */
> +//! @cond Doxygen_Suppress
> +
> +#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)
> +
> +struct kshark_context;
> +struct kshark_entry;
> +
> +//! @endcond
> +
> +/**
> + * A function type to be used when defining load/reload/unload plugin
> + * functions.
> + */
> +typedef int (*kshark_plugin_load_func)(void);
> +
> +struct kshark_trace_histo;
> +
> +/**
> + * Structure representing the C arguments of the drawing function of
> + * a plugin.
> + */
> +struct kshark_cpp_argv {
> +	/** Pointer to the model descriptor object. */
> +	struct kshark_trace_histo	*histo;
> +};
> +
> +/** A function type to be used when defining plugin functions for drawing. */
> +typedef void
> +(*kshark_plugin_draw_handler_func)(struct kshark_cpp_argv *argv,
> +				   int val, int draw_action);
> +
> +/**
> + * A function type to be used when defining plugin functions for data
> + * manipulation.
> + */
> +typedef void
> +(*kshark_plugin_event_handler_func)(struct kshark_context *kshark_ctx,
> +				    struct tep_record *rec,
> +				    struct kshark_entry *e);
> +
> +/** Plugin action identifier. */
> +enum kshark_plugin_actions {
> +	/**
> +	 * Load plugins action. This action identifier is used when handling
> +	 * plugins.
> +	 */
> +	KSHARK_PLUGIN_LOAD,
> +
> +	/**
> +	 * Reload plugins action. This action identifier is used when handling
> +	 * plugins.
> +	 */
> +	KSHARK_PLUGIN_RELOAD,
> +
> +	/**
> +	 * Unload plugins action. This action identifier is used when handling
> +	 * plugins.
> +	 */
> +	KSHARK_PLUGIN_UNLOAD,
> +
> +	/**
> +	 * Task draw action. This action identifier is used by the plugin draw
> +	 * function.
> +	 */
> +	KSHARK_PLUGIN_TASK_DRAW,
> +
> +	/**
> +	 * CPU draw action. This action identifier is used by the plugin draw
> +	 * function.
> +	 */
> +	KSHARK_PLUGIN_CPU_DRAW,
> +};
> +
> +/**
> + * Plugin Event handler structure, defining the properties of the required
> + * kshark_entry.
> + */
> +struct kshark_event_handler {
> +	/** Pointer to the next Plugin Event handler. */
> +	struct kshark_event_handler		*next;
> +
> +	/** Unique Id ot the trace event type. */
> +	int					id;
> +
> +	/**
> +	 * Event action function. This action can be used to modify the content
> +	 * of all kshark_entries having Event Ids equal to "id".
> +	 */
> +	kshark_plugin_event_handler_func	event_func;
> +
> +	/**
> +	 * Draw action function. This action can be used to draw additional
> +	 * graphical elements (shapes) for all kshark_entries having Event Ids
> +	 * equal to "id".
> +	 */
> +	kshark_plugin_draw_handler_func		draw_func;
> +};
> +
> +struct kshark_event_handler *
> +find_event_handler(struct kshark_event_handler *handlers,
> +						int event_id);
> +
> +int kshark_register_event_handler(struct kshark_event_handler **handlers,
> +				  int event_id,
> +				  kshark_plugin_event_handler_func evt_func,
> +				  kshark_plugin_draw_handler_func dw_func);
> +
> +void kshark_unregister_event_handler(struct kshark_event_handler **handlers,
> +				     int event_id,
> +				     kshark_plugin_event_handler_func evt_func,
> +				     kshark_plugin_draw_handler_func dw_func);
> +
> +void kshark_free_event_handler_list(struct kshark_event_handler *handlers);
> +
> +/** Linked list of plugins. */
> +struct kshark_plugin_list {
> +	/** Pointer to the next Plugin. */
> +	struct kshark_plugin_list	*next;
> +
> +	/** The plugin object file to load. */
> +	char			*file;
> +
> +	/** Plugin Event handler. */
> +	void			*handle;
> +};
> +
> +int kshark_register_plugin(struct kshark_context *kshark_ctx,
> +			   const char *file);
> +
> +void kshark_unregister_plugin(struct kshark_context *kshark_ctx,
> +			      const char *file);
> +
> +void kshark_free_plugin_list(struct kshark_plugin_list *plugins);
> +
> +int kshark_handle_plugins(struct kshark_context *kshark_ctx, int task_id);
> +
> +#ifdef __cplusplus
> +}
> +#endif // __cplusplus
> +
> +#endif // _KSHARK_PLUGIN_H
> diff --git a/kernel-shark-qt/src/libkshark.h b/kernel-shark-qt/src/libkshark.h
> index 2580449a..fda133c8 100644
> --- a/kernel-shark-qt/src/libkshark.h
> +++ b/kernel-shark-qt/src/libkshark.h
> @@ -121,6 +121,9 @@ struct kshark_context {
>  
>  	/** List of Data collections. */
>  	struct kshark_entry_collection *collections;
> +
> +	/** List of Plugins. */
> +	struct kshark_plugin_list	*plugins;
>  };
>  
>  bool kshark_instance(struct kshark_context **kshark_ctx);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/
  2018-08-29 16:42 [PATCH 0/7] The infrastructure for plugins used by the Qt-based Yordan Karadzhov (VMware)
@ 2018-08-29 16:42 ` Yordan Karadzhov (VMware)
  0 siblings, 0 replies; 10+ messages in thread
From: Yordan Karadzhov (VMware) @ 2018-08-29 16:42 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel, Yordan Karadzhov (VMware)

This Patch adds ../src/plugins/ to the list of input locations used by
Doxygen to search for documented source files.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 kernel-shark-qt/doc/dox_config | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel-shark-qt/doc/dox_config b/kernel-shark-qt/doc/dox_config
index b982baa..acc9083 100644
--- a/kernel-shark-qt/doc/dox_config
+++ b/kernel-shark-qt/doc/dox_config
@@ -4,7 +4,7 @@
 DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "kernel-shark-qt"
 PROJECT_BRIEF = "Kernel Shark is a front-end reader of the Linux kernel tracing data."
-INPUT                  = "../src/"
+INPUT                  = ../src/ ../src/plugins/
 SOURCE_BROWSER         = YES
 QT_AUTOBRIEF           = YES
 TAB_SIZE               = 8
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-09-05  6:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-04 15:52 [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
2018-09-05  2:09   ` Steven Rostedt
2018-09-04 15:52 ` [PATCH 2/7] kernel-shark-qt: Add Plugin event handlers to session Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 3/7] kernel-shark-qt: Add C++/C conversion for args of a plugin draw function Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 4/7] kernel-shark-qt: Make kshark_read_at() non-static Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 5/7] kernel-shark-qt: Add src/plugins dir. to hold the source code of the plugins Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/ Yordan Karadzhov (VMware)
2018-09-04 15:52 ` [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events Yordan Karadzhov (VMware)
  -- strict thread matches above, loose matches on Subject: below --
2018-08-29 16:42 [PATCH 0/7] The infrastructure for plugins used by the Qt-based Yordan Karadzhov (VMware)
2018-08-29 16:42 ` [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/ Yordan Karadzhov (VMware)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.