Messages in this thread Patch in this message | | | From | "Yordan Karadzhov (VMware)" <> | Subject | [PATCH v2 4/4] kernelshark: Adding a GUI plugin for xenomai events | Date | Fri, 10 Nov 2017 14:29:15 +0200 |
| |
A plugin for processing xenomai events "cobalt_switch_context" and "cobalt_thread_resume" is added.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com> --- 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 <y.karadz@gmail.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 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
| |