From: Tom Zanussi <tom.zanussi@linux.intel.com>
To: rostedt@goodmis.org
Cc: tglx@linutronix.de, mhiramat@kernel.org, namhyung@kernel.org,
linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org,
Tom Zanussi <tom.zanussi@linux.intel.com>
Subject: [RFC][PATCH 19/21] tracing: Add 'onmatch' hist trigger action support
Date: Wed, 8 Feb 2017 11:25:15 -0600 [thread overview]
Message-ID: <d18055cfec5d6a16d047804a816a05f1676c050e.1486569306.git.tom.zanussi@linux.intel.com> (raw)
In-Reply-To: <cover.1486569306.git.tom.zanussi@linux.intel.com>
In-Reply-To: <cover.1486569306.git.tom.zanussi@linux.intel.com>
Add an 'onmatch().trace(event)' hist trigger action which is invoked
with the set of resolved variables named in the given synthetic event.
The result is the generation of a synthetic event that consists of the
values contained in those variables at the time the invoking event was
hit.
As an example the below defines a simple synthetic event using a
variable defined on the sched_wakeup_new event, and shows the event
definition with unresolved fields, since the sched_wakeup_new event
with the testpid variable hasn't been defined yet:
# echo 'wakeup_new_test pid=sched_wakeup_new:testpid' >> \
/sys/kernel/debug/tracing/synthetic_events
# cat /sys/kernel/debug/tracing/synthetic_events
wakeup_new_test pid=sched_wakeup_new:testpid*
The following hist trigger both defines the missing testpid variable
and specifies an onmatch().trace action that generates a
wakeup_new_test synthetic event whenever a sched_wakeup_new event
occurs, which because of the 'if comm == "cyclictest"' filter only
happens when the executable is cyclictest:
# echo 'hist:keys=testpid=pid:onmatch().trace(wakeup_new_test) \
if comm=="cyclictest"' >> \
/sys/kernel/debug/tracing/events/sched/sched_wakeup_new/trigger
Creating and displaying a histogram based on those events is now just
a matter of using the fields and new synthetic event in the
tracing/events/synthetic directory, as usual:
# echo 'hist:keys=pid:sort=pid' >> \
/sys/kernel/debug/tracing/events/synthetic/wakeup_new_test/trigger
Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
---
kernel/trace/trace_events_hist.c | 167 +++++++++++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 46da09f..2f9efb8 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -279,6 +279,7 @@ static u64 hist_field_timestamp(struct hist_field *hist_field,
}
static LIST_HEAD(hist_var_list);
+static LIST_HEAD(hist_action_list);
struct hist_var_data {
struct list_head list;
@@ -610,6 +611,16 @@ static int parse_action(char *str, struct hist_trigger_attrs *attrs)
if (attrs->n_actions == HIST_ACTIONS_MAX)
return -EINVAL;
+ if ((strncmp(str, "onmatch(", strlen("onmatch(")) == 0)) {
+ attrs->action_str[attrs->n_actions] = kstrdup(str, GFP_KERNEL);
+ if (!attrs->action_str[attrs->n_actions]) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ attrs->n_actions++;
+ ret = 1;
+ }
+
return ret;
}
@@ -1823,6 +1834,129 @@ static int add_synthetic_var_refs(struct hist_trigger_data *hist_data,
return var_ref_idx;
}
+static void action_trace(struct hist_trigger_data *hist_data,
+ struct tracing_map_elt *elt, void *rec,
+ struct ring_buffer_event *rbe,
+ struct action_data *data, u64 *var_ref_vals)
+{
+ struct synthetic_event *event = data->synthetic_event;
+
+ trace_synthetic(event, var_ref_vals, data->var_ref_idx);
+}
+
+static bool check_hist_action_refs(struct hist_trigger_data *hist_data,
+ struct synthetic_event *event)
+{
+ unsigned int i;
+
+ for (i = 0; i < hist_data->n_actions; i++) {
+ struct action_data *data = hist_data->actions[i];
+
+ if (data->fn == action_trace && data->synthetic_event == event)
+ return true;
+ }
+
+ return false;
+}
+
+static bool check_synthetic_action_refs(struct synthetic_event *event)
+{
+ struct hist_var_data *var_data;
+
+ list_for_each_entry(var_data, &hist_action_list, list)
+ if (check_hist_action_refs(var_data->hist_data, event))
+ return true;
+
+ return false;
+}
+
+static struct hist_var_data *find_hist_actions(struct hist_trigger_data *hist_data)
+{
+ struct hist_var_data *var_data, *found = NULL;
+
+ list_for_each_entry(var_data, &hist_action_list, list) {
+ if (var_data->hist_data == hist_data) {
+ found = var_data;
+ break;
+ }
+ }
+
+ return found;
+}
+
+static int save_hist_actions(struct hist_trigger_data *hist_data)
+{
+ struct hist_var_data *var_data;
+
+ var_data = find_hist_actions(hist_data);
+ if (var_data)
+ return 0;
+
+ var_data = kzalloc(sizeof(*var_data), GFP_KERNEL);
+ if (!var_data)
+ return -ENOMEM;
+
+ var_data->hist_data = hist_data;
+ list_add(&var_data->list, &hist_action_list);
+
+ return 0;
+}
+
+static int remove_hist_actions(struct hist_trigger_data *hist_data)
+{
+ struct hist_var_data *var_data;
+
+ var_data = find_hist_actions(hist_data);
+ if (!var_data)
+ return -EINVAL;
+
+ list_del(&var_data->list);
+
+ return 0;
+}
+
+static int create_onmatch_data(char *str, struct hist_trigger_data *hist_data)
+{
+ char *fn_name, *param;
+ struct action_data *data;
+ int ret = 0;
+
+ strsep(&str, ".");
+ if (!str)
+ return -EINVAL;
+
+ fn_name = strsep(&str, "(");
+ if (!fn_name || !str)
+ return -EINVAL;
+
+ if (strncmp(fn_name, "trace", strlen("trace")) == 0) {
+ struct synthetic_event *event;
+
+ param = strsep(&str, ")");
+ if (!param)
+ return -EINVAL;
+
+ event = find_synthetic_event(param);
+ if (!event)
+ return -EINVAL;
+
+ if (!resolve_pending_var_refs(event))
+ return -EINVAL;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->fn = action_trace;
+ data->synthetic_event = event;
+ data->var_ref_idx = add_synthetic_var_refs(hist_data, event);
+ hist_data->actions[hist_data->n_actions++] = data;
+ save_hist_actions(hist_data);
+ }
+
+ return ret;
+}
+
static void destroy_actions(struct hist_trigger_data *hist_data)
{
unsigned int i;
@@ -1842,6 +1976,14 @@ static int create_actions(struct hist_trigger_data *hist_data)
for (i = 0; i < hist_data->attrs->n_actions; i++) {
str = hist_data->attrs->action_str[i];
+
+ if (strncmp(str, "onmatch(", strlen("onmatch(")) == 0) {
+ char *action_str = str + strlen("onmatch(");
+
+ ret = create_onmatch_data(action_str, hist_data);
+ if (ret)
+ return ret;
+ }
}
return ret;
@@ -1858,6 +2000,16 @@ static void print_actions(struct seq_file *m,
}
}
+static void print_onmatch_spec(struct seq_file *m,
+ struct hist_trigger_data *hist_data,
+ struct action_data *data)
+{
+ seq_puts(m, ":onmatch().");
+
+ if (data->synthetic_event)
+ seq_printf(m, "trace(%s)", data->synthetic_event->name);
+}
+
static void print_actions_spec(struct seq_file *m,
struct hist_trigger_data *hist_data)
{
@@ -1865,6 +2017,9 @@ static void print_actions_spec(struct seq_file *m,
for (i = 0; i < hist_data->n_actions; i++) {
struct action_data *data = hist_data->actions[i];
+
+ if (data->fn == action_trace)
+ print_onmatch_spec(m, hist_data, data);
}
}
@@ -2428,6 +2583,9 @@ static void event_hist_trigger_free(struct event_trigger_ops *ops,
if (remove_hist_vars(hist_data))
return;
+ if (remove_hist_actions(hist_data))
+ return;
+
destroy_hist_data(hist_data);
}
}
@@ -3417,6 +3575,10 @@ static int create_synthetic_event(int argc, char **argv)
event = find_synthetic_event(token);
if (event) {
if (delete_event) {
+ if (check_synthetic_action_refs(event)) {
+ ret = -EINVAL;
+ goto out;
+ }
remove_synthetic_event(event);
goto err;
} else
@@ -3462,6 +3624,11 @@ static int release_all_synthetic_events(void)
mutex_lock(&synthetic_event_mutex);
+ list_for_each_entry(event, &synthetic_events_list, list) {
+ if (check_synthetic_action_refs(event))
+ return -EINVAL;
+ }
+
list_for_each_entry_safe(event, e, &synthetic_events_list, list) {
remove_synthetic_event(event);
free_synthetic_event(event);
--
1.9.3
next prev parent reply other threads:[~2017-02-08 17:31 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-08 17:24 [RFC][PATCH 00/21] tracing: Inter-event (e.g. latency) support Tom Zanussi
2017-02-08 17:24 ` [RFC][PATCH 01/21] tracing: Add hist_field_name() accessor Tom Zanussi
2017-02-08 20:09 ` Steven Rostedt
2017-02-08 17:24 ` [RFC][PATCH 02/21] tracing: Reimplement log2 Tom Zanussi
2017-02-08 20:13 ` Steven Rostedt
2017-02-08 20:25 ` Tom Zanussi
2017-02-08 17:24 ` [RFC][PATCH 03/21] ring-buffer: Add TIME_EXTEND_ABS ring buffer type Tom Zanussi
2017-02-08 20:32 ` Steven Rostedt
2017-02-08 20:55 ` Tom Zanussi
2017-02-09 14:54 ` Steven Rostedt
2017-02-10 6:04 ` Namhyung Kim
2017-02-10 14:28 ` Steven Rostedt
2017-02-08 17:25 ` [RFC][PATCH 04/21] tracing: Give event triggers access to ring_buffer_event Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 05/21] tracing: Add ring buffer event param to hist field functions Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 06/21] tracing: Increase tracing map KEYS_MAX size Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 07/21] tracing: Break out hist trigger assignment parsing Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 08/21] tracing: Make traceprobe parsing code reusable Tom Zanussi
2017-02-09 20:40 ` Steven Rostedt
2017-02-08 17:25 ` [RFC][PATCH 09/21] tracing: Add hist trigger timestamp support Tom Zanussi
2017-02-10 6:14 ` Namhyung Kim
2017-02-08 17:25 ` [RFC][PATCH 10/21] tracing: Add per-element variable support to tracing_map Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 11/21] tracing: Add variable support to hist triggers Tom Zanussi
2017-02-13 6:03 ` Namhyung Kim
2017-02-14 15:25 ` Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 12/21] tracing: Account for variables in named trigger compatibility Tom Zanussi
2017-02-13 6:04 ` Namhyung Kim
2017-02-14 15:26 ` Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 13/21] tracing: Add simple expression support to hist triggers Tom Zanussi
2017-02-14 2:37 ` Namhyung Kim
2017-02-14 15:29 ` Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 14/21] tracing: Add variable reference handling " Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 15/21] tracing: Add usecs modifier for hist trigger timestamps Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 16/21] tracing: Add support for dynamic tracepoints Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 17/21] tracing: Add hist trigger action hook Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 18/21] tracing: Add support for 'synthetic' events Tom Zanussi
2017-02-08 17:25 ` Tom Zanussi [this message]
2017-02-08 17:25 ` [RFC][PATCH 20/21] tracing: Add 'onmax' hist trigger action support Tom Zanussi
2017-02-08 17:25 ` [RFC][PATCH 21/21] tracing: Add inter-event hist trigger Documentation Tom Zanussi
2017-02-08 20:01 ` [RFC][PATCH 00/21] tracing: Inter-event (e.g. latency) support Steven Rostedt
2017-02-08 20:19 ` Tom Zanussi
2017-02-08 23:28 ` Tom Zanussi
2017-02-09 2:14 ` Steven Rostedt
2017-02-08 23:13 ` Masami Hiramatsu
2017-02-09 1:14 ` Tom Zanussi
2017-02-09 14:18 ` Masami Hiramatsu
2017-02-09 17:18 ` Tom Zanussi
2017-02-09 19:57 ` Steven Rostedt
2017-02-09 14:46 ` Frank Ch. Eigler
2017-02-09 18:43 ` Tom Zanussi
2017-02-10 4:16 ` Namhyung Kim
2017-02-10 9:34 ` Masami Hiramatsu
2017-02-10 18:58 ` Tom Zanussi
2017-02-13 1:04 ` Namhyung Kim
2017-02-14 9:37 ` Masami Hiramatsu
2017-02-14 15:27 ` Tom Zanussi
2017-02-10 18:43 ` Tom Zanussi
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=d18055cfec5d6a16d047804a816a05f1676c050e.1486569306.git.tom.zanussi@linux.intel.com \
--to=tom.zanussi@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-users@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=namhyung@kernel.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome