* [PATCH] libtracefs: Add stacktrace to tracefs_sql()
@ 2023-01-17 16:35 Steven Rostedt
0 siblings, 0 replies; only message in thread
From: Steven Rostedt @ 2023-01-17 16:35 UTC (permalink / raw)
To: Linux Trace Devel; +Cc: Ross Zwisler
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Now that the kernel can pass stacktraces from the start to end of a
synthetic event, update the tracefs_sql() (and by doing so sqlhist) to
handle stacktrace.
A new keyword STACKTRACE is added, so the following will now work:
sqlhist -e -n block_lat 'SELECT (end.TIMESTAMP_USECS - start.TIMESTAMP_USECS) AS delta,start.STACKTRACE AS stack
FROM sched_switch AS start JOIN sched_switch AS end ON end.next_pid = start.prev_pid
WHERE start.prev_state == 1 && start.prev_prio < 100'
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Documentation/libtracefs-sql.txt | 13 +++++++++++++
include/tracefs.h | 2 ++
src/tracefs-filter.c | 10 ++++++++++
src/tracefs-hist.c | 3 ++-
src/tracefs-sqlhist.c | 5 ++++-
5 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/Documentation/libtracefs-sql.txt b/Documentation/libtracefs-sql.txt
index 6d606db..62fd771 100644
--- a/Documentation/libtracefs-sql.txt
+++ b/Documentation/libtracefs-sql.txt
@@ -162,6 +162,19 @@ select start.pid, (end.TIMESTAMP_USECS - start.TIMESTAMP_USECS) as lat from sche
WHERE start.prio < 100 || end.prev_prio < 100
--
+If the kernel supports it, you can pass around a stacktrace between events.
+
+[source, c]
+--
+select start.prev_pid as pid, (end.TIMESTAMP_USECS - start.TIMESTAMP_USECS) as delta, start.STACKTRACE as stack
+ FROM sched_switch as start JOIN sched_switch as end ON start.prev_pid = end.next_pid
+ WHERE start.prev_state == 2
+--
+
+The above will record a stacktrace when a task is in the UNINTERRUPTIBLE (blocked) state, and trigger
+the synthetic event when it is scheduled back in, recording the time delta that it was blocked for.
+It will record the stacktrace of where it was when it scheduled out along with the delta.
+
KEYWORDS AS EVENT FIELDS
------------------------
diff --git a/include/tracefs.h b/include/tracefs.h
index 3547b5a..23b3f8c 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -553,6 +553,8 @@ int tracefs_event_verify_filter(struct tep_event *event, const char *filter,
#define TRACEFS_TIMESTAMP "common_timestamp"
#define TRACEFS_TIMESTAMP_USECS "common_timestamp.usecs"
+#define TRACEFS_STACKTRACE "stacktrace"
+
enum tracefs_synth_handler {
TRACEFS_SYNTH_HANDLE_NONE = 0,
TRACEFS_SYNTH_HANDLE_MATCH,
diff --git a/src/tracefs-filter.c b/src/tracefs-filter.c
index a3dd77b..068329e 100644
--- a/src/tracefs-filter.c
+++ b/src/tracefs-filter.c
@@ -41,6 +41,13 @@ static const struct tep_format_field common_comm = {
.size = 16,
};
+static const struct tep_format_field stacktrace = {
+ .type = "unsigned long[]",
+ .name = "stacktrace",
+ .size = 4,
+ .flags = TEP_FIELD_IS_ARRAY | TEP_FIELD_IS_DYNAMIC,
+};
+
/*
* This also must be able to accept fields that are OK via the histograms,
* such as common_timestamp.
@@ -56,6 +63,9 @@ static const struct tep_format_field *get_event_field(struct tep_event *event,
if (!strcmp(field_name, TRACEFS_TIMESTAMP_USECS))
return &common_timestamp_usecs;
+ if (!strcmp(field_name, TRACEFS_STACKTRACE))
+ return &stacktrace;
+
field = tep_find_any_field(event, field_name);
if (!field && (!strcmp(field_name, "COMM") || !strcmp(field_name, "comm")))
return &common_comm;
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index fb6231e..1918670 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -915,7 +915,8 @@ static char *add_synth_field(const struct tep_format_field *field,
bool sign;
if (field->flags & TEP_FIELD_IS_ARRAY) {
- str = strdup("char");
+ str = strdup(field->type);
+ str = strtok(str, "[");
str = append_string(str, " ", name);
str = append_string(str, NULL, "[");
diff --git a/src/tracefs-sqlhist.c b/src/tracefs-sqlhist.c
index 3f571b7..0035922 100644
--- a/src/tracefs-sqlhist.c
+++ b/src/tracefs-sqlhist.c
@@ -566,7 +566,8 @@ static int test_field_exists(struct tep_handle *tep,
return -1;
if (!strcmp(field_name, TRACEFS_TIMESTAMP) ||
- !strcmp(field->field, TRACEFS_TIMESTAMP_USECS))
+ !strcmp(field->field, TRACEFS_TIMESTAMP_USECS) ||
+ !strcmp(field->field, TRACEFS_STACKTRACE))
tfield = (void *)1L;
else
tfield = tep_find_any_field(field->event, field_name);
@@ -695,6 +696,8 @@ static int update_vars(struct tep_handle *tep,
field->field = store_str(sb, TRACEFS_TIMESTAMP);
if (!strcmp(field->field, "TIMESTAMP_USECS"))
field->field = store_str(sb, TRACEFS_TIMESTAMP_USECS);
+ if (!strcmp(field->field, "STACKTRACE"))
+ field->field = store_str(sb, TRACEFS_STACKTRACE);
if (test_field_exists(tep, sb, expr))
return -1;
}
--
2.35.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2023-01-17 16:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-17 16:35 [PATCH] libtracefs: Add stacktrace to tracefs_sql() Steven Rostedt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).