From: Steven Rostedt <rostedt@goodmis.org>
To: "Yordan Karadzhov (VMware)" <y.karadz@gmail.com>
Cc: linux-trace-devel@vger.kernel.org
Subject: Re: [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events.
Date: Thu, 30 Aug 2018 13:38:32 -0400 [thread overview]
Message-ID: <20180830133832.657a8eab@gandalf.local.home> (raw)
In-Reply-To: <20180829164224.20677-8-y.karadz@gmail.com>
On Wed, 29 Aug 2018 19:42:24 +0300
"Yordan Karadzhov (VMware)" <y.karadz@gmail.com> wrote:
> --- /dev/null
> +++ b/kernel-shark-qt/src/plugins/SchedEvents.cpp
> @@ -0,0 +1,258 @@
> +// SPDX-License-Identifier: LGPL-2.1
> +
> +/*
> + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
> + */
> +
> +/**
> + * @file SchedEvents.cpp
> + * @brief Plugin for Sched events.
> + */
> +
> +// KernelShark
> +#include "libkshark.h"
> +#include "plugins/sched_events.h"
> +#include "KsPlotTools.hpp"
> +#include "KsPlugins.hpp"
> +
> +extern struct plugin_sched_context *plugin_sched_context_handler;
> +
> +static int plugin_get_wakeup_pid_lazy(struct kshark_context *kshark_ctx,
> + const struct kshark_entry *e)
> +{
> + struct plugin_sched_context *plugin_ctx;
> + struct tep_record *record;
> + unsigned long long val;
> +
> + plugin_ctx = plugin_sched_context_handler;
> + 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;
> +}
> +
> +static void openBox(KsPlot::Rectangle **rec,
> + const KsPlot::Bin &bin,
> + int height)
> +{
> + if (!*rec)
> + *rec = new KsPlot::Rectangle;
BTW, for exception handling here (if new fails), should there be some
sort of comments somewhere, about what types of exceptions should be
caught. This is more a general question and not specific to this code
here.
With C, one needs to always check for the return. Now, with C++ we can
do try { } catch, but then we need to be able to clean everything up.
I honestly think that try/catch can end up being sloppier than the C
way, but C is a bit more work to get right.
> +
> + (**rec).setFill(false);
> + (**rec).setPoint(0, bin._base.x() - 1,
> + bin._base.y() - height);
> +
> + (**rec).setPoint(1, bin._base.x() - 1,
> + bin._base.y() - 1);
> +}
> +
> +static void closeBox(KsPlot::Rectangle **rec,
> + const KsPlot::Bin &bin,
> + int height,
> + KsPlot::PlotObjList *list)
> +{
> + if (*rec == nullptr)
> + return;
> +
> + if (bin._base.x() - (**rec).getPoint(0)->x < 4) {
Let's keep from using hard coded numbers. Why 4? We should make this at
least a macro that can be changed. Or perhaps a variable in some class?
> + /* This box is too small.
> + * Don't try to plot it. */
> + delete *rec;
> + *rec = nullptr;
> + return;
> + }
> +
> + (**rec).setPoint(3, bin._base.x() - 1,
> + bin._base.y() - height);
> +
> + (**rec).setPoint(2, bin._base.x() - 1,
> + bin._base.y() - 1);
> +
> + list->push_front(*rec);
> + *rec = nullptr;
> +}
> +
> +static void schedWakeupPluginDraw(struct plugin_sched_context *plugin_ctx,
> + kshark_trace_histo *histo,
> + KsPlot::Graph *graph,
> + int pid,
> + KsPlot::PlotObjList *shapes)
> +{
> + const kshark_entry *entryF, *entryB;
> + KsPlot::Rectangle *rec = nullptr;
> + kshark_context *kshark_ctx(NULL);
> + kshark_entry_collection *col;
> + kshark_instance(&kshark_ctx);
> + int wakeup_pid;
> +
> + col = kshark_find_data_collection(kshark_ctx->collections,
> + kshark_match_pid, pid);
If col is NULL, should we just return right away? Or is col OK to be
NULL?
> +
> + size_t nBins = graph->size();
> + for (size_t bin = 0; bin < nBins; ++bin) {
> + if (ksmodel_bin_count(histo, bin) > 500)
Why 500?
> + continue;
> +
> + /*
> + * Starting from the first element in this bin, go forward
> + * in time until you find a trace entry that satisfies the
> + * condition defined by plugin_check_pid.
> + */
> + entryF = ksmodel_get_entry_front(histo, bin, false,
> + kshark_match_pid, pid,
> + col, nullptr);
> +
> + /*
> + * 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_check_pid.
> + */
> + entryB = ksmodel_get_entry_back(histo, bin, false,
> + plugin_wakeup_match_pid, pid,
> + col, nullptr);
> +
> + if (entryB &&
> + plugin_ctx->sched_wakeup_event &&
> + entryB->event_id == plugin_ctx->sched_wakeup_event->id) {
> + wakeup_pid =
> + plugin_get_wakeup_pid_lazy(kshark_ctx, entryB);
> + if (wakeup_pid == pid) {
> + /*
> + * entryB is a sched_wakeup_event. Open a
> + * green box here.
> + */
> + openBox(&rec, graph->getBin(bin),
> + graph->getHeight() * .3);
> +
> + /* Green */
> + rec->_color = KsPlot::Color(0, 255, 0);
> + }
> + }
> +
> + if (entryF &&
> + plugin_ctx->sched_switch_event &&
> + entryF->event_id == plugin_ctx->sched_switch_event->id &&
> + entryF->pid == pid) {
> + /*
> + * entryF is sched_switch_event. Close the box and add
> + * it to the list of shapes to be ploted.
> + */
> + closeBox(&rec, graph->getBin(bin),
> + graph->getHeight() * .3,
> + shapes);
> + }
> + }
> +
> + if (rec)
> + delete rec;
> +
> + return;
> +}
> +
> +static void schedSwitchPluginDraw(struct plugin_sched_context *plugin_ctx,
> + kshark_trace_histo *histo,
> + KsPlot::Graph *graph,
> + int pid,
> + KsPlot::PlotObjList *shapes)
This is quite similar to the function above, is there a way to combine
the two? This is C++ ;-)
-- Steve
> +{
> + const kshark_entry *entryF, *entryB;
> + KsPlot::Rectangle *rec = nullptr;
> + kshark_context *kshark_ctx(NULL);
> + kshark_entry_collection *col;
> +
> + kshark_instance(&kshark_ctx);
> + col = kshark_find_data_collection(kshark_ctx->collections,
> + kshark_match_pid, pid);
> +
> + size_t nBins = graph->size();
> + for (size_t bin = 0; bin < nBins; ++bin) {
> +
> + if (ksmodel_bin_count(histo, bin) > 500)
> + continue;
> +
> + /*
> + * 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.
> + */
> + entryF = ksmodel_get_entry_front(histo, bin, false,
> + kshark_match_pid, pid,
> + col, nullptr);
> +
> + /*
> + * 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_check_pid.
> + */
> + entryB = ksmodel_get_entry_back(histo, bin, false,
> + plugin_switch_match_pid, pid,
> + col, nullptr);
> +
> + if (entryB && entryB->pid != pid &&
> + entryB->event_id == plugin_ctx->sched_switch_event->id) {
> + /*
> + * entryB is a sched_switch_event.
> + * Open a red box here.
> + */
> + openBox(&rec, graph->getBin(bin),
> + graph->getHeight() * .3);
> +
> + /* Red */
> + rec->_color = KsPlot::Color(255, 0, 0);
> + }
> +
> + if (entryF && entryF->pid == pid &&
> + 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(&rec, graph->getBin(bin),
> + graph->getHeight() * .3,
> + shapes);
> + }
> + }
> +
> + 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(struct kshark_cpp_argv *argv_c, int pid, int draw_action)
> +{
> + if (draw_action != KSHARK_PLUGIN_TASK_DRAW || pid == 0)
> + return;
> +
> + struct plugin_sched_context *plugin_ctx =
> + plugin_sched_context_handler;
> +
> + if (!plugin_ctx)
> + return;
> +
> + KsCppArgV *argvCpp = KS_ARGV_TO_CPP(argv_c);
> +
> + schedWakeupPluginDraw(plugin_ctx, argvCpp->_histo,
> + argvCpp->_graph,
> + pid,
> + argvCpp->_shapes);
> +
> + schedSwitchPluginDraw(plugin_ctx, argvCpp->_histo,
> + argvCpp->_graph,
> + pid,
> + argvCpp->_shapes);
> +}
> 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 0000000..2885a22
> --- /dev/null
> +++ b/kernel-shark-qt/src/plugins/sched_events.c
> @@ -0,0 +1,302 @@
> +// SPDX-License-Identifier: LGPL-2.1
> +
> +/*
> + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
> + */
> +
> +/**
> + * @file sched_events.c
> + * @brief Plugin for Sched events.
> + */
> +
> +// 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 0000000..d0c125a
> --- /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
next prev parent reply other threads:[~2018-08-30 21:41 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
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 1/7] kernel-shark-qt: Add plugin infrastructure to be used by the Qt-baset KS Yordan Karadzhov (VMware)
2018-08-29 20:12 ` Steven Rostedt
2018-08-29 20:17 ` Steven Rostedt
2018-08-29 20:32 ` Steven Rostedt
2018-08-30 11:45 ` Yordan Karadzhov (VMware)
2018-08-30 16:17 ` Steven Rostedt
2018-08-29 16:42 ` [PATCH 2/7] kernel-shark-qt: Add Plugin event handlers to session Yordan Karadzhov (VMware)
2018-08-30 2:08 ` Steven Rostedt
2018-08-29 16:42 ` [PATCH 3/7] kernel-shark-qt: Add C++/C conversion for args of a plugin draw function Yordan Karadzhov (VMware)
2018-08-29 16:42 ` [PATCH 4/7] kernel-shark-qt: Make kshark_read_at() non-static Yordan Karadzhov (VMware)
2018-08-29 16:42 ` [PATCH 5/7] kernel-shark-qt: Add src/plugins dir. to hold the source code of the plugins Yordan Karadzhov (VMware)
2018-08-29 16:42 ` [PATCH 6/7] kernel-shark-qt: Tell Doxygen to enter ../src/plugins/ Yordan Karadzhov (VMware)
2018-08-29 16:42 ` [PATCH 7/7] kernel-shark-qt: Add a plugin for sched events Yordan Karadzhov (VMware)
2018-08-30 2:43 ` Steven Rostedt
2018-08-30 11:48 ` Yordan Karadzhov (VMware)
2018-08-30 11:49 ` Yordan Karadzhov (VMware)
2018-08-30 14:12 ` Steven Rostedt
2018-08-30 11:51 ` Yordan Karadzhov (VMware)
2018-08-30 14:13 ` Steven Rostedt
2018-08-30 14:50 ` Steven Rostedt
2018-08-30 17:38 ` Steven Rostedt [this message]
2018-08-29 16:49 ` [PATCH 0/7] Add infrastructure for plugins Yordan Karadzhov (VMware)
-- strict thread matches above, loose matches on Subject: below --
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)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180830133832.657a8eab@gandalf.local.home \
--to=rostedt@goodmis.org \
--cc=linux-trace-devel@vger.kernel.org \
--cc=y.karadz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.