A plugin for processing xenomai events "cobalt_switch_context"
and "cobalt_thread_resume" is added.

Signed-off-by: Yordan Karadzhov (VMware) <[email protected]>
---
 Makefile             |   1 +
 kshark-plugin.h      |  10 ++
 plugin_xenomai_gui.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 311 insertions(+)
 create mode 100644 plugin_xenomai_gui.c

diff --git a/Makefile b/Makefile
index 992e6b0..e4d280b 100644
--- a/Makefile
+++ b/Makefile
@@ -384,6 +384,7 @@ 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)
 
diff --git a/kshark-plugin.h b/kshark-plugin.h
index 42fb40c..1166781 100644
--- a/kshark-plugin.h
+++ b/kshark-plugin.h
@@ -53,6 +53,16 @@ enum gui_plugin_actions {
        KSHARK_PLUGIN_GET_COMMAND,
 };
 
+enum gui_plugin_ctx_updates {
+       KSHARK_PLUGIN_UPDATE_SWITCH_EVENT       = (1 << 0),
+       KSHARK_PLUGIN_UPDATE_WAKEUP_EVENT       = (1 << 1),
+       KSHARK_PLUGIN_UPDATE_WAKEUP_PID         = (1 << 2),
+       KSHARK_PLUGIN_UPDATE_SWITCH_PID         = (1 << 3),
+       KSHARK_PLUGIN_UPDATE_PREV_STATE         = (1 << 4),
+       KSHARK_PLUGIN_UPDATE_NEXT_NAME          = (1 << 5),
+       KSHARK_PLUGIN_UPDATE_ALL                = INT_MAX
+};
+
 enum gui_event_types {
        KSHARK_PLUGIN_SWITCH_EVENT,
        KSHARK_PLUGIN_WAKEUP_EVENT,
diff --git a/plugin_xenomai_gui.c b/plugin_xenomai_gui.c
new file mode 100644
index 0000000..c786cc8
--- /dev/null
+++ b/plugin_xenomai_gui.c
@@ -0,0 +1,300 @@
+/*
+ *  Copyright (C) 2017 VMware Inc, Yordan Karadzhov <[email protected]>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * 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 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;
+struct gui_event_handler *switch_handler = NULL;
+struct gui_event_handler *wakeup_handler = NULL;
+
+#define COBALT_PREV_STATE_BIT          (1 << 3)
+#define COBALT_COMM_OFFSET_MASK        0xFFFF
+
+static gboolean xenomai_update_context(struct pevent *pevent, int task_id)
+{
+       struct event_format *event;
+       struct xenomai_context *ctx = xenomai_context_handler;
+
+       if (!ctx)
+               return FALSE;
+
+       if (task_id & KSHARK_PLUGIN_UPDATE_SWITCH_EVENT) {
+               event = pevent_find_event_by_name(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(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->pevent = tracecmd_get_pevent(info->handle);
+
+       int status = xenomai_update_context(xenomai_context_handler->pevent,
+                                           KSHARK_PLUGIN_UPDATE_ALL);
+       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 & COBALT_PREV_STATE_BIT) ? 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 &= COBALT_COMM_OFFSET_MASK;
+       *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;
+
+       if (!ctx)
+               return FALSE;
+
+       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;
+
+       if (!ctx)
+               return FALSE;
+
+       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;
+
+       switch_handler = make_gui_event_handler(ctx->cobalt_switch_event->id,
+                                               KSHARK_PLUGIN_SWITCH_EVENT,
+                                               xenomai_switch_handler,
+                                               xenomai_update_context);
+
+       wakeup_handler = make_gui_event_handler(ctx->cobalt_wakeup_event->id,
+                                               KSHARK_PLUGIN_WAKEUP_EVENT,
+                                               xenomai_wakeup_handler,
+                                               xenomai_update_context);
+
+       if (switch_handler && wakeup_handler) {
+               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_RELOADER(void *info, void *store)
+{
+       struct shark_info *ks_info = info;
+       struct trace_view_store *ks_store = store;
+
+       if (!xenomai_context_handler) {
+               xenomai_context_new(ks_info, ks_store);
+
+               if (!xenomai_context_handler)
+                       return;
+       } else {
+               int status = 
xenomai_update_context(tracecmd_get_pevent(ks_info->handle),
+                                                   KSHARK_PLUGIN_UPDATE_ALL);
+
+               if (status == FALSE)
+                       return;
+       }
+
+       if (switch_handler && wakeup_handler) {
+               trace_view_store_register_gui_handler(ks_store, switch_handler);
+               trace_view_store_register_gui_handler(ks_store, 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;
+
+       if (!ctx)
+               return;
+
+       if (switch_handler) {
+               unregister_gui_event_handler(&ks_store->event_handlers,
+                                            ctx->cobalt_switch_event->id);
+
+               unregister_gui_event_handler(&ks_info->ginfo->event_handlers,
+                                            ctx->cobalt_switch_event->id);
+
+               free(switch_handler);
+               switch_handler = NULL;
+       }
+
+       if (wakeup_handler) {
+               unregister_gui_event_handler(&ks_store->event_handlers,
+                                            ctx->cobalt_wakeup_event->id);
+
+               unregister_gui_event_handler(&ks_info->ginfo->event_handlers,
+                                            ctx->cobalt_wakeup_event->id);
+
+               free(wakeup_handler);
+               wakeup_handler = NULL;
+       }
+
+       free(ctx);
+       xenomai_context_handler = NULL;
+}
-- 
2.15.0.rc0

Reply via email to