* [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions
@ 2025-08-21 3:57 Crystal Wood
2025-08-21 3:57 ` [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
` (6 more replies)
0 siblings, 7 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Consolidate code between osnoise/timerlat and top/hist for easier
maintenance and less future divergence.
As a consequence, actions work on osnoise as well as timerlat, so
expose it to the user, document it, and test it.
Costa Shulyupin (1):
tools/rtla: Consolidate common parameters into shared structure
Crystal Wood (6):
tools/rtla: Move top/hist union members elsewhere
tools/rtla: Create common_apply_config()
tools/rtla: Consolidate code between osnoise/timerlat and hist/top
tools/rtla: Fix -A option name in test comment
tools/rtla: Add test engine support for unexpected output
tools/rtla: Add remaining support for osnoise actions
Documentation/tools/rtla/common_options.rst | 61 ++
.../tools/rtla/common_osnoise_options.rst | 8 +
.../tools/rtla/common_timerlat_options.rst | 74 +-
Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
.../tools/rtla/rtla-osnoise-hist.rst | 2 +
Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
.../tools/rtla/rtla-timerlat-hist.rst | 2 +
.../tools/rtla/rtla-timerlat-top.rst | 2 +
tools/tracing/rtla/src/Build | 1 +
tools/tracing/rtla/src/actions.c | 8 +-
tools/tracing/rtla/src/actions.h | 2 +-
tools/tracing/rtla/src/common.c | 345 ++++++++++
tools/tracing/rtla/src/common.h | 154 +++++
tools/tracing/rtla/src/osnoise.c | 101 ++-
tools/tracing/rtla/src/osnoise.h | 114 +---
tools/tracing/rtla/src/osnoise_hist.c | 369 ++++------
tools/tracing/rtla/src/osnoise_top.c | 303 +++------
tools/tracing/rtla/src/timerlat.c | 210 ++++--
tools/tracing/rtla/src/timerlat.h | 55 +-
tools/tracing/rtla/src/timerlat_bpf.c | 22 +-
tools/tracing/rtla/src/timerlat_hist.c | 642 +++++-------------
tools/tracing/rtla/src/timerlat_top.c | 568 ++++------------
tools/tracing/rtla/src/trace.h | 3 -
tools/tracing/rtla/tests/engine.sh | 22 +-
tools/tracing/rtla/tests/hwnoise.t | 2 +-
tools/tracing/rtla/tests/osnoise.t | 29 +-
tools/tracing/rtla/tests/timerlat.t | 4 +-
27 files changed, 1394 insertions(+), 1713 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.c
create mode 100644 tools/tracing/rtla/src/common.h
--
2.48.1
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-26 14:15 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere Crystal Wood
` (5 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
From: Costa Shulyupin <costa.shul@redhat.com>
timerlat_params and osnoise_params structures contain 15 identical
fields.
Introduce a new header common.h and define a common_params structure to
consolidate shared fields, reduce code duplication, and enhance
maintainability.
Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/src/common.h | 30 +++++++
tools/tracing/rtla/src/osnoise.c | 20 ++---
tools/tracing/rtla/src/osnoise.h | 19 +----
tools/tracing/rtla/src/osnoise_hist.c | 92 ++++++++++----------
tools/tracing/rtla/src/osnoise_top.c | 80 ++++++++---------
tools/tracing/rtla/src/timerlat.c | 24 +++---
tools/tracing/rtla/src/timerlat.h | 18 +---
tools/tracing/rtla/src/timerlat_bpf.c | 4 +-
tools/tracing/rtla/src/timerlat_hist.c | 113 +++++++++++++------------
tools/tracing/rtla/src/timerlat_top.c | 105 +++++++++++------------
10 files changed, 253 insertions(+), 252 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.h
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
new file mode 100644
index 000000000000..0a44cfaa7c0b
--- /dev/null
+++ b/tools/tracing/rtla/src/common.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#pragma once
+
+#include "utils.h"
+
+/*
+ * common_params - Parameters shared between timerlat_params and osnoise_params
+ */
+struct common_params {
+ /* trace configuration */
+ char *cpus;
+ cpu_set_t monitored_cpus;
+ struct trace_events *events;
+ int buffer_size;
+
+ /* Timing parameters */
+ int warmup;
+ long long stop_us;
+ long long stop_total_us;
+ int sleep_time;
+ int duration;
+
+ /* Scheduling parameters */
+ int set_sched;
+ struct sched_attr sched_param;
+ int cgroup;
+ char *cgroup_name;
+ int hk_cpus;
+ cpu_set_t hk_cpu_set;
+};
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 2dc3e4539e99..06ae7437c2c7 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -1127,10 +1127,10 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
{
int retval;
- if (!params->sleep_time)
- params->sleep_time = 1;
+ if (!params->common.sleep_time)
+ params->common.sleep_time = 1;
- retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
if (retval) {
err_msg("Failed to apply CPUs config\n");
goto out_err;
@@ -1151,13 +1151,13 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- retval = osnoise_set_stop_us(tool->context, params->stop_us);
+ retval = osnoise_set_stop_us(tool->context, params->common.stop_us);
if (retval) {
err_msg("Failed to set stop us\n");
goto out_err;
}
- retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
+ retval = osnoise_set_stop_total_us(tool->context, params->common.stop_total_us);
if (retval) {
err_msg("Failed to set stop total us\n");
goto out_err;
@@ -1169,14 +1169,14 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- if (params->hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
- ¶ms->hk_cpu_set);
+ if (params->common.hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
+ ¶ms->common.hk_cpu_set);
if (retval == -1) {
err_msg("Failed to set rtla to the house keeping CPUs\n");
goto out_err;
}
- } else if (params->cpus) {
+ } else if (params->common.cpus) {
/*
* Even if the user do not set a house-keeping CPU, try to
* move rtla to a CPU set different to the one where the user
@@ -1184,7 +1184,7 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
*
* No need to check results as this is an automatic attempt.
*/
- auto_house_keeping(¶ms->monitored_cpus);
+ auto_house_keeping(¶ms->common.monitored_cpus);
}
retval = osnoise_set_workload(tool->context, true);
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index ac1c99910744..0386bb50ffa1 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#pragma once
-#include "utils.h"
+#include "common.h"
#include "trace.h"
enum osnoise_mode {
@@ -10,26 +10,11 @@ enum osnoise_mode {
};
struct osnoise_params {
- /* Common params */
- char *cpus;
- cpu_set_t monitored_cpus;
+ struct common_params common;
char *trace_output;
- char *cgroup_name;
unsigned long long runtime;
unsigned long long period;
long long threshold;
- long long stop_us;
- long long stop_total_us;
- int sleep_time;
- int duration;
- int set_sched;
- int cgroup;
- int hk_cpus;
- cpu_set_t hk_cpu_set;
- struct sched_attr sched_param;
- struct trace_events *events;
- int warmup;
- int buffer_size;
union {
struct {
/* top only */
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 8d579bcee709..3fb9bb553498 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -243,7 +243,7 @@ static void osnoise_hist_header(struct osnoise_tool *tool)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -274,7 +274,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -288,7 +288,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -303,7 +303,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -321,7 +321,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -357,7 +357,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
bucket * data->bucket_size);
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -395,7 +395,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -537,7 +537,7 @@ static struct osnoise_params
switch (c) {
case 'a':
/* set sample stop to auto_thresh */
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
/* set sample threshold to 1 */
params->threshold = 1;
@@ -552,27 +552,27 @@ static struct osnoise_params
osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
osnoise_hist_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
osnoise_hist_usage("Invalid -D duration\n");
break;
case 'e':
@@ -582,10 +582,10 @@ static struct osnoise_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
+ if (params->common.events)
+ tevent->next = params->common.events;
- params->events = tevent;
+ params->common.events = tevent;
break;
case 'E':
params->entries = get_llong_from_str(optarg);
@@ -597,8 +597,8 @@ static struct osnoise_params
osnoise_hist_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
@@ -610,10 +610,10 @@ static struct osnoise_params
osnoise_hist_usage("Period longer than 10 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
osnoise_hist_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'r':
params->runtime = get_llong_from_str(optarg);
@@ -621,10 +621,10 @@ static struct osnoise_params
osnoise_hist_usage("Runtime shorter than 100 us\n");
break;
case 's':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'S':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 'T':
params->threshold = get_llong_from_str(optarg);
@@ -653,8 +653,8 @@ static struct osnoise_params
params->with_zeros = 1;
break;
case '4': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -664,8 +664,8 @@ static struct osnoise_params
}
break;
case '5': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -675,10 +675,10 @@ static struct osnoise_params
}
break;
case '6':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '7':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
default:
osnoise_hist_usage("Invalid option");
@@ -755,9 +755,9 @@ static void
osnoise_hist_set_signals(struct osnoise_params *params)
{
signal(SIGINT, stop_hist);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_hist);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -798,16 +798,16 @@ int osnoise_hist_main(int argc, char *argv[])
if (retval)
goto out_destroy;
- if (params->set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -821,14 +821,14 @@ int osnoise_hist_main(int argc, char *argv[])
goto out_free;
}
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_hist;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_hist;
}
@@ -845,9 +845,9 @@ int osnoise_hist_main(int argc, char *argv[])
trace_instance_start(&record->trace);
trace_instance_start(trace);
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_hist;
@@ -868,7 +868,7 @@ int osnoise_hist_main(int argc, char *argv[])
osnoise_hist_set_signals(params);
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -899,8 +899,8 @@ int osnoise_hist_main(int argc, char *argv[])
}
out_hist:
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
osnoise_free_histogram(tool->data);
out_destroy:
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 2c12780c8aa9..ad5daa8210aa 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -238,7 +238,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
osnoise_top_header(top);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
osnoise_top_print(top, i);
}
@@ -377,7 +377,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
switch (c) {
case 'a':
/* set sample stop to auto_thresh */
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
/* set sample threshold to 1 */
params->threshold = 1;
@@ -387,27 +387,27 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
osnoise_top_usage(params, "\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
osnoise_top_usage(params, "Invalid -d duration\n");
break;
case 'e':
@@ -417,9 +417,9 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
- params->events = tevent;
+ if (params->common.events)
+ tevent->next = params->common.events;
+ params->common.events = tevent;
break;
case 'h':
@@ -427,8 +427,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
@@ -440,10 +440,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "Period longer than 10 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
osnoise_top_usage(params, "Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'q':
params->quiet = 1;
@@ -454,10 +454,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "Runtime shorter than 100 us\n");
break;
case 's':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'S':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -474,8 +474,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->threshold = get_llong_from_str(optarg);
break;
case '0': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -485,8 +485,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
break;
case '1': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -496,10 +496,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
break;
case '2':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '3':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
default:
osnoise_top_usage(params, "Invalid option");
@@ -583,9 +583,9 @@ static void stop_top(int sig)
static void osnoise_top_set_signals(struct osnoise_params *params)
{
signal(SIGINT, stop_top);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_top);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -622,16 +622,16 @@ int osnoise_top_main(int argc, char **argv)
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup) {
- retval = set_comm_cgroup("osnoise/", params->cgroup_name);
+ if (params->common.cgroup) {
+ retval = set_comm_cgroup("osnoise/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -645,14 +645,14 @@ int osnoise_top_main(int argc, char **argv)
goto out_free;
}
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_top;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_top;
}
@@ -669,9 +669,9 @@ int osnoise_top_main(int argc, char **argv)
trace_instance_start(&record->trace);
trace_instance_start(trace);
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_top;
@@ -692,7 +692,7 @@ int osnoise_top_main(int argc, char **argv)
osnoise_top_set_signals(params);
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -725,8 +725,8 @@ int osnoise_top_main(int argc, char **argv)
}
out_top:
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
osnoise_free_top(tool->data);
osnoise_destroy_tool(record);
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 63d6d43eafff..0b2f03e1e612 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -26,18 +26,18 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
int retval, i;
- if (!params->sleep_time)
- params->sleep_time = 1;
+ if (!params->common.sleep_time)
+ params->common.sleep_time = 1;
- retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
if (retval) {
err_msg("Failed to apply CPUs config\n");
goto out_err;
}
- if (!params->cpus) {
+ if (!params->common.cpus) {
for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
- CPU_SET(i, ¶ms->monitored_cpus);
+ CPU_SET(i, ¶ms->common.monitored_cpus);
}
if (params->mode != TRACING_MODE_BPF) {
@@ -45,13 +45,13 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
* In tracefs and mixed mode, timerlat tracer handles stopping
* on threshold
*/
- retval = osnoise_set_stop_us(tool->context, params->stop_us);
+ retval = osnoise_set_stop_us(tool->context, params->common.stop_us);
if (retval) {
err_msg("Failed to set stop us\n");
goto out_err;
}
- retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
+ retval = osnoise_set_stop_total_us(tool->context, params->common.stop_total_us);
if (retval) {
err_msg("Failed to set stop total us\n");
goto out_err;
@@ -75,14 +75,14 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
goto out_err;
}
- if (params->hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
- ¶ms->hk_cpu_set);
+ if (params->common.hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
+ ¶ms->common.hk_cpu_set);
if (retval == -1) {
err_msg("Failed to set rtla to the house keeping CPUs\n");
goto out_err;
}
- } else if (params->cpus) {
+ } else if (params->common.cpus) {
/*
* Even if the user do not set a house-keeping CPU, try to
* move rtla to a CPU set different to the one where the user
@@ -90,7 +90,7 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
*
* No need to check results as this is an automatic attempt.
*/
- auto_house_keeping(¶ms->monitored_cpus);
+ auto_house_keeping(¶ms->common.monitored_cpus);
}
/*
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index bc55ed04fc96..dd9e0f05bdad 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -20,33 +20,17 @@ enum timerlat_tracing_mode {
};
struct timerlat_params {
- /* Common params */
- char *cpus;
- cpu_set_t monitored_cpus;
- char *cgroup_name;
- unsigned long long runtime;
- long long stop_us;
- long long stop_total_us;
+ struct common_params common;
long long timerlat_period_us;
long long print_stack;
- int sleep_time;
int output_divisor;
- int duration;
- int set_sched;
int dma_latency;
int no_aa;
int dump_tasks;
- int cgroup;
- int hk_cpus;
int user_workload;
int kernel_workload;
int user_data;
- int warmup;
- int buffer_size;
int deepest_idle_state;
- cpu_set_t hk_cpu_set;
- struct sched_attr sched_param;
- struct trace_events *events;
enum timerlat_tracing_mode mode;
struct actions threshold_actions;
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index 1666215dd687..a6c77ac55e00 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -23,8 +23,8 @@ int timerlat_bpf_init(struct timerlat_params *params)
/* Pass common options */
bpf->rodata->output_divisor = params->output_divisor;
bpf->rodata->entries = params->entries;
- bpf->rodata->irq_threshold = params->stop_us;
- bpf->rodata->thread_threshold = params->stop_total_us;
+ bpf->rodata->irq_threshold = params->common.stop_us;
+ bpf->rodata->thread_threshold = params->common.stop_total_us;
bpf->rodata->aa_only = params->aa_only;
if (params->entries != 0) {
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 9baea1b251ed..a3de644f2b75 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -303,7 +303,7 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -357,7 +357,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -381,7 +381,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -411,7 +411,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -441,7 +441,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -488,7 +488,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.min_user = ~0;
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -636,7 +636,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
bucket * data->bucket_size);
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -676,7 +676,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -867,8 +867,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -878,19 +878,19 @@ static struct timerlat_params
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
timerlat_hist_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'b':
@@ -902,8 +902,8 @@ static struct timerlat_params
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
timerlat_hist_usage("Invalid -D duration\n");
break;
case 'e':
@@ -913,10 +913,10 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
+ if (params->common.events)
+ tevent->next = params->common.events;
- params->events = tevent;
+ params->common.events = tevent;
break;
case 'E':
params->entries = get_llong_from_str(optarg);
@@ -928,15 +928,15 @@ static struct timerlat_params
timerlat_hist_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
}
break;
case 'i':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
params->kernel_workload = 1;
@@ -950,16 +950,16 @@ static struct timerlat_params
timerlat_hist_usage("Period longer than 1 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
timerlat_hist_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 's':
params->print_stack = get_llong_from_str(optarg);
break;
case 'T':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -997,8 +997,8 @@ static struct timerlat_params
params->with_zeros = 1;
break;
case '6': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1008,8 +1008,8 @@ static struct timerlat_params
}
break;
case '7': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1032,10 +1032,10 @@ static struct timerlat_params
params->dump_tasks = 1;
break;
case '\2':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '\3':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
case '\4':
params->deepest_idle_state = get_llong_from_str(optarg);
@@ -1076,7 +1076,7 @@ static struct timerlat_params
/*
* Auto analysis only happens if stop tracing, thus:
*/
- if (!params->stop_us && !params->stop_total_us)
+ if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
if (params->kernel_workload && params->user_workload)
@@ -1167,9 +1167,9 @@ static void
timerlat_hist_set_signals(struct timerlat_params *params)
{
signal(SIGINT, stop_hist);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_hist);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -1235,16 +1235,16 @@ int timerlat_hist_main(int argc, char *argv[])
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup && !params->user_workload) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup && !params->user_workload) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -1268,7 +1268,7 @@ int timerlat_hist_main(int argc, char *argv[])
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
if (save_cpu_idle_disable_state(i) < 0) {
err_msg("Could not save cpu idle state.\n");
@@ -1291,14 +1291,14 @@ int timerlat_hist_main(int argc, char *argv[])
params->threshold_actions.trace_output_inst = record->trace.inst;
params->end_actions.trace_output_inst = record->trace.inst;
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_hist;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_hist;
}
@@ -1328,22 +1328,22 @@ int timerlat_hist_main(int argc, char *argv[])
/* all threads left */
params_u.stopped_running = 0;
- params_u.set = ¶ms->monitored_cpus;
- if (params->set_sched)
- params_u.sched_param = ¶ms->sched_param;
+ params_u.set = ¶ms->common.monitored_cpus;
+ if (params->common.set_sched)
+ params_u.sched_param = ¶ms->common.sched_param;
else
params_u.sched_param = NULL;
- params_u.cgroup_name = params->cgroup_name;
+ params_u.cgroup_name = params->common.cgroup_name;
retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
if (retval)
err_msg("Error creating timerlat user-space threads\n");
}
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_hist;
}
@@ -1374,7 +1374,7 @@ int timerlat_hist_main(int argc, char *argv[])
if (params->mode == TRACING_MODE_TRACEFS) {
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -1456,7 +1456,8 @@ int timerlat_hist_main(int argc, char *argv[])
printf("rtla timerlat hit stop tracing\n");
if (!params->no_aa)
- timerlat_auto_analysis(params->stop_us, params->stop_total_us);
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
return_value = FAILED;
}
@@ -1467,13 +1468,13 @@ int timerlat_hist_main(int argc, char *argv[])
close(dma_latency_fd);
if (params->deepest_idle_state >= -1) {
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
restore_cpu_idle_disable_state(i);
}
}
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
timerlat_free_histogram(tool->data);
osnoise_destroy_tool(aa);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index c80b81c0b4da..9fb60f4dd092 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -457,7 +457,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
timerlat_top_header(params, top);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
timerlat_top_print(top, i);
timerlat_top_update_sum(top, i, &summary);
@@ -618,8 +618,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -633,8 +633,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -643,27 +643,27 @@ static struct timerlat_params
params->aa_only = 1;
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
timerlat_top_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
timerlat_top_usage("Invalid -d duration\n");
break;
case 'e':
@@ -673,24 +673,24 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
- params->events = tevent;
+ if (params->common.events)
+ tevent->next = params->common.events;
+ params->common.events = tevent;
break;
case 'h':
case '?':
timerlat_top_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
}
break;
case 'i':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
params->kernel_workload = true;
@@ -704,10 +704,10 @@ static struct timerlat_params
timerlat_top_usage("Period longer than 1 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
timerlat_top_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'q':
params->quiet = 1;
@@ -716,7 +716,7 @@ static struct timerlat_params
params->print_stack = get_llong_from_str(optarg);
break;
case 'T':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -736,8 +736,8 @@ static struct timerlat_params
params->user_data = true;
break;
case '0': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -747,8 +747,8 @@ static struct timerlat_params
}
break;
case '1': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -771,10 +771,10 @@ static struct timerlat_params
params->dump_tasks = 1;
break;
case '6':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '7':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
case '8':
params->deepest_idle_state = get_llong_from_str(optarg);
@@ -809,7 +809,7 @@ static struct timerlat_params
/*
* Auto analysis only happens if stop tracing, thus:
*/
- if (!params->stop_us && !params->stop_total_us)
+ if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
if (params->no_aa && params->aa_only)
@@ -906,9 +906,9 @@ static void
timerlat_top_set_signals(struct timerlat_params *params)
{
signal(SIGINT, stop_top);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_top);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -926,7 +926,7 @@ timerlat_top_main_loop(struct osnoise_tool *top,
int retval;
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
if (params->aa_only && !osnoise_trace_is_off(top, record))
continue;
@@ -992,7 +992,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
/* Pull and display data in a loop */
while (!stop_tracing) {
- wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->sleep_time);
+ wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->common.sleep_time);
retval = timerlat_top_bpf_pull_data(top);
if (retval) {
@@ -1094,16 +1094,16 @@ int timerlat_top_main(int argc, char *argv[])
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup && !params->user_data) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup && !params->user_data) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -1127,7 +1127,7 @@ int timerlat_top_main(int argc, char *argv[])
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
if (save_cpu_idle_disable_state(i) < 0) {
err_msg("Could not save cpu idle state.\n");
@@ -1150,14 +1150,14 @@ int timerlat_top_main(int argc, char *argv[])
params->threshold_actions.trace_output_inst = record->trace.inst;
params->end_actions.trace_output_inst = record->trace.inst;
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_top;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_top;
}
@@ -1190,22 +1190,22 @@ int timerlat_top_main(int argc, char *argv[])
/* all threads left */
params_u.stopped_running = 0;
- params_u.set = ¶ms->monitored_cpus;
- if (params->set_sched)
- params_u.sched_param = ¶ms->sched_param;
+ params_u.set = ¶ms->common.monitored_cpus;
+ if (params->common.set_sched)
+ params_u.sched_param = ¶ms->common.sched_param;
else
params_u.sched_param = NULL;
- params_u.cgroup_name = params->cgroup_name;
+ params_u.cgroup_name = params->common.cgroup_name;
retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
if (retval)
err_msg("Error creating timerlat user-space threads\n");
}
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
}
/*
@@ -1258,7 +1258,8 @@ int timerlat_top_main(int argc, char *argv[])
printf("rtla timerlat hit stop tracing\n");
if (!params->no_aa)
- timerlat_auto_analysis(params->stop_us, params->stop_total_us);
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
return_value = FAILED;
} else if (params->aa_only) {
@@ -1279,13 +1280,13 @@ int timerlat_top_main(int argc, char *argv[])
close(dma_latency_fd);
if (params->deepest_idle_state >= -1) {
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
restore_cpu_idle_disable_state(i);
}
}
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
timerlat_free_top(top->data);
if (aa && aa != top)
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-08-21 3:57 ` [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-26 13:58 ` Tomas Glozar
2025-08-26 18:05 ` Costa Shulyupin
2025-08-21 3:57 ` [PATCH 3/7] tools/rtla: Create common_apply_config() Crystal Wood
` (4 subsequent siblings)
6 siblings, 2 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
The hist members were very similar between timerlat and top, so
just use one common hist struct.
output_divisor, quiet, and pretty printing are pretty generic
concepts that can go in the main struct even if not every
specific tool (currently) uses them.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/src/common.h | 17 ++++
tools/tracing/rtla/src/osnoise.h | 19 +---
tools/tracing/rtla/src/osnoise_hist.c | 59 ++++++------
tools/tracing/rtla/src/osnoise_top.c | 19 ++--
tools/tracing/rtla/src/timerlat.h | 22 +----
tools/tracing/rtla/src/timerlat_bpf.c | 14 +--
tools/tracing/rtla/src/timerlat_hist.c | 127 +++++++++++++------------
tools/tracing/rtla/src/timerlat_top.c | 38 ++++----
8 files changed, 152 insertions(+), 163 deletions(-)
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 0a44cfaa7c0b..276dfbc7f955 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -3,6 +3,17 @@
#include "utils.h"
+struct hist_params {
+ char no_irq;
+ char no_thread;
+ char no_header;
+ char no_summary;
+ char no_index;
+ char with_zeros;
+ int bucket_size;
+ int entries;
+};
+
/*
* common_params - Parameters shared between timerlat_params and osnoise_params
*/
@@ -27,4 +38,10 @@ struct common_params {
char *cgroup_name;
int hk_cpus;
cpu_set_t hk_cpu_set;
+
+ /* Other parameters */
+ struct hist_params hist;
+ int output_divisor;
+ int pretty_output;
+ int quiet;
};
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index 0386bb50ffa1..b64b39de97b5 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -15,24 +15,7 @@ struct osnoise_params {
unsigned long long runtime;
unsigned long long period;
long long threshold;
- union {
- struct {
- /* top only */
- int quiet;
- int pretty_output;
- enum osnoise_mode mode;
- };
- struct {
- /* hist only */
- int output_divisor;
- char no_header;
- char no_summary;
- char no_index;
- char with_zeros;
- int bucket_size;
- int entries;
- };
- };
+ enum osnoise_mode mode;
};
/*
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 3fb9bb553498..a31ab9b4ab21 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -102,8 +102,8 @@ static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
int bucket;
int *hist;
- if (params->output_divisor)
- duration = duration / params->output_divisor;
+ if (params->common.output_divisor)
+ duration = duration / params->common.output_divisor;
bucket = duration / data->bucket_size;
@@ -146,7 +146,7 @@ static int osnoise_init_trace_hist(struct osnoise_tool *tool)
/*
* Set the size of the bucket.
*/
- bucket_size = params->output_divisor * params->bucket_size;
+ bucket_size = params->common.output_divisor * params->common.hist.bucket_size;
snprintf(buff, sizeof(buff), "duration.buckets=%d", bucket_size);
data->trace_hist = tracefs_hist_alloc(tool->trace.tep, "osnoise", "sample_threshold",
@@ -228,18 +228,18 @@ static void osnoise_hist_header(struct osnoise_tool *tool)
char duration[26];
int cpu;
- if (params->no_header)
+ if (params->common.hist.no_header)
return;
get_duration(tool->start_time, duration, sizeof(duration));
trace_seq_printf(s, "# RTLA osnoise histogram\n");
trace_seq_printf(s, "# Time unit is %s (%s)\n",
- params->output_divisor == 1 ? "nanoseconds" : "microseconds",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "nanoseconds" : "microseconds",
+ params->common.output_divisor == 1 ? "ns" : "us");
trace_seq_printf(s, "# Duration: %s\n", duration);
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -267,10 +267,10 @@ osnoise_print_summary(struct osnoise_params *params,
{
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -284,7 +284,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -299,7 +299,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -317,7 +317,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -352,7 +352,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
for (bucket = 0; bucket < data->entries; bucket++) {
total = 0;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "%-6d",
bucket * data->bucket_size);
@@ -367,7 +367,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].samples[bucket]);
}
- if (total == 0 && !params->with_zeros) {
+ if (total == 0 && !params->common.hist.with_zeros) {
trace_seq_reset(trace->seq);
continue;
}
@@ -391,7 +391,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
return;
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -490,9 +490,9 @@ static struct osnoise_params
exit(1);
/* display data in microseconds */
- params->output_divisor = 1000;
- params->bucket_size = 1;
- params->entries = 256;
+ params->common.output_divisor = 1000;
+ params->common.hist.bucket_size = 1;
+ params->common.hist.entries = 256;
while (1) {
static struct option long_options[] = {
@@ -547,8 +547,9 @@ static struct osnoise_params
break;
case 'b':
- params->bucket_size = get_llong_from_str(optarg);
- if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
+ params->common.hist.bucket_size = get_llong_from_str(optarg);
+ if (params->common.hist.bucket_size == 0 ||
+ params->common.hist.bucket_size >= 1000000)
osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'c':
@@ -588,8 +589,9 @@ static struct osnoise_params
params->common.events = tevent;
break;
case 'E':
- params->entries = get_llong_from_str(optarg);
- if ((params->entries < 10) || (params->entries > 9999999))
+ params->common.hist.entries = get_llong_from_str(optarg);
+ if (params->common.hist.entries < 10 ||
+ params->common.hist.entries > 9999999)
osnoise_hist_usage("Entries must be > 10 and < 9999999\n");
break;
case 'h':
@@ -641,16 +643,16 @@ static struct osnoise_params
params->trace_output = "osnoise_trace.txt";
break;
case '0': /* no header */
- params->no_header = 1;
+ params->common.hist.no_header = 1;
break;
case '1': /* no summary */
- params->no_summary = 1;
+ params->common.hist.no_summary = 1;
break;
case '2': /* no index */
- params->no_index = 1;
+ params->common.hist.no_index = 1;
break;
case '3': /* with zeros */
- params->with_zeros = 1;
+ params->common.hist.with_zeros = 1;
break;
case '4': /* trigger */
if (params->common.events) {
@@ -690,7 +692,7 @@ static struct osnoise_params
exit(EXIT_FAILURE);
}
- if (params->no_index && !params->with_zeros)
+ if (params->common.hist.no_index && !params->common.hist.with_zeros)
osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense");
return params;
@@ -729,7 +731,8 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = osnoise_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
+ tool->data = osnoise_alloc_histogram(nr_cpus, params->common.hist.entries,
+ params->common.hist.bucket_size);
if (!tool->data)
goto out_err;
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index ad5daa8210aa..7c68feed300e 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -125,11 +125,12 @@ static void osnoise_top_header(struct osnoise_tool *top)
{
struct osnoise_params *params = top->params;
struct trace_seq *s = top->trace.seq;
+ bool pretty = params->common.pretty_output;
char duration[26];
get_duration(top->start_time, duration, sizeof(duration));
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " ");
@@ -143,13 +144,13 @@ static void osnoise_top_header(struct osnoise_tool *top)
trace_seq_printf(s, " ");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
trace_seq_printf(s, "duration: %9s | time is in us\n", duration);
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU Period Runtime ");
@@ -164,7 +165,7 @@ static void osnoise_top_header(struct osnoise_tool *top)
trace_seq_printf(s, " IRQ Softirq Thread");
eol:
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
}
@@ -232,7 +233,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- if (!params->quiet)
+ if (!params->common.quiet)
clear_terminal(trace->seq);
osnoise_top_header(top);
@@ -446,7 +447,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->common.set_sched = 1;
break;
case 'q':
- params->quiet = 1;
+ params->common.quiet = 1;
break;
case 'r':
params->runtime = get_llong_from_str(optarg);
@@ -534,8 +535,8 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *param
}
}
- if (isatty(STDOUT_FILENO) && !params->quiet)
- params->pretty_output = 1;
+ if (isatty(STDOUT_FILENO) && !params->common.quiet)
+ params->common.pretty_output = 1;
return 0;
@@ -705,7 +706,7 @@ int osnoise_top_main(int argc, char **argv)
goto out_top;
}
- if (!params->quiet)
+ if (!params->common.quiet)
osnoise_print_stats(params, tool);
if (osnoise_trace_is_off(tool, record))
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index dd9e0f05bdad..212ee7971bab 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -23,7 +23,6 @@ struct timerlat_params {
struct common_params common;
long long timerlat_period_us;
long long print_stack;
- int output_divisor;
int dma_latency;
int no_aa;
int dump_tasks;
@@ -31,30 +30,11 @@ struct timerlat_params {
int kernel_workload;
int user_data;
int deepest_idle_state;
+ int aa_only;
enum timerlat_tracing_mode mode;
struct actions threshold_actions;
struct actions end_actions;
-
- union {
- struct {
- /* top only */
- int quiet;
- int aa_only;
- int pretty_output;
- };
- struct {
- /* hist only */
- char no_irq;
- char no_thread;
- char no_header;
- char no_summary;
- char no_index;
- char with_zeros;
- int bucket_size;
- int entries;
- };
- };
};
int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index a6c77ac55e00..03be2606f54a 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -21,20 +21,20 @@ int timerlat_bpf_init(struct timerlat_params *params)
return 1;
/* Pass common options */
- bpf->rodata->output_divisor = params->output_divisor;
- bpf->rodata->entries = params->entries;
+ bpf->rodata->output_divisor = params->common.output_divisor;
+ bpf->rodata->entries = params->common.hist.entries;
bpf->rodata->irq_threshold = params->common.stop_us;
bpf->rodata->thread_threshold = params->common.stop_total_us;
bpf->rodata->aa_only = params->aa_only;
- if (params->entries != 0) {
+ if (params->common.hist.entries != 0) {
/* Pass histogram options */
- bpf->rodata->bucket_size = params->bucket_size;
+ bpf->rodata->bucket_size = params->common.hist.bucket_size;
/* Set histogram array sizes */
- bpf_map__set_max_entries(bpf->maps.hist_irq, params->entries);
- bpf_map__set_max_entries(bpf->maps.hist_thread, params->entries);
- bpf_map__set_max_entries(bpf->maps.hist_user, params->entries);
+ bpf_map__set_max_entries(bpf->maps.hist_irq, params->common.hist.entries);
+ bpf_map__set_max_entries(bpf->maps.hist_thread, params->common.hist.entries);
+ bpf_map__set_max_entries(bpf->maps.hist_user, params->common.hist.entries);
} else {
/* No entries, disable histogram */
bpf_map__set_autocreate(bpf->maps.hist_irq, false);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index a3de644f2b75..4dc22a749885 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -141,8 +141,8 @@ timerlat_hist_update(struct osnoise_tool *tool, int cpu,
int bucket;
int *hist;
- if (params->output_divisor)
- latency = latency / params->output_divisor;
+ if (params->common.output_divisor)
+ latency = latency / params->common.output_divisor;
bucket = latency / data->bucket_size;
@@ -288,18 +288,18 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
char duration[26];
int cpu;
- if (params->no_header)
+ if (params->common.hist.no_header)
return;
get_duration(tool->start_time, duration, sizeof(duration));
trace_seq_printf(s, "# RTLA timerlat histogram\n");
trace_seq_printf(s, "# Time unit is %s (%s)\n",
- params->output_divisor == 1 ? "nanoseconds" : "microseconds",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "nanoseconds" : "microseconds",
+ params->common.output_divisor == 1 ? "ns" : "us");
trace_seq_printf(s, "# Duration: %s\n", duration);
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -309,10 +309,10 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(s, " IRQ-%03d", cpu);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(s, " Thr-%03d", cpu);
if (params->user_data)
@@ -350,10 +350,10 @@ timerlat_print_summary(struct timerlat_params *params,
{
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -363,11 +363,11 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].irq_count);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].thread_count);
@@ -377,7 +377,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -387,13 +387,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].min_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].min_thread,
@@ -407,7 +407,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -417,13 +417,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].sum_irq,
true);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].sum_thread,
@@ -437,7 +437,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -447,13 +447,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].max_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].max_thread,
@@ -479,7 +479,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
struct timerlat_hist_cpu sum;
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
memset(&sum, 0, sizeof(sum));
@@ -512,13 +512,13 @@ timerlat_print_stats_all(struct timerlat_params *params,
update_max(&sum.max_user, &cpu_data->max_user);
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "ALL: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, " IRQ");
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, " Thr");
if (params->user_data)
@@ -526,14 +526,14 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9llu ",
sum.irq_count);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9llu ",
sum.thread_count);
@@ -543,16 +543,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.min_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.min_thread,
@@ -566,16 +566,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.sum_irq,
true);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.sum_thread,
@@ -589,16 +589,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.max_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.max_thread,
@@ -631,7 +631,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
for (bucket = 0; bucket < data->entries; bucket++) {
total = 0;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "%-6d",
bucket * data->bucket_size);
@@ -642,13 +642,13 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq) {
+ if (!params->common.hist.no_irq) {
total += data->hist[cpu].irq[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].irq[bucket]);
}
- if (!params->no_thread) {
+ if (!params->common.hist.no_thread) {
total += data->hist[cpu].thread[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[bucket]);
@@ -662,7 +662,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
}
- if (total == 0 && !params->with_zeros) {
+ if (total == 0 && !params->common.hist.with_zeros) {
trace_seq_reset(trace->seq);
continue;
}
@@ -672,7 +672,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_reset(trace->seq);
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -682,11 +682,11 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].irq[data->entries]);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[data->entries]);
@@ -804,9 +804,9 @@ static struct timerlat_params
params->deepest_idle_state = -2;
/* display data in microseconds */
- params->output_divisor = 1000;
- params->bucket_size = 1;
- params->entries = 256;
+ params->common.output_divisor = 1000;
+ params->common.hist.bucket_size = 1;
+ params->common.hist.entries = 256;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
@@ -894,8 +894,9 @@ static struct timerlat_params
}
break;
case 'b':
- params->bucket_size = get_llong_from_str(optarg);
- if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
+ params->common.hist.bucket_size = get_llong_from_str(optarg);
+ if (params->common.hist.bucket_size == 0 ||
+ params->common.hist.bucket_size >= 1000000)
timerlat_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'D':
@@ -919,9 +920,10 @@ static struct timerlat_params
params->common.events = tevent;
break;
case 'E':
- params->entries = get_llong_from_str(optarg);
- if ((params->entries < 10) || (params->entries > 9999999))
- timerlat_hist_usage("Entries must be > 10 and < 9999999\n");
+ params->common.hist.entries = get_llong_from_str(optarg);
+ if (params->common.hist.entries < 10 ||
+ params->common.hist.entries > 9999999)
+ timerlat_hist_usage("Entries must be > 10 and < 9999999\n");
break;
case 'h':
case '?':
@@ -942,7 +944,7 @@ static struct timerlat_params
params->kernel_workload = 1;
break;
case 'n':
- params->output_divisor = 1;
+ params->common.output_divisor = 1;
break;
case 'p':
params->timerlat_period_us = get_llong_from_str(optarg);
@@ -979,22 +981,22 @@ static struct timerlat_params
params->user_data = 1;
break;
case '0': /* no irq */
- params->no_irq = 1;
+ params->common.hist.no_irq = 1;
break;
case '1': /* no thread */
- params->no_thread = 1;
+ params->common.hist.no_thread = 1;
break;
case '2': /* no header */
- params->no_header = 1;
+ params->common.hist.no_header = 1;
break;
case '3': /* no summary */
- params->no_summary = 1;
+ params->common.hist.no_summary = 1;
break;
case '4': /* no index */
- params->no_index = 1;
+ params->common.hist.no_index = 1;
break;
case '5': /* with zeros */
- params->with_zeros = 1;
+ params->common.hist.with_zeros = 1;
break;
case '6': /* trigger */
if (params->common.events) {
@@ -1067,10 +1069,10 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->no_irq && params->no_thread)
+ if (params->common.hist.no_irq && params->common.hist.no_thread)
timerlat_hist_usage("no-irq and no-thread set, there is nothing to do here");
- if (params->no_index && !params->with_zeros)
+ if (params->common.hist.no_index && !params->common.hist.with_zeros)
timerlat_hist_usage("no-index set with with-zeros is not set - it does not make sense");
/*
@@ -1127,7 +1129,8 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = timerlat_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
+ tool->data = timerlat_alloc_histogram(nr_cpus, params->common.hist.entries,
+ params->common.hist.bucket_size);
if (!tool->data)
goto out_err;
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 9fb60f4dd092..72be083d7d71 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -132,8 +132,8 @@ timerlat_top_update(struct osnoise_tool *tool, int cpu,
struct timerlat_top_data *data = tool->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
- if (params->output_divisor)
- latency = latency / params->output_divisor;
+ if (params->common.output_divisor)
+ latency = latency / params->common.output_divisor;
if (!thread) {
cpu_data->irq_count++;
@@ -258,39 +258,40 @@ static int timerlat_top_bpf_pull_data(struct osnoise_tool *tool)
static void timerlat_top_header(struct timerlat_params *params, struct osnoise_tool *top)
{
struct trace_seq *s = top->trace.seq;
+ bool pretty = params->common.pretty_output;
char duration[26];
get_duration(top->start_time, duration, sizeof(duration));
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " Timer Latency ");
if (params->user_data)
trace_seq_printf(s, " ");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
trace_seq_printf(s, "%-6s | IRQ Timer Latency (%s) | Thread Timer Latency (%s)", duration,
- params->output_divisor == 1 ? "ns" : "us",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "ns" : "us",
+ params->common.output_divisor == 1 ? "ns" : "us");
if (params->user_data) {
trace_seq_printf(s, " | Ret user Timer Latency (%s)",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "ns" : "us");
}
trace_seq_printf(s, "\n");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU COUNT | cur min avg max | cur min avg max");
if (params->user_data)
trace_seq_printf(s, " | cur min avg max");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
}
@@ -449,7 +450,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- if (!params->quiet)
+ if (!params->common.quiet)
clear_terminal(trace->seq);
timerlat_top_reset_sum(&summary);
@@ -563,7 +564,7 @@ static struct timerlat_params
params->deepest_idle_state = -2;
/* display data in microseconds */
- params->output_divisor = 1000;
+ params->common.output_divisor = 1000;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
@@ -696,7 +697,7 @@ static struct timerlat_params
params->kernel_workload = true;
break;
case 'n':
- params->output_divisor = 1;
+ params->common.output_divisor = 1;
break;
case 'p':
params->timerlat_period_us = get_llong_from_str(optarg);
@@ -710,7 +711,7 @@ static struct timerlat_params
params->common.set_sched = 1;
break;
case 'q':
- params->quiet = 1;
+ params->common.quiet = 1;
break;
case 's':
params->print_stack = get_llong_from_str(optarg);
@@ -842,8 +843,8 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *para
if (retval)
goto out_err;
- if (isatty(STDOUT_FILENO) && !params->quiet)
- params->pretty_output = 1;
+ if (isatty(STDOUT_FILENO) && !params->common.quiet)
+ params->common.pretty_output = 1;
return 0;
@@ -942,7 +943,7 @@ timerlat_top_main_loop(struct osnoise_tool *top,
return retval;
}
- if (!params->quiet)
+ if (!params->common.quiet)
timerlat_print_stats(params, top);
if (osnoise_trace_is_off(top, record)) {
@@ -992,7 +993,8 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
/* Pull and display data in a loop */
while (!stop_tracing) {
- wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->common.sleep_time);
+ wait_retval = timerlat_bpf_wait(params->common.quiet ? -1 :
+ params->common.sleep_time);
retval = timerlat_top_bpf_pull_data(top);
if (retval) {
@@ -1000,7 +1002,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
return retval;
}
- if (!params->quiet)
+ if (!params->common.quiet)
timerlat_print_stats(params, top);
if (wait_retval == 1) {
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 3/7] tools/rtla: Create common_apply_config()
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-08-21 3:57 ` [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
2025-08-21 3:57 ` [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-27 11:33 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
` (3 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Merge the common bits of osnoise_apply_config() and
timerlat_apply_config(). Put the result in a new common.c, and move
enough things to common.h so that common.c does not need to include
osnoise.h.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
At some point it would be nice to have all of the common code named and
located correctly, but it's a start. Do we want to stick with "common" or
go with something less vague like "osn" for things that relate to the
broader osnoise mechanism rather than the specific osnoise tracer?
---
tools/tracing/rtla/src/Build | 1 +
tools/tracing/rtla/src/common.c | 64 ++++++++++++++++++++++++
tools/tracing/rtla/src/common.h | 67 ++++++++++++++++++++++++++
tools/tracing/rtla/src/osnoise.c | 37 ++------------
tools/tracing/rtla/src/osnoise.h | 64 ------------------------
tools/tracing/rtla/src/timerlat.c | 51 ++------------------
tools/tracing/rtla/src/timerlat.h | 1 -
tools/tracing/rtla/src/timerlat_hist.c | 4 +-
tools/tracing/rtla/src/timerlat_top.c | 4 +-
9 files changed, 143 insertions(+), 150 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.c
diff --git a/tools/tracing/rtla/src/Build b/tools/tracing/rtla/src/Build
index 66631280b75b..329e24a40cf7 100644
--- a/tools/tracing/rtla/src/Build
+++ b/tools/tracing/rtla/src/Build
@@ -1,6 +1,7 @@
rtla-y += trace.o
rtla-y += utils.o
rtla-y += actions.o
+rtla-y += common.o
rtla-y += osnoise.o
rtla-y += osnoise_top.o
rtla-y += osnoise_hist.o
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
new file mode 100644
index 000000000000..c3834c760182
--- /dev/null
+++ b/tools/tracing/rtla/src/common.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include "common.h"
+
+/*
+ * common_apply_config - apply common configs to the initialized tool
+ */
+int
+common_apply_config(struct osnoise_tool *tool, struct common_params *params)
+{
+ int retval, i;
+
+ if (!params->sleep_time)
+ params->sleep_time = 1;
+
+ retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ if (retval) {
+ err_msg("Failed to apply CPUs config\n");
+ goto out_err;
+ }
+
+ if (!params->cpus) {
+ for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
+ CPU_SET(i, ¶ms->monitored_cpus);
+ }
+
+ if (params->hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
+ ¶ms->hk_cpu_set);
+ if (retval == -1) {
+ err_msg("Failed to set rtla to the house keeping CPUs\n");
+ goto out_err;
+ }
+ } else if (params->cpus) {
+ /*
+ * Even if the user do not set a house-keeping CPU, try to
+ * move rtla to a CPU set different to the one where the user
+ * set the workload to run.
+ *
+ * No need to check results as this is an automatic attempt.
+ */
+ auto_house_keeping(¶ms->monitored_cpus);
+ }
+
+ /*
+ * Set workload according to type of thread if the kernel supports it.
+ * On kernels without support, user threads will have already failed
+ * on missing fd, and kernel threads do not need it.
+ */
+ retval = osnoise_set_workload(tool->context, params->kernel_workload);
+ if (retval < -1) {
+ err_msg("Failed to set OSNOISE_WORKLOAD option\n");
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ return -1;
+}
+
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 276dfbc7f955..c306ba502688 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -1,8 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
#pragma once
+#include "trace.h"
#include "utils.h"
+/*
+ * osnoise_context - read, store, write, restore osnoise configs.
+ */
+struct osnoise_context {
+ int flags;
+ int ref;
+
+ char *curr_cpus;
+ char *orig_cpus;
+
+ /* 0 as init value */
+ unsigned long long orig_runtime_us;
+ unsigned long long runtime_us;
+
+ /* 0 as init value */
+ unsigned long long orig_period_us;
+ unsigned long long period_us;
+
+ /* 0 as init value */
+ long long orig_timerlat_period_us;
+ long long timerlat_period_us;
+
+ /* 0 as init value */
+ long long orig_tracing_thresh;
+ long long tracing_thresh;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_stop_us;
+ long long stop_us;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_stop_total_us;
+ long long stop_total_us;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_print_stack;
+ long long print_stack;
+
+ /* -1 as init value because 0 is off */
+ int orig_opt_irq_disable;
+ int opt_irq_disable;
+
+ /* -1 as init value because 0 is off */
+ int orig_opt_workload;
+ int opt_workload;
+};
+
+/*
+ * osnoise_tool - osnoise based tool definition.
+ */
+struct osnoise_tool {
+ struct trace_instance trace;
+ struct osnoise_context *context;
+ void *data;
+ void *params;
+ time_t start_time;
+};
+
struct hist_params {
char no_irq;
char no_thread;
@@ -44,4 +103,12 @@ struct common_params {
int output_divisor;
int pretty_output;
int quiet;
+ int kernel_workload;
};
+
+int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
+void osnoise_restore_cpus(struct osnoise_context *context);
+
+int osnoise_set_workload(struct osnoise_context *context, bool onoff);
+
+int common_apply_config(struct osnoise_tool *tool, struct common_params *params);
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 06ae7437c2c7..4051b21db69a 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -1120,21 +1120,14 @@ osnoise_report_missed_events(struct osnoise_tool *tool)
}
/*
- * osnoise_apply_config - apply common configs to the initialized tool
+ * osnoise_apply_config - apply osnoise configs to the initialized tool
*/
int
osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
{
int retval;
- if (!params->common.sleep_time)
- params->common.sleep_time = 1;
-
- retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
- if (retval) {
- err_msg("Failed to apply CPUs config\n");
- goto out_err;
- }
+ params->common.kernel_workload = true;
if (params->runtime || params->period) {
retval = osnoise_set_runtime_period(tool->context,
@@ -1169,31 +1162,7 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- if (params->common.hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
- ¶ms->common.hk_cpu_set);
- if (retval == -1) {
- err_msg("Failed to set rtla to the house keeping CPUs\n");
- goto out_err;
- }
- } else if (params->common.cpus) {
- /*
- * Even if the user do not set a house-keeping CPU, try to
- * move rtla to a CPU set different to the one where the user
- * set the workload to run.
- *
- * No need to check results as this is an automatic attempt.
- */
- auto_house_keeping(¶ms->common.monitored_cpus);
- }
-
- retval = osnoise_set_workload(tool->context, true);
- if (retval < -1) {
- err_msg("Failed to set OSNOISE_WORKLOAD option\n");
- goto out_err;
- }
-
- return 0;
+ return common_apply_config(tool, ¶ms->common);
out_err:
return -1;
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index b64b39de97b5..25baf46a2520 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -2,7 +2,6 @@
#pragma once
#include "common.h"
-#include "trace.h"
enum osnoise_mode {
MODE_OSNOISE = 0,
@@ -18,53 +17,6 @@ struct osnoise_params {
enum osnoise_mode mode;
};
-/*
- * osnoise_context - read, store, write, restore osnoise configs.
- */
-struct osnoise_context {
- int flags;
- int ref;
-
- char *curr_cpus;
- char *orig_cpus;
-
- /* 0 as init value */
- unsigned long long orig_runtime_us;
- unsigned long long runtime_us;
-
- /* 0 as init value */
- unsigned long long orig_period_us;
- unsigned long long period_us;
-
- /* 0 as init value */
- long long orig_timerlat_period_us;
- long long timerlat_period_us;
-
- /* 0 as init value */
- long long orig_tracing_thresh;
- long long tracing_thresh;
-
- /* -1 as init value because 0 is disabled */
- long long orig_stop_us;
- long long stop_us;
-
- /* -1 as init value because 0 is disabled */
- long long orig_stop_total_us;
- long long stop_total_us;
-
- /* -1 as init value because 0 is disabled */
- long long orig_print_stack;
- long long print_stack;
-
- /* -1 as init value because 0 is off */
- int orig_opt_irq_disable;
- int opt_irq_disable;
-
- /* -1 as init value because 0 is off */
- int orig_opt_workload;
- int opt_workload;
-};
-
/*
* *_INIT_VALs are also invalid values, they are used to
* communicate errors.
@@ -76,9 +28,6 @@ struct osnoise_context *osnoise_context_alloc(void);
int osnoise_get_context(struct osnoise_context *context);
void osnoise_put_context(struct osnoise_context *context);
-int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
-void osnoise_restore_cpus(struct osnoise_context *context);
-
int osnoise_set_runtime_period(struct osnoise_context *context,
unsigned long long runtime,
unsigned long long period);
@@ -105,19 +54,6 @@ int osnoise_set_print_stack(struct osnoise_context *context,
long long print_stack);
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
-int osnoise_set_workload(struct osnoise_context *context, bool onoff);
-
-/*
- * osnoise_tool - osnoise based tool definition.
- */
-struct osnoise_tool {
- struct trace_instance trace;
- struct osnoise_context *context;
- void *data;
- void *params;
- time_t start_time;
-};
-
void osnoise_destroy_tool(struct osnoise_tool *top);
struct osnoise_tool *osnoise_init_tool(char *tool_name);
struct osnoise_tool *osnoise_init_trace_tool(char *tracer);
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 0b2f03e1e612..e4bf58db1dd2 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -24,21 +24,7 @@
int
timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
- int retval, i;
-
- if (!params->common.sleep_time)
- params->common.sleep_time = 1;
-
- retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
- if (retval) {
- err_msg("Failed to apply CPUs config\n");
- goto out_err;
- }
-
- if (!params->common.cpus) {
- for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
- CPU_SET(i, ¶ms->common.monitored_cpus);
- }
+ int retval;
if (params->mode != TRACING_MODE_BPF) {
/*
@@ -75,29 +61,11 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
goto out_err;
}
- if (params->common.hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
- ¶ms->common.hk_cpu_set);
- if (retval == -1) {
- err_msg("Failed to set rtla to the house keeping CPUs\n");
- goto out_err;
- }
- } else if (params->common.cpus) {
- /*
- * Even if the user do not set a house-keeping CPU, try to
- * move rtla to a CPU set different to the one where the user
- * set the workload to run.
- *
- * No need to check results as this is an automatic attempt.
- */
- auto_house_keeping(¶ms->common.monitored_cpus);
- }
-
/*
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
- if (!params->kernel_workload && !params->user_data) {
+ if (!params->common.kernel_workload && !params->user_data) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
@@ -105,22 +73,11 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
params->user_data = 1;
} else {
debug_msg("User-space interface not detected, setting kernel-threads\n");
- params->kernel_workload = 1;
+ params->common.kernel_workload = 1;
}
}
- /*
- * Set workload according to type of thread if the kernel supports it.
- * On kernels without support, user threads will have already failed
- * on missing timerlat_fd, and kernel threads do not need it.
- */
- retval = osnoise_set_workload(tool->context, params->kernel_workload);
- if (retval < -1) {
- err_msg("Failed to set OSNOISE_WORKLOAD option\n");
- goto out_err;
- }
-
- return 0;
+ return common_apply_config(tool, ¶ms->common);
out_err:
return -1;
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index 212ee7971bab..86cd9bac8855 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -27,7 +27,6 @@ struct timerlat_params {
int no_aa;
int dump_tasks;
int user_workload;
- int kernel_workload;
int user_data;
int deepest_idle_state;
int aa_only;
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 4dc22a749885..d339e2cffae2 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -941,7 +941,7 @@ static struct timerlat_params
params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
- params->kernel_workload = 1;
+ params->common.kernel_workload = 1;
break;
case 'n':
params->common.output_divisor = 1;
@@ -1081,7 +1081,7 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->user_workload)
timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 72be083d7d71..bb42697d2575 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -694,7 +694,7 @@ static struct timerlat_params
params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
- params->kernel_workload = true;
+ params->common.kernel_workload = true;
break;
case 'n':
params->common.output_divisor = 1;
@@ -816,7 +816,7 @@ static struct timerlat_params
if (params->no_aa && params->aa_only)
timerlat_top_usage("--no-aa and --aa-only are mutually exclusive!");
- if (params->kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->user_workload)
timerlat_top_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (2 preceding siblings ...)
2025-08-21 3:57 ` [PATCH 3/7] tools/rtla: Create common_apply_config() Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-27 13:34 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
` (2 subsequent siblings)
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Currently a lot of code is duplicated between the different rtla tools,
making maintenance more difficult, and encouraging divergence such as
features that are only implemented for certain tools even though they
could be more broadly applicable.
Merge the various main() functions into a common run_tool() with an ops
struct for tool-specific details.
Implement enough support for actions on osnoise to not need to keep the
old params->trace_output path.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
I've reworked this from my original plan in order to avoid a "god object
anti-pattern" with the params struct, as requested by Costa. In this
case I'm not 100% convinced that the separation is worth the hassle and
all the "params->common.xxx" and the churn as a field or some code goes
from tool-specific to common, but I can see some advantages.
Some bits like aa_only and the user stuff are in common even though they
are only used by timerlat. In the case of user stuff I plan to submit
patches for supporting that on osnoise, and it doesn't seem worthwhile to
jump through hoops to move some of that code out of code that is otherwise
able to be shared. For aa_only, making it non-common would have precluded
sharing some code, and the code that the flag inhibits isn't tool-specific
(unlike no_aa). Plus, there's other common code referring to tool->aa.
---
tools/tracing/rtla/src/common.c | 281 +++++++++++++++
tools/tracing/rtla/src/common.h | 60 +++-
tools/tracing/rtla/src/osnoise.c | 66 ++--
tools/tracing/rtla/src/osnoise.h | 14 +-
tools/tracing/rtla/src/osnoise_hist.c | 234 +++---------
tools/tracing/rtla/src/osnoise_top.c | 218 ++----------
tools/tracing/rtla/src/timerlat.c | 167 ++++++++-
tools/tracing/rtla/src/timerlat.h | 16 +-
tools/tracing/rtla/src/timerlat_bpf.c | 4 +-
tools/tracing/rtla/src/timerlat_hist.c | 450 +++++------------------
tools/tracing/rtla/src/timerlat_top.c | 473 ++++---------------------
tools/tracing/rtla/src/trace.h | 3 -
tools/tracing/rtla/tests/hwnoise.t | 2 +-
tools/tracing/rtla/tests/osnoise.t | 2 +-
14 files changed, 794 insertions(+), 1196 deletions(-)
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index c3834c760182..c6e446425cd2 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -2,9 +2,42 @@
#define _GNU_SOURCE
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
#include <unistd.h>
#include "common.h"
+struct trace_instance *trace_inst;
+int stop_tracing;
+
+static void stop_trace(int sig)
+{
+ if (stop_tracing) {
+ /*
+ * Stop requested twice in a row; abort event processing and
+ * exit immediately
+ */
+ tracefs_iterate_stop(trace_inst->inst);
+ return;
+ }
+ stop_tracing = 1;
+ if (trace_inst)
+ trace_instance_stop(trace_inst);
+}
+
+/*
+ * set_signals - handles the signal to stop the tool
+ */
+static void set_signals(struct common_params *params)
+{
+ signal(SIGINT, stop_trace);
+ if (params->duration) {
+ signal(SIGALRM, stop_trace);
+ alarm(params->duration);
+ }
+}
+
/*
* common_apply_config - apply common configs to the initialized tool
*/
@@ -62,3 +95,251 @@ common_apply_config(struct osnoise_tool *tool, struct common_params *params)
return -1;
}
+
+int run_tool(struct tool_ops *ops, int argc, char *argv[])
+{
+ struct common_params *params;
+ enum result return_value = ERROR;
+ struct osnoise_tool *tool;
+ bool stopped;
+ int retval;
+
+ params = ops->parse_args(argc, argv);
+ if (!params)
+ exit(1);
+
+ tool = ops->init_tool(params);
+ if (!tool) {
+ err_msg("Could not init osnoise tool\n");
+ goto out_exit;
+ }
+ tool->ops = ops;
+ tool->params = params;
+
+ /*
+ * Save trace instance into global variable so that SIGINT can stop
+ * the timerlat tracer.
+ * Otherwise, rtla could loop indefinitely when overloaded.
+ */
+ trace_inst = &tool->trace;
+
+ retval = ops->apply_config(tool);
+ if (retval) {
+ err_msg("Could not apply config\n");
+ goto out_free;
+ }
+
+ retval = enable_tracer_by_name(trace_inst->inst, ops->tracer);
+ if (retval) {
+ err_msg("Failed to enable %s tracer\n", ops->tracer);
+ goto out_free;
+ }
+
+ if (params->set_sched) {
+ retval = set_comm_sched_attr(ops->comm_prefix, ¶ms->sched_param);
+ if (retval) {
+ err_msg("Failed to set sched parameters\n");
+ goto out_free;
+ }
+ }
+
+ if (params->cgroup && !params->user_data) {
+ retval = set_comm_cgroup(ops->comm_prefix, params->cgroup_name);
+ if (!retval) {
+ err_msg("Failed to move threads to cgroup\n");
+ goto out_free;
+ }
+ }
+
+
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT]) {
+ tool->record = osnoise_init_trace_tool(ops->tracer);
+ if (!tool->record) {
+ err_msg("Failed to enable the trace instance\n");
+ goto out_free;
+ }
+ params->threshold_actions.trace_output_inst = tool->record->trace.inst;
+ params->end_actions.trace_output_inst = tool->record->trace.inst;
+
+ if (params->events) {
+ retval = trace_events_enable(&tool->record->trace, params->events);
+ if (retval)
+ goto out_trace;
+ }
+
+ if (params->buffer_size > 0) {
+ retval = trace_set_buffer_size(&tool->record->trace, params->buffer_size);
+ if (retval)
+ goto out_trace;
+ }
+ }
+
+ if (params->user_workload) {
+ pthread_t user_thread;
+
+ /* rtla asked to stop */
+ params->user.should_run = 1;
+ /* all threads left */
+ params->user.stopped_running = 0;
+
+ params->user.set = ¶ms->monitored_cpus;
+ if (params->set_sched)
+ params->user.sched_param = ¶ms->sched_param;
+ else
+ params->user.sched_param = NULL;
+
+ params->user.cgroup_name = params->cgroup_name;
+
+ retval = pthread_create(&user_thread, NULL, timerlat_u_dispatcher, ¶ms->user);
+ if (retval)
+ err_msg("Error creating timerlat user-space threads\n");
+ }
+
+ retval = ops->enable(tool);
+ if (retval)
+ goto out_trace;
+
+ tool->start_time = time(NULL);
+ set_signals(params);
+
+ retval = ops->main(tool);
+ if (retval)
+ goto out_trace;
+
+ if (params->user_workload && !params->user.stopped_running) {
+ params->user.should_run = 0;
+ sleep(1);
+ }
+
+ ops->print_stats(tool);
+
+ actions_perform(¶ms->end_actions);
+
+ return_value = PASSED;
+
+ stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing;
+ if (stopped) {
+ printf("rtla hit stop tracing\n");
+ return_value = FAILED;
+ }
+
+ if (ops->analyze)
+ ops->analyze(tool, stopped);
+
+out_trace:
+ trace_events_destroy(&tool->record->trace, params->events);
+ params->events = NULL;
+out_free:
+ ops->free(tool);
+ osnoise_destroy_tool(tool->record);
+ osnoise_destroy_tool(tool);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
+ free(params);
+out_exit:
+ exit(return_value);
+}
+
+int top_main_loop(struct osnoise_tool *tool)
+{
+ struct common_params *params = tool->params;
+ struct trace_instance *trace = &tool->trace;
+ struct osnoise_tool *record = tool->record;
+ int retval;
+
+ while (!stop_tracing) {
+ sleep(params->sleep_time);
+
+ if (params->aa_only && !osnoise_trace_is_off(tool, record))
+ continue;
+
+ retval = tracefs_iterate_raw_events(trace->tep,
+ trace->inst,
+ NULL,
+ 0,
+ collect_registered_events,
+ trace);
+ if (retval < 0) {
+ err_msg("Error iterating on events\n");
+ return retval;
+ }
+
+ if (!params->quiet)
+ tool->ops->print_stats(tool);
+
+ if (osnoise_trace_is_off(tool, record)) {
+ actions_perform(¶ms->threshold_actions);
+
+ if (!params->threshold_actions.continue_flag)
+ /* continue flag not set, break */
+ return 0;
+
+ /* continue action reached, re-enable tracing */
+ if (record)
+ trace_instance_start(&record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ trace_instance_start(trace);
+ }
+
+ /* is there still any user-threads ? */
+ if (params->user_workload) {
+ if (params->user.stopped_running) {
+ debug_msg("timerlat user space threads stopped!\n");
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int hist_main_loop(struct osnoise_tool *tool)
+{
+ struct common_params *params = tool->params;
+ struct trace_instance *trace = &tool->trace;
+ int retval = 0;
+
+ while (!stop_tracing) {
+ sleep(params->sleep_time);
+
+ retval = tracefs_iterate_raw_events(trace->tep,
+ trace->inst,
+ NULL,
+ 0,
+ collect_registered_events,
+ trace);
+ if (retval < 0) {
+ err_msg("Error iterating on events\n");
+ break;
+ }
+
+ if (osnoise_trace_is_off(tool, tool->record)) {
+ actions_perform(¶ms->threshold_actions);
+
+ if (!params->threshold_actions.continue_flag) {
+ /* continue flag not set, break */
+ break;
+
+ /* continue action reached, re-enable tracing */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ trace_instance_start(&tool->trace);
+ }
+ break;
+ }
+
+ /* is there still any user-threads ? */
+ if (params->user_workload) {
+ if (params->user.stopped_running) {
+ debug_msg("user-space threads stopped!\n");
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index c306ba502688..355f113a14a3 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#pragma once
+#include "actions.h"
+#include "timerlat_u.h"
#include "trace.h"
#include "utils.h"
@@ -51,16 +53,8 @@ struct osnoise_context {
int opt_workload;
};
-/*
- * osnoise_tool - osnoise based tool definition.
- */
-struct osnoise_tool {
- struct trace_instance trace;
- struct osnoise_context *context;
- void *data;
- void *params;
- time_t start_time;
-};
+extern struct trace_instance *trace_inst;
+extern int stop_tracing;
struct hist_params {
char no_irq;
@@ -103,7 +97,46 @@ struct common_params {
int output_divisor;
int pretty_output;
int quiet;
+ int user_workload;
int kernel_workload;
+ int user_data;
+ int aa_only;
+
+ struct actions threshold_actions;
+ struct actions end_actions;
+ struct timerlat_u_params user;
+};
+
+struct tool_ops;
+
+/*
+ * osnoise_tool - osnoise based tool definition.
+ *
+ * Only the "trace" and "context" fields are used for
+ * the additional trace instances (record and aa).
+ */
+struct osnoise_tool {
+ struct tool_ops *ops;
+ struct trace_instance trace;
+ struct osnoise_context *context;
+ void *data;
+ struct common_params *params;
+ time_t start_time;
+ struct osnoise_tool *record;
+ struct osnoise_tool *aa;
+};
+
+struct tool_ops {
+ const char *tracer;
+ const char *comm_prefix;
+ struct common_params *(*parse_args)(int argc, char *argv[]);
+ struct osnoise_tool *(*init_tool)(struct common_params *params);
+ int (*apply_config)(struct osnoise_tool *tool);
+ int (*enable)(struct osnoise_tool *tool);
+ int (*main)(struct osnoise_tool *tool);
+ void (*print_stats)(struct osnoise_tool *tool);
+ void (*analyze)(struct osnoise_tool *tool, bool stopped);
+ void (*free)(struct osnoise_tool *tool);
};
int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
@@ -111,4 +144,11 @@ void osnoise_restore_cpus(struct osnoise_context *context);
int osnoise_set_workload(struct osnoise_context *context, bool onoff);
+void osnoise_destroy_tool(struct osnoise_tool *top);
+struct osnoise_tool *osnoise_init_tool(char *tool_name);
+struct osnoise_tool *osnoise_init_trace_tool(const char *tracer);
+bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
+
int common_apply_config(struct osnoise_tool *tool, struct common_params *params);
+int top_main_loop(struct osnoise_tool *tool);
+int hist_main_loop(struct osnoise_tool *tool);
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 4051b21db69a..312c511fa004 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -906,22 +906,6 @@ static void osnoise_put_workload(struct osnoise_context *context)
context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL;
}
-/*
- * enable_osnoise - enable osnoise tracer in the trace_instance
- */
-int enable_osnoise(struct trace_instance *trace)
-{
- return enable_tracer_by_name(trace->inst, "osnoise");
-}
-
-/*
- * enable_timerlat - enable timerlat tracer in the trace_instance
- */
-int enable_timerlat(struct trace_instance *trace)
-{
- return enable_tracer_by_name(trace->inst, "timerlat");
-}
-
enum {
FLAG_CONTEXT_NEWLY_CREATED = (1 << 0),
FLAG_CONTEXT_DELETED = (1 << 1),
@@ -1056,7 +1040,7 @@ struct osnoise_tool *osnoise_init_tool(char *tool_name)
/*
* osnoise_init_trace_tool - init a tracer instance to trace osnoise events
*/
-struct osnoise_tool *osnoise_init_trace_tool(char *tracer)
+struct osnoise_tool *osnoise_init_trace_tool(const char *tracer)
{
struct osnoise_tool *trace;
int retval;
@@ -1168,6 +1152,44 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
return -1;
}
+int osnoise_enable(struct osnoise_tool *tool)
+{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
+ int retval;
+
+ /*
+ * Start the tracer here, after having set all instances.
+ *
+ * Let the trace instance start first for the case of hitting a stop
+ * tracing while enabling other instances. The trace instance is the
+ * one with most valuable information.
+ */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ trace_instance_start(&tool->trace);
+
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
+ if (stop_tracing)
+ return -1;
+
+ /*
+ * Clean up the buffer. The osnoise workload do not run
+ * with tracing off to avoid creating a performance penalty
+ * when not needed.
+ */
+ retval = tracefs_instance_file_write(tool->trace.inst, "trace", "");
+ if (retval < 0) {
+ debug_msg("Error cleaning up the buffer");
+ return retval;
+ }
+
+ }
+
+ return 0;
+}
+
static void osnoise_usage(int err)
{
int i;
@@ -1201,7 +1223,7 @@ int osnoise_main(int argc, char *argv[])
* default cmdline.
*/
if (argc == 1) {
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
}
@@ -1209,13 +1231,13 @@ int osnoise_main(int argc, char *argv[])
osnoise_usage(0);
} else if (strncmp(argv[1], "-", 1) == 0) {
/* the user skipped the tool, call the default one */
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
} else if (strcmp(argv[1], "top") == 0) {
- osnoise_top_main(argc-1, &argv[1]);
+ run_tool(&osnoise_top_ops, argc-1, &argv[1]);
exit(0);
} else if (strcmp(argv[1], "hist") == 0) {
- osnoise_hist_main(argc-1, &argv[1]);
+ run_tool(&osnoise_hist_ops, argc-1, &argv[1]);
exit(0);
}
@@ -1226,6 +1248,6 @@ int osnoise_main(int argc, char *argv[])
int hwnoise_main(int argc, char *argv[])
{
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
}
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index 25baf46a2520..895687030c0b 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -10,13 +10,14 @@ enum osnoise_mode {
struct osnoise_params {
struct common_params common;
- char *trace_output;
unsigned long long runtime;
unsigned long long period;
long long threshold;
enum osnoise_mode mode;
};
+#define to_osnoise_params(ptr) container_of(ptr, struct osnoise_params, common)
+
/*
* *_INIT_VALs are also invalid values, they are used to
* communicate errors.
@@ -54,14 +55,17 @@ int osnoise_set_print_stack(struct osnoise_context *context,
long long print_stack);
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
-void osnoise_destroy_tool(struct osnoise_tool *top);
-struct osnoise_tool *osnoise_init_tool(char *tool_name);
-struct osnoise_tool *osnoise_init_trace_tool(char *tracer);
void osnoise_report_missed_events(struct osnoise_tool *tool);
-bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params);
int osnoise_hist_main(int argc, char *argv[]);
int osnoise_top_main(int argc, char **argv);
+int osnoise_enable(struct osnoise_tool *tool);
int osnoise_main(int argc, char **argv);
int hwnoise_main(int argc, char **argv);
+
+extern struct tool_ops timerlat_top_ops, timerlat_hist_ops;
+extern struct tool_ops osnoise_top_ops, osnoise_hist_ops;
+
+int run_tool(struct tool_ops *ops, int argc, char *argv[]);
+int hist_main_loop(struct osnoise_tool *tool);
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index a31ab9b4ab21..2c2cdd467a67 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -54,6 +54,11 @@ osnoise_free_histogram(struct osnoise_hist_data *data)
free(data);
}
+static void osnoise_free_hist_tool(struct osnoise_tool *tool)
+{
+ osnoise_free_histogram(tool->data);
+}
+
/*
* osnoise_alloc_histogram - alloc runtime data
*/
@@ -95,7 +100,7 @@ static struct osnoise_hist_data
static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
unsigned long long duration, int count)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
unsigned long long total_duration;
int entries = data->entries;
@@ -137,7 +142,7 @@ static void osnoise_destroy_trace_hist(struct osnoise_tool *tool)
*/
static int osnoise_init_trace_hist(struct osnoise_tool *tool)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
int bucket_size;
char buff[128];
@@ -222,7 +227,7 @@ static void osnoise_read_trace_hist(struct osnoise_tool *tool)
*/
static void osnoise_hist_header(struct osnoise_tool *tool)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
struct trace_seq *s = tool->trace.seq;
char duration[26];
@@ -339,8 +344,9 @@ osnoise_print_summary(struct osnoise_params *params,
* osnoise_print_stats - print data for all CPUs
*/
static void
-osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
+osnoise_print_stats(struct osnoise_tool *tool)
{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
struct trace_instance *trace = &tool->trace;
int has_samples = 0;
@@ -477,18 +483,22 @@ static void osnoise_hist_usage(char *usage)
/*
* osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct osnoise_params
+static struct common_params
*osnoise_hist_parse_args(int argc, char *argv[])
{
struct osnoise_params *params;
struct trace_events *tevent;
int retval;
int c;
+ char *trace_output = NULL;
params = calloc(1, sizeof(*params));
if (!params)
exit(1);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
+
/* display data in microseconds */
params->common.output_divisor = 1000;
params->common.hist.bucket_size = 1;
@@ -543,7 +553,7 @@ static struct osnoise_params
params->threshold = 1;
/* set trace */
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'b':
@@ -634,13 +644,13 @@ static struct osnoise_params
case 't':
if (optarg) {
if (optarg[0] == '=')
- params->trace_output = &optarg[1];
+ trace_output = &optarg[1];
else
- params->trace_output = &optarg[0];
+ trace_output = &optarg[0];
} else if (optind < argc && argv[optind][0] != '0')
- params->trace_output = argv[optind];
+ trace_output = argv[optind];
else
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case '0': /* no header */
params->common.hist.no_header = 1;
@@ -687,6 +697,9 @@ static struct osnoise_params
}
}
+ if (trace_output)
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
+
if (geteuid()) {
err_msg("rtla needs root permission\n");
exit(EXIT_FAILURE);
@@ -695,32 +708,23 @@ static struct osnoise_params
if (params->common.hist.no_index && !params->common.hist.with_zeros)
osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense");
- return params;
+ return ¶ms->common;
}
/*
* osnoise_hist_apply_config - apply the hist configs to the initialized tool
*/
static int
-osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
+osnoise_hist_apply_config(struct osnoise_tool *tool)
{
- int retval;
-
- retval = osnoise_apply_config(tool, params);
- if (retval)
- goto out_err;
-
- return 0;
-
-out_err:
- return -1;
+ return osnoise_apply_config(tool, to_osnoise_params(tool->params));
}
/*
* osnoise_init_hist - initialize a osnoise hist tool with parameters
*/
static struct osnoise_tool
-*osnoise_init_hist(struct osnoise_params *params)
+*osnoise_init_hist(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -731,13 +735,11 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = osnoise_alloc_histogram(nr_cpus, params->common.hist.entries,
- params->common.hist.bucket_size);
+ tool->data = osnoise_alloc_histogram(nr_cpus, params->hist.entries,
+ params->hist.bucket_size);
if (!tool->data)
goto out_err;
- tool->params = params;
-
return tool;
out_err:
@@ -745,171 +747,35 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static void stop_hist(int sig)
-{
- stop_tracing = 1;
-}
-
-/*
- * osnoise_hist_set_signals - handles the signal to stop the tool
- */
-static void
-osnoise_hist_set_signals(struct osnoise_params *params)
+static int osnoise_hist_enable(struct osnoise_tool *tool)
{
- signal(SIGINT, stop_hist);
- if (params->common.duration) {
- signal(SIGALRM, stop_hist);
- alarm(params->common.duration);
- }
-}
-
-int osnoise_hist_main(int argc, char *argv[])
-{
- struct osnoise_params *params;
- struct osnoise_tool *record = NULL;
- struct osnoise_tool *tool = NULL;
- enum result return_value = ERROR;
- struct trace_instance *trace;
int retval;
- params = osnoise_hist_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = osnoise_init_hist(params);
- if (!tool) {
- err_msg("Could not init osnoise hist\n");
- goto out_exit;
- }
-
- retval = osnoise_hist_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_destroy;
- }
-
- trace = &tool->trace;
-
- retval = enable_osnoise(trace);
- if (retval) {
- err_msg("Failed to enable osnoise tracer\n");
- goto out_destroy;
- }
-
retval = osnoise_init_trace_hist(tool);
if (retval)
- goto out_destroy;
+ return retval;
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->trace_output) {
- record = osnoise_init_trace_tool("osnoise");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_hist;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_hist;
- }
- }
-
- /*
- * Start the tracer here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (params->trace_output)
- trace_instance_start(&record->trace);
- trace_instance_start(trace);
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_hist;
-
- /*
- * Clean up the buffer. The osnoise workload do not run
- * with tracing off to avoid creating a performance penalty
- * when not needed.
- */
- retval = tracefs_instance_file_write(trace->inst, "trace", "");
- if (retval < 0) {
- debug_msg("Error cleaning up the buffer");
- goto out_hist;
- }
-
- }
-
- tool->start_time = time(NULL);
- osnoise_hist_set_signals(params);
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_hist;
- }
+ return osnoise_enable(tool);
+}
- if (osnoise_trace_is_off(tool, record))
- break;
- }
+static int osnoise_hist_main_loop(struct osnoise_tool *tool)
+{
+ int retval;
+ retval = hist_main_loop(tool);
osnoise_read_trace_hist(tool);
- osnoise_print_stats(params, tool);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(tool, record)) {
- printf("rtla osnoise hit stop tracing\n");
- save_trace_to_file(record ? record->trace.inst : NULL,
- params->trace_output);
- return_value = FAILED;
- }
-
-out_hist:
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- osnoise_free_histogram(tool->data);
-out_destroy:
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- free(params);
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops osnoise_hist_ops = {
+ .tracer = "osnoise",
+ .comm_prefix = "osnoise/",
+ .parse_args = osnoise_hist_parse_args,
+ .init_tool = osnoise_init_hist,
+ .apply_config = osnoise_hist_apply_config,
+ .enable = osnoise_hist_enable,
+ .main = osnoise_hist_main_loop,
+ .print_stats = osnoise_print_stats,
+ .free = osnoise_free_hist_tool,
+};
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 7c68feed300e..5a56c276f9da 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -37,13 +37,17 @@ struct osnoise_top_data {
/*
* osnoise_free_top - free runtime data
*/
-static void
-osnoise_free_top(struct osnoise_top_data *data)
+static void osnoise_free_top(struct osnoise_top_data *data)
{
free(data->cpu_data);
free(data);
}
+static void osnoise_free_top_tool(struct osnoise_tool *tool)
+{
+ osnoise_free_top(tool->data);
+}
+
/*
* osnoise_alloc_histogram - alloc runtime data
*/
@@ -123,7 +127,7 @@ osnoise_top_handler(struct trace_seq *s, struct tep_record *record,
*/
static void osnoise_top_header(struct osnoise_tool *top)
{
- struct osnoise_params *params = top->params;
+ struct osnoise_params *params = to_osnoise_params(top->params);
struct trace_seq *s = top->trace.seq;
bool pretty = params->common.pretty_output;
char duration[26];
@@ -184,7 +188,7 @@ static void clear_terminal(struct trace_seq *seq)
*/
static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct trace_seq *s = tool->trace.seq;
struct osnoise_top_cpu *cpu_data;
struct osnoise_top_data *data;
@@ -224,8 +228,9 @@ static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
* osnoise_print_stats - print data for all cpus
*/
static void
-osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
+osnoise_print_stats(struct osnoise_tool *top)
{
+ struct osnoise_params *params = to_osnoise_params(top->params);
struct trace_instance *trace = &top->trace;
static int nr_cpus = -1;
int i;
@@ -320,17 +325,21 @@ static void osnoise_top_usage(struct osnoise_params *params, char *usage)
/*
* osnoise_top_parse_args - allocs, parse and fill the cmd line parameters
*/
-struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
+struct common_params *osnoise_top_parse_args(int argc, char **argv)
{
struct osnoise_params *params;
struct trace_events *tevent;
int retval;
int c;
+ char *trace_output = NULL;
params = calloc(1, sizeof(*params));
if (!params)
exit(1);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
+
if (strcmp(argv[0], "hwnoise") == 0) {
params->mode = MODE_HWNOISE;
/*
@@ -384,7 +393,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->threshold = 1;
/* set trace */
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'c':
@@ -463,13 +472,13 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
case 't':
if (optarg) {
if (optarg[0] == '=')
- params->trace_output = &optarg[1];
+ trace_output = &optarg[1];
else
- params->trace_output = &optarg[0];
+ trace_output = &optarg[0];
} else if (optind < argc && argv[optind][0] != '-')
- params->trace_output = argv[optind];
+ trace_output = argv[optind];
else
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'T':
params->threshold = get_llong_from_str(optarg);
@@ -507,20 +516,24 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
}
+ if (trace_output)
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
+
if (geteuid()) {
err_msg("osnoise needs root permission\n");
exit(EXIT_FAILURE);
}
- return params;
+ return ¶ms->common;
}
/*
* osnoise_top_apply_config - apply the top configs to the initialized tool
*/
static int
-osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
+osnoise_top_apply_config(struct osnoise_tool *tool)
{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
int retval;
retval = osnoise_apply_config(tool, params);
@@ -547,7 +560,7 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *param
/*
* osnoise_init_top - initialize a osnoise top tool with parameters
*/
-struct osnoise_tool *osnoise_init_top(struct osnoise_params *params)
+struct osnoise_tool *osnoise_init_top(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -564,175 +577,20 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_params *params)
return NULL;
}
- tool->params = params;
-
tep_register_event_handler(tool->trace.tep, -1, "ftrace", "osnoise",
osnoise_top_handler, NULL);
return tool;
}
-static int stop_tracing;
-static void stop_top(int sig)
-{
- stop_tracing = 1;
-}
-
-/*
- * osnoise_top_set_signals - handles the signal to stop the tool
- */
-static void osnoise_top_set_signals(struct osnoise_params *params)
-{
- signal(SIGINT, stop_top);
- if (params->common.duration) {
- signal(SIGALRM, stop_top);
- alarm(params->common.duration);
- }
-}
-
-int osnoise_top_main(int argc, char **argv)
-{
- struct osnoise_params *params;
- struct osnoise_tool *record = NULL;
- struct osnoise_tool *tool = NULL;
- enum result return_value = ERROR;
- struct trace_instance *trace;
- int retval;
-
- params = osnoise_top_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = osnoise_init_top(params);
- if (!tool) {
- err_msg("Could not init osnoise top\n");
- goto out_exit;
- }
-
- retval = osnoise_top_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
-
- trace = &tool->trace;
-
- retval = enable_osnoise(trace);
- if (retval) {
- err_msg("Failed to enable osnoise tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup) {
- retval = set_comm_cgroup("osnoise/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->trace_output) {
- record = osnoise_init_trace_tool("osnoise");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_top;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_top;
- }
- }
-
- /*
- * Start the tracer here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (params->trace_output)
- trace_instance_start(&record->trace);
- trace_instance_start(trace);
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_top;
-
- /*
- * Clean up the buffer. The osnoise workload do not run
- * with tracing off to avoid creating a performance penalty
- * when not needed.
- */
- retval = tracefs_instance_file_write(trace->inst, "trace", "");
- if (retval < 0) {
- debug_msg("Error cleaning up the buffer");
- goto out_top;
- }
-
- }
-
- tool->start_time = time(NULL);
- osnoise_top_set_signals(params);
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_top;
- }
-
- if (!params->common.quiet)
- osnoise_print_stats(params, tool);
-
- if (osnoise_trace_is_off(tool, record))
- break;
-
- }
-
- osnoise_print_stats(params, tool);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(tool, record)) {
- printf("osnoise hit stop tracing\n");
- save_trace_to_file(record ? record->trace.inst : NULL,
- params->trace_output);
- return_value = FAILED;
- }
-
-out_top:
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- osnoise_free_top(tool->data);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- free(params);
-out_exit:
- exit(return_value);
-}
+struct tool_ops osnoise_top_ops = {
+ .tracer = "osnoise",
+ .comm_prefix = "osnoise/",
+ .parse_args = osnoise_top_parse_args,
+ .init_tool = osnoise_init_top,
+ .apply_config = osnoise_top_apply_config,
+ .enable = osnoise_enable,
+ .main = top_main_loop,
+ .print_stats = osnoise_print_stats,
+ .free = osnoise_free_top_tool,
+};
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index e4bf58db1dd2..b69212874127 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -15,9 +15,13 @@
#include <sched.h>
#include "timerlat.h"
+#include "timerlat_aa.h"
+#include "timerlat_bpf.h"
#define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */
+static int dma_latency_fd = -1;
+
/*
* timerlat_apply_config - apply common configs to the initialized tool
*/
@@ -26,6 +30,24 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
int retval;
+ /*
+ * Try to enable BPF, unless disabled explicitly.
+ * If BPF enablement fails, fall back to tracefs mode.
+ */
+ if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
+ debug_msg("RTLA_NO_BPF set, disabling BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ } else if (!tep_find_event_by_name(tool->trace.tep, "osnoise", "timerlat_sample")) {
+ debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ } else {
+ retval = timerlat_bpf_init(params);
+ if (retval) {
+ debug_msg("Could not enable BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ }
+ }
+
if (params->mode != TRACING_MODE_BPF) {
/*
* In tracefs and mixed mode, timerlat tracer handles stopping
@@ -65,12 +87,12 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
- if (!params->common.kernel_workload && !params->user_data) {
+ if (!params->common.kernel_workload && !params->common.user_data) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
- params->user_workload = 1;
- params->user_data = 1;
+ params->common.user_workload = 1;
+ params->common.user_data = 1;
} else {
debug_msg("User-space interface not detected, setting kernel-threads\n");
params->common.kernel_workload = 1;
@@ -83,6 +105,137 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
return -1;
}
+int timerlat_enable(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int retval, nr_cpus, i;
+
+ if (params->dma_latency >= 0) {
+ dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
+ if (dma_latency_fd < 0) {
+ err_msg("Could not set /dev/cpu_dma_latency.\n");
+ return -1;
+ }
+ }
+
+ if (params->deepest_idle_state >= -1) {
+ if (!have_libcpupower_support()) {
+ err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
+ return -1;
+ }
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
+ continue;
+ if (save_cpu_idle_disable_state(i) < 0) {
+ err_msg("Could not save cpu idle state.\n");
+ return -1;
+ }
+ if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
+ err_msg("Could not set deepest cpu idle state.\n");
+ return -1;
+ }
+ }
+ }
+
+ if (!params->no_aa) {
+ tool->aa = osnoise_init_tool("timerlat_aa");
+ if (!tool->aa)
+ return -1;
+
+ retval = timerlat_aa_init(tool->aa, params->dump_tasks);
+ if (retval) {
+ err_msg("Failed to enable the auto analysis instance\n");
+ return retval;
+ }
+
+ retval = enable_tracer_by_name(tool->aa->trace.inst, "timerlat");
+ if (retval) {
+ err_msg("Failed to enable aa tracer\n");
+ return retval;
+ }
+ }
+
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
+ if (stop_tracing)
+ return -1;
+ }
+
+ /*
+ * Start the tracers here, after having set all instances.
+ *
+ * Let the trace instance start first for the case of hitting a stop
+ * tracing while enabling other instances. The trace instance is the
+ * one with most valuable information.
+ */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (!params->no_aa)
+ trace_instance_start(&tool->aa->trace);
+ if (params->mode == TRACING_MODE_TRACEFS) {
+ trace_instance_start(&tool->trace);
+ } else {
+ retval = timerlat_bpf_attach();
+ if (retval) {
+ err_msg("Error attaching BPF program\n");
+ return retval;
+ }
+ }
+
+ return 0;
+}
+
+void timerlat_analyze(struct osnoise_tool *tool, bool stopped)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+
+ if (stopped) {
+ if (!params->no_aa)
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
+ } else if (params->common.aa_only) {
+ char *max_lat;
+
+ /*
+ * If the trace did not stop with --aa-only, at least print
+ * the max known latency.
+ */
+ max_lat = tracefs_instance_file_read(trace_inst->inst, "tracing_max_latency", NULL);
+ if (max_lat) {
+ printf(" Max latency was %s\n", max_lat);
+ free(max_lat);
+ }
+ }
+}
+
+void timerlat_free(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int nr_cpus, i;
+
+ timerlat_aa_destroy();
+ if (dma_latency_fd >= 0)
+ close(dma_latency_fd);
+ if (params->deepest_idle_state >= -1) {
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->common.cpus &&
+ !CPU_ISSET(i, ¶ms->common.monitored_cpus))
+ continue;
+ restore_cpu_idle_disable_state(i);
+ }
+ }
+
+ osnoise_destroy_tool(tool->aa);
+
+ if (params->mode != TRACING_MODE_TRACEFS)
+ timerlat_bpf_destroy();
+ free_cpu_idle_disable_states();
+}
+
static void timerlat_usage(int err)
{
int i;
@@ -116,7 +269,7 @@ int timerlat_main(int argc, char *argv[])
* default cmdline.
*/
if (argc == 1) {
- timerlat_top_main(argc, argv);
+ run_tool(&timerlat_top_ops, argc, argv);
exit(0);
}
@@ -124,13 +277,13 @@ int timerlat_main(int argc, char *argv[])
timerlat_usage(0);
} else if (strncmp(argv[1], "-", 1) == 0) {
/* the user skipped the tool, call the default one */
- timerlat_top_main(argc, argv);
+ run_tool(&timerlat_top_ops, argc, argv);
exit(0);
} else if (strcmp(argv[1], "top") == 0) {
- timerlat_top_main(argc-1, &argv[1]);
+ run_tool(&timerlat_top_ops, argc-1, &argv[1]);
exit(0);
} else if (strcmp(argv[1], "hist") == 0) {
- timerlat_hist_main(argc-1, &argv[1]);
+ run_tool(&timerlat_hist_ops, argc-1, &argv[1]);
exit(0);
}
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index 86cd9bac8855..fd6065f48bb7 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "actions.h"
#include "osnoise.h"
/*
@@ -26,18 +25,15 @@ struct timerlat_params {
int dma_latency;
int no_aa;
int dump_tasks;
- int user_workload;
- int user_data;
int deepest_idle_state;
- int aa_only;
enum timerlat_tracing_mode mode;
-
- struct actions threshold_actions;
- struct actions end_actions;
};
-int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
+#define to_timerlat_params(ptr) container_of(ptr, struct timerlat_params, common)
-int timerlat_hist_main(int argc, char *argv[]);
-int timerlat_top_main(int argc, char *argv[]);
+int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
int timerlat_main(int argc, char *argv[]);
+int timerlat_enable(struct osnoise_tool *tool);
+void timerlat_analyze(struct osnoise_tool *tool, bool stopped);
+void timerlat_free(struct osnoise_tool *tool);
+
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index 03be2606f54a..e97d16646bcd 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -25,7 +25,7 @@ int timerlat_bpf_init(struct timerlat_params *params)
bpf->rodata->entries = params->common.hist.entries;
bpf->rodata->irq_threshold = params->common.stop_us;
bpf->rodata->thread_threshold = params->common.stop_total_us;
- bpf->rodata->aa_only = params->aa_only;
+ bpf->rodata->aa_only = params->common.aa_only;
if (params->common.hist.entries != 0) {
/* Pass histogram options */
@@ -42,7 +42,7 @@ int timerlat_bpf_init(struct timerlat_params *params)
bpf_map__set_autocreate(bpf->maps.hist_user, false);
}
- if (params->aa_only) {
+ if (params->common.aa_only) {
/* Auto-analysis only, disable summary */
bpf_map__set_autocreate(bpf->maps.summary_irq, false);
bpf_map__set_autocreate(bpf->maps.summary_thread, false);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index d339e2cffae2..a9154f83f1a9 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -16,7 +16,6 @@
#include "timerlat.h"
#include "timerlat_aa.h"
-#include "timerlat_u.h"
#include "timerlat_bpf.h"
struct timerlat_hist_cpu {
@@ -72,8 +71,12 @@ timerlat_free_histogram(struct timerlat_hist_data *data)
/* one set of histograms per CPU */
if (data->hist)
free(data->hist);
+}
- free(data);
+static void timerlat_free_histogram_tool(struct osnoise_tool *tool)
+{
+ timerlat_free_histogram(tool->data);
+ timerlat_free(tool);
}
/*
@@ -135,7 +138,7 @@ timerlat_hist_update(struct osnoise_tool *tool, int cpu,
unsigned long long context,
unsigned long long latency)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
int entries = data->entries;
int bucket;
@@ -282,7 +285,7 @@ static int timerlat_hist_bpf_pull_data(struct osnoise_tool *tool)
*/
static void timerlat_hist_header(struct osnoise_tool *tool)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
struct trace_seq *s = tool->trace.seq;
char duration[26];
@@ -315,7 +318,7 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
if (!params->common.hist.no_thread)
trace_seq_printf(s, " Thr-%03d", cpu);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " Usr-%03d", cpu);
}
trace_seq_printf(s, "\n");
@@ -371,7 +374,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].thread_count);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].user_count);
}
@@ -399,7 +402,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].min_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].min_user,
@@ -429,7 +432,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].sum_thread,
true);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].sum_user,
@@ -459,7 +462,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].max_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].max_user,
@@ -521,7 +524,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, " Thr");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, " Usr");
trace_seq_printf(trace->seq, "\n");
@@ -537,7 +540,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "%9llu ",
sum.thread_count);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9llu ",
sum.user_count);
@@ -558,7 +561,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.min_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.min_user,
@@ -581,7 +584,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.sum_thread,
true);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.sum_user,
@@ -604,7 +607,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.max_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.max_user,
@@ -619,8 +622,9 @@ timerlat_print_stats_all(struct timerlat_params *params,
* timerlat_print_stats - print data for each CPUs
*/
static void
-timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
+timerlat_print_stats(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
struct trace_instance *trace = &tool->trace;
int bucket, cpu;
@@ -654,7 +658,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
data->hist[cpu].thread[bucket]);
}
- if (params->user_data) {
+ if (params->common.user_data) {
total += data->hist[cpu].user[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].user[bucket]);
@@ -690,7 +694,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[data->entries]);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].user[data->entries]);
}
@@ -780,7 +784,7 @@ static void timerlat_hist_usage(char *usage)
/*
* timerlat_hist_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct timerlat_params
+static struct common_params
*timerlat_hist_parse_args(int argc, char *argv[])
{
struct timerlat_params *params;
@@ -794,8 +798,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->threshold_actions);
- actions_init(¶ms->end_actions);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -975,10 +979,10 @@ static struct timerlat_params
trace_output = "timerlat_trace.txt";
break;
case 'u':
- params->user_workload = 1;
+ params->common.user_workload = 1;
/* fallback: -u implies in -U */
case 'U':
- params->user_data = 1;
+ params->common.user_data = 1;
break;
case '0': /* no irq */
params->common.hist.no_irq = 1;
@@ -1043,14 +1047,14 @@ static struct timerlat_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '\5':
- retval = actions_parse(¶ms->threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\6':
- retval = actions_parse(¶ms->end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1062,7 +1066,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->threshold_actions, trace_output);
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -1081,7 +1085,7 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->common.kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->common.user_workload)
timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
@@ -1089,19 +1093,21 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
+ !params->no_aa))
params->mode = TRACING_MODE_MIXED;
- return params;
+ return ¶ms->common;
}
/*
* timerlat_hist_apply_config - apply the hist configs to the initialized tool
*/
static int
-timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
+timerlat_hist_apply_config(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
retval = timerlat_apply_config(tool, params);
@@ -1118,7 +1124,7 @@ timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *pa
* timerlat_init_hist - initialize a timerlat hist tool with parameters
*/
static struct osnoise_tool
-*timerlat_init_hist(struct timerlat_params *params)
+*timerlat_init_hist(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -1129,13 +1135,11 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = timerlat_alloc_histogram(nr_cpus, params->common.hist.entries,
- params->common.hist.bucket_size);
+ tool->data = timerlat_alloc_histogram(nr_cpus, params->hist.entries,
+ params->hist.bucket_size);
if (!tool->data)
goto out_err;
- tool->params = params;
-
tep_register_event_handler(tool->trace.tep, -1, "ftrace", "timerlat",
timerlat_hist_handler, tool);
@@ -1146,349 +1150,61 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static struct trace_instance *hist_inst = NULL;
-static void stop_hist(int sig)
-{
- if (stop_tracing) {
- /*
- * Stop requested twice in a row; abort event processing and
- * exit immediately
- */
- tracefs_iterate_stop(hist_inst->inst);
- return;
- }
- stop_tracing = 1;
- if (hist_inst)
- trace_instance_stop(hist_inst);
-}
-
-/*
- * timerlat_hist_set_signals - handles the signal to stop the tool
- */
-static void
-timerlat_hist_set_signals(struct timerlat_params *params)
+static int timerlat_hist_bpf_main_loop(struct osnoise_tool *tool)
{
- signal(SIGINT, stop_hist);
- if (params->common.duration) {
- signal(SIGALRM, stop_hist);
- alarm(params->common.duration);
- }
-}
-
-int timerlat_hist_main(int argc, char *argv[])
-{
- struct timerlat_params *params;
- struct osnoise_tool *record = NULL;
- struct timerlat_u_params params_u;
- enum result return_value = ERROR;
- struct osnoise_tool *tool = NULL;
- struct osnoise_tool *aa = NULL;
- struct trace_instance *trace;
- int dma_latency_fd = -1;
- pthread_t timerlat_u;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
- int nr_cpus, i;
-
- params = timerlat_hist_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = timerlat_init_hist(params);
- if (!tool) {
- err_msg("Could not init osnoise hist\n");
- goto out_exit;
- }
-
- trace = &tool->trace;
- /*
- * Save trace instance into global variable so that SIGINT can stop
- * the timerlat tracer.
- * Otherwise, rtla could loop indefinitely when overloaded.
- */
- hist_inst = trace;
-
- /*
- * Try to enable BPF, unless disabled explicitly.
- * If BPF enablement fails, fall back to tracefs mode.
- */
- if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
- debug_msg("RTLA_NO_BPF set, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
- debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else {
- retval = timerlat_bpf_init(params);
- if (retval) {
- debug_msg("Could not enable BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- }
- }
-
- retval = timerlat_hist_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
-
- retval = enable_timerlat(trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup && !params->user_workload) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->dma_latency >= 0) {
- dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
- if (dma_latency_fd < 0) {
- err_msg("Could not set /dev/cpu_dma_latency.\n");
- goto out_free;
- }
- }
-
- if (params->deepest_idle_state >= -1) {
- if (!have_libcpupower_support()) {
- err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
- goto out_free;
- }
-
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- if (save_cpu_idle_disable_state(i) < 0) {
- err_msg("Could not save cpu idle state.\n");
- goto out_free;
- }
- if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
- err_msg("Could not set deepest cpu idle state.\n");
- goto out_free;
- }
- }
- }
-
- if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT]) {
- record = osnoise_init_trace_tool("timerlat");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
- params->threshold_actions.trace_output_inst = record->trace.inst;
- params->end_actions.trace_output_inst = record->trace.inst;
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_hist;
- }
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_hist;
- }
- }
+ while (!stop_tracing) {
+ timerlat_bpf_wait(-1);
- if (!params->no_aa) {
- aa = osnoise_init_tool("timerlat_aa");
- if (!aa)
- goto out_hist;
+ if (!stop_tracing) {
+ /* Threshold overflow, perform actions on threshold */
+ actions_perform(¶ms->common.threshold_actions);
- retval = timerlat_aa_init(aa, params->dump_tasks);
- if (retval) {
- err_msg("Failed to enable the auto analysis instance\n");
- goto out_hist;
- }
+ if (!params->common.threshold_actions.continue_flag)
+ /* continue flag not set, break */
+ break;
- retval = enable_timerlat(&aa->trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_hist;
+ /* continue action reached, re-enable tracing */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ timerlat_bpf_restart_tracing();
}
}
+ timerlat_bpf_detach();
- if (params->user_workload) {
- /* rtla asked to stop */
- params_u.should_run = 1;
- /* all threads left */
- params_u.stopped_running = 0;
-
- params_u.set = ¶ms->common.monitored_cpus;
- if (params->common.set_sched)
- params_u.sched_param = ¶ms->common.sched_param;
- else
- params_u.sched_param = NULL;
-
- params_u.cgroup_name = params->common.cgroup_name;
-
- retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
- if (retval)
- err_msg("Error creating timerlat user-space threads\n");
- }
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_hist;
- }
-
- /*
- * Start the tracers here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- if (params->mode == TRACING_MODE_TRACEFS) {
- trace_instance_start(trace);
- } else {
- retval = timerlat_bpf_attach();
- if (retval) {
- err_msg("Error attaching BPF program\n");
- goto out_hist;
- }
- }
-
- tool->start_time = time(NULL);
- timerlat_hist_set_signals(params);
-
- if (params->mode == TRACING_MODE_TRACEFS) {
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_hist;
- }
-
- if (osnoise_trace_is_off(tool, record)) {
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- trace_instance_start(trace);
- }
-
- /* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u.stopped_running) {
- debug_msg("timerlat user-space threads stopped!\n");
- break;
- }
- }
- }
- } else {
- while (!stop_tracing) {
- timerlat_bpf_wait(-1);
-
- if (!stop_tracing) {
- /* Threshold overflow, perform actions on threshold */
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- timerlat_bpf_restart_tracing();
- }
- }
- }
-
- if (params->mode != TRACING_MODE_TRACEFS) {
- timerlat_bpf_detach();
- retval = timerlat_hist_bpf_pull_data(tool);
- if (retval) {
- err_msg("Error pulling BPF data\n");
- goto out_hist;
- }
- }
-
- if (params->user_workload && !params_u.stopped_running) {
- params_u.should_run = 0;
- sleep(1);
- }
-
- timerlat_print_stats(params, tool);
-
- actions_perform(¶ms->end_actions);
-
- return_value = PASSED;
+ retval = timerlat_hist_bpf_pull_data(tool);
+ if (retval)
+ err_msg("Error pulling BPF data\n");
- if (osnoise_trace_is_off(tool, record) && !stop_tracing) {
- printf("rtla timerlat hit stop tracing\n");
+ return retval;
+}
- if (!params->no_aa)
- timerlat_auto_analysis(params->common.stop_us,
- params->common.stop_total_us);
+static int timerlat_hist_main(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int retval;
- return_value = FAILED;
- }
+ if (params->mode == TRACING_MODE_TRACEFS)
+ retval = hist_main_loop(tool);
+ else
+ retval = timerlat_hist_bpf_main_loop(tool);
-out_hist:
- timerlat_aa_destroy();
- if (dma_latency_fd >= 0)
- close(dma_latency_fd);
- if (params->deepest_idle_state >= -1) {
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- restore_cpu_idle_disable_state(i);
- }
- }
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- timerlat_free_histogram(tool->data);
- osnoise_destroy_tool(aa);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- actions_destroy(¶ms->threshold_actions);
- actions_destroy(¶ms->end_actions);
- if (params->mode != TRACING_MODE_TRACEFS)
- timerlat_bpf_destroy();
- free(params);
- free_cpu_idle_disable_states();
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops timerlat_hist_ops = {
+ .tracer = "timerlat",
+ .comm_prefix = "timerlat/",
+ .parse_args = timerlat_hist_parse_args,
+ .init_tool = timerlat_init_hist,
+ .apply_config = timerlat_hist_apply_config,
+ .enable = timerlat_enable,
+ .main = timerlat_hist_main,
+ .print_stats = timerlat_print_stats,
+ .analyze = timerlat_analyze,
+ .free = timerlat_free_histogram_tool,
+};
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index bb42697d2575..42c3b0518749 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -17,7 +17,6 @@
#include "timerlat.h"
#include "timerlat_aa.h"
-#include "timerlat_u.h"
#include "timerlat_bpf.h"
struct timerlat_top_cpu {
@@ -49,13 +48,18 @@ struct timerlat_top_data {
/*
* timerlat_free_top - free runtime data
*/
-static void
-timerlat_free_top(struct timerlat_top_data *data)
+static void timerlat_free_top(struct timerlat_top_data *data)
{
free(data->cpu_data);
free(data);
}
+static void timerlat_free_top_tool(struct osnoise_tool *tool)
+{
+ timerlat_free_top(tool->data);
+ timerlat_free(tool);
+}
+
/*
* timerlat_alloc_histogram - alloc runtime data
*/
@@ -128,7 +132,7 @@ timerlat_top_update(struct osnoise_tool *tool, int cpu,
unsigned long long thread,
unsigned long long latency)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_top_data *data = tool->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
@@ -164,15 +168,13 @@ timerlat_top_handler(struct trace_seq *s, struct tep_record *record,
struct tep_event *event, void *context)
{
struct trace_instance *trace = context;
- struct timerlat_params *params;
unsigned long long latency, thread;
struct osnoise_tool *top;
int cpu = record->cpu;
top = container_of(trace, struct osnoise_tool, trace);
- params = top->params;
- if (!params->aa_only) {
+ if (!top->params->aa_only) {
tep_get_field_val(s, event, "context", record, &thread, 1);
tep_get_field_val(s, event, "timer_latency", record, &latency, 1);
@@ -267,7 +269,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " Timer Latency ");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " ");
if (pretty)
@@ -278,7 +280,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
params->common.output_divisor == 1 ? "ns" : "us",
params->common.output_divisor == 1 ? "ns" : "us");
- if (params->user_data) {
+ if (params->common.user_data) {
trace_seq_printf(s, " | Ret user Timer Latency (%s)",
params->common.output_divisor == 1 ? "ns" : "us");
}
@@ -288,7 +290,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU COUNT | cur min avg max | cur min avg max");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " | cur min avg max");
if (pretty)
@@ -303,8 +305,7 @@ static const char *no_value = " -";
*/
static void timerlat_top_print(struct osnoise_tool *top, int cpu)
{
-
- struct timerlat_params *params = top->params;
+ struct timerlat_params *params = to_timerlat_params(top->params);
struct timerlat_top_data *data = top->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
struct trace_seq *s = top->trace.seq;
@@ -339,7 +340,7 @@ static void timerlat_top_print(struct osnoise_tool *top, int cpu)
trace_seq_printf(s, "%9llu", cpu_data->max_thread);
}
- if (!params->user_data) {
+ if (!params->common.user_data) {
trace_seq_printf(s, "\n");
return;
}
@@ -364,7 +365,7 @@ static void
timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summary)
{
const char *split = "----------------------------------------";
- struct timerlat_params *params = top->params;
+ struct timerlat_params *params = to_timerlat_params(top->params);
unsigned long long count = summary->irq_count;
struct trace_seq *s = top->trace.seq;
int e = 0;
@@ -381,7 +382,7 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summar
}
trace_seq_printf(s, "%.*s|%.*s|%.*s", 15, split, 40, split, 39, split);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, "-|%.*s", 39, split);
trace_seq_printf(s, "\n");
@@ -406,7 +407,7 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summar
trace_seq_printf(s, "%9llu", summary->max_thread);
}
- if (!params->user_data) {
+ if (!params->common.user_data) {
trace_seq_printf(s, "\n");
return;
}
@@ -437,14 +438,15 @@ static void clear_terminal(struct trace_seq *seq)
* timerlat_print_stats - print data for all cpus
*/
static void
-timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
+timerlat_print_stats(struct osnoise_tool *top)
{
+ struct timerlat_params *params = to_timerlat_params(top->params);
struct trace_instance *trace = &top->trace;
struct timerlat_top_cpu summary;
static int nr_cpus = -1;
int i;
- if (params->aa_only)
+ if (params->common.aa_only)
return;
if (nr_cpus == -1)
@@ -540,7 +542,7 @@ static void timerlat_top_usage(char *usage)
/*
* timerlat_top_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct timerlat_params
+static struct common_params
*timerlat_top_parse_args(int argc, char **argv)
{
struct timerlat_params *params;
@@ -554,8 +556,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->threshold_actions);
- actions_init(¶ms->end_actions);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -641,7 +643,7 @@ static struct timerlat_params
params->print_stack = auto_thresh;
/* set aa_only to avoid parsing the trace */
- params->aa_only = 1;
+ params->common.aa_only = 1;
break;
case 'c':
retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
@@ -731,10 +733,10 @@ static struct timerlat_params
trace_output = "timerlat_trace.txt";
break;
case 'u':
- params->user_workload = true;
+ params->common.user_workload = true;
/* fallback: -u implies -U */
case 'U':
- params->user_data = true;
+ params->common.user_data = true;
break;
case '0': /* trigger */
if (params->common.events) {
@@ -781,14 +783,14 @@ static struct timerlat_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '9':
- retval = actions_parse(¶ms->threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\1':
- retval = actions_parse(¶ms->end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -800,7 +802,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->threshold_actions, trace_output);
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -813,10 +815,10 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->no_aa && params->aa_only)
+ if (params->no_aa && params->common.aa_only)
timerlat_top_usage("--no-aa and --aa-only are mutually exclusive!");
- if (params->common.kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->common.user_workload)
timerlat_top_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
@@ -824,19 +826,21 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
+ !params->no_aa))
params->mode = TRACING_MODE_MIXED;
- return params;
+ return ¶ms->common;
}
/*
* timerlat_top_apply_config - apply the top configs to the initialized tool
*/
static int
-timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *params)
+timerlat_top_apply_config(struct osnoise_tool *top)
{
+ struct timerlat_params *params = to_timerlat_params(top->params);
int retval;
retval = timerlat_apply_config(top, params);
@@ -856,7 +860,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *para
* timerlat_init_top - initialize a timerlat top tool with parameters
*/
static struct osnoise_tool
-*timerlat_init_top(struct timerlat_params *params)
+*timerlat_init_top(struct common_params *params)
{
struct osnoise_tool *top;
int nr_cpus;
@@ -871,8 +875,6 @@ static struct osnoise_tool
if (!top->data)
goto out_err;
- top->params = params;
-
tep_register_event_handler(top->trace.tep, -1, "ftrace", "timerlat",
timerlat_top_handler, top);
@@ -883,109 +885,16 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static struct trace_instance *top_inst = NULL;
-static void stop_top(int sig)
-{
- if (stop_tracing) {
- /*
- * Stop requested twice in a row; abort event processing and
- * exit immediately
- */
- tracefs_iterate_stop(top_inst->inst);
- return;
- }
- stop_tracing = 1;
- if (top_inst)
- trace_instance_stop(top_inst);
-}
-
-/*
- * timerlat_top_set_signals - handles the signal to stop the tool
- */
-static void
-timerlat_top_set_signals(struct timerlat_params *params)
-{
- signal(SIGINT, stop_top);
- if (params->common.duration) {
- signal(SIGALRM, stop_top);
- alarm(params->common.duration);
- }
-}
-
-/*
- * timerlat_top_main_loop - main loop to process events
- */
-static int
-timerlat_top_main_loop(struct osnoise_tool *top,
- struct osnoise_tool *record,
- struct osnoise_tool *aa,
- struct timerlat_params *params,
- struct timerlat_u_params *params_u)
-{
- struct trace_instance *trace = &top->trace;
- int retval;
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- if (params->aa_only && !osnoise_trace_is_off(top, record))
- continue;
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- return retval;
- }
-
- if (!params->common.quiet)
- timerlat_print_stats(params, top);
-
- if (osnoise_trace_is_off(top, record)) {
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- trace_instance_start(trace);
- }
-
- /* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u->stopped_running) {
- debug_msg("timerlat user space threads stopped!\n");
- break;
- }
- }
- }
-
- return 0;
-}
-
/*
* timerlat_top_bpf_main_loop - main loop to process events (BPF variant)
*/
static int
-timerlat_top_bpf_main_loop(struct osnoise_tool *top,
- struct osnoise_tool *record,
- struct osnoise_tool *aa,
- struct timerlat_params *params,
- struct timerlat_u_params *params_u)
+__timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval, wait_retval;
- if (params->aa_only) {
+ if (params->common.aa_only) {
/* Auto-analysis only, just wait for stop tracing */
timerlat_bpf_wait(-1);
return 0;
@@ -996,34 +905,34 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
wait_retval = timerlat_bpf_wait(params->common.quiet ? -1 :
params->common.sleep_time);
- retval = timerlat_top_bpf_pull_data(top);
+ retval = timerlat_top_bpf_pull_data(tool);
if (retval) {
err_msg("Error pulling BPF data\n");
return retval;
}
if (!params->common.quiet)
- timerlat_print_stats(params, top);
+ timerlat_print_stats(tool);
if (wait_retval == 1) {
/* Stopping requested by tracer */
- actions_perform(¶ms->threshold_actions);
+ actions_perform(¶ms->common.threshold_actions);
- if (!params->threshold_actions.continue_flag)
+ if (!params->common.threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
timerlat_bpf_restart_tracing();
}
/* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u->stopped_running) {
+ if (params->common.user_workload) {
+ if (params->common.user.stopped_running) {
debug_msg("timerlat user space threads stopped!\n");
break;
}
@@ -1033,274 +942,30 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
return 0;
}
-int timerlat_top_main(int argc, char *argv[])
+static int timerlat_top_main_loop(struct osnoise_tool *tool)
{
- struct timerlat_params *params;
- struct osnoise_tool *record = NULL;
- struct timerlat_u_params params_u;
- enum result return_value = ERROR;
- struct osnoise_tool *top = NULL;
- struct osnoise_tool *aa = NULL;
- struct trace_instance *trace;
- int dma_latency_fd = -1;
- pthread_t timerlat_u;
- char *max_lat;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
- int nr_cpus, i;
-
- params = timerlat_top_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- top = timerlat_init_top(params);
- if (!top) {
- err_msg("Could not init osnoise top\n");
- goto out_exit;
- }
-
- trace = &top->trace;
- /*
- * Save trace instance into global variable so that SIGINT can stop
- * the timerlat tracer.
- * Otherwise, rtla could loop indefinitely when overloaded.
- */
- top_inst = trace;
-
- /*
- * Try to enable BPF, unless disabled explicitly.
- * If BPF enablement fails, fall back to tracefs mode.
- */
- if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
- debug_msg("RTLA_NO_BPF set, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
- debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else {
- retval = timerlat_bpf_init(params);
- if (retval) {
- debug_msg("Could not enable BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- }
- }
-
- retval = timerlat_top_apply_config(top, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
- retval = enable_timerlat(trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup && !params->user_data) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->dma_latency >= 0) {
- dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
- if (dma_latency_fd < 0) {
- err_msg("Could not set /dev/cpu_dma_latency.\n");
- goto out_free;
- }
- }
-
- if (params->deepest_idle_state >= -1) {
- if (!have_libcpupower_support()) {
- err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
- goto out_free;
- }
-
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- if (save_cpu_idle_disable_state(i) < 0) {
- err_msg("Could not save cpu idle state.\n");
- goto out_free;
- }
- if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
- err_msg("Could not set deepest cpu idle state.\n");
- goto out_free;
- }
- }
- }
-
- if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT]) {
- record = osnoise_init_trace_tool("timerlat");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
- params->threshold_actions.trace_output_inst = record->trace.inst;
- params->end_actions.trace_output_inst = record->trace.inst;
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_top;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_top;
- }
- }
-
- if (!params->no_aa) {
- aa = osnoise_init_tool("timerlat_aa");
- if (!aa)
- goto out_top;
-
- retval = timerlat_aa_init(aa, params->dump_tasks);
- if (retval) {
- err_msg("Failed to enable the auto analysis instance\n");
- goto out_top;
- }
-
- /* if it is re-using the main instance, there is no need to start it */
- if (aa != top) {
- retval = enable_timerlat(&aa->trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_top;
- }
- }
- }
-
- if (params->user_workload) {
- /* rtla asked to stop */
- params_u.should_run = 1;
- /* all threads left */
- params_u.stopped_running = 0;
-
- params_u.set = ¶ms->common.monitored_cpus;
- if (params->common.set_sched)
- params_u.sched_param = ¶ms->common.sched_param;
- else
- params_u.sched_param = NULL;
-
- params_u.cgroup_name = params->common.cgroup_name;
-
- retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
- if (retval)
- err_msg("Error creating timerlat user-space threads\n");
- }
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- }
-
- /*
- * Start the tracers here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
if (params->mode == TRACING_MODE_TRACEFS) {
- trace_instance_start(trace);
+ retval = top_main_loop(tool);
} else {
- retval = timerlat_bpf_attach();
- if (retval) {
- err_msg("Error attaching BPF program\n");
- goto out_top;
- }
- }
-
- top->start_time = time(NULL);
- timerlat_top_set_signals(params);
-
- if (params->mode == TRACING_MODE_TRACEFS)
- retval = timerlat_top_main_loop(top, record, aa, params, ¶ms_u);
- else
- retval = timerlat_top_bpf_main_loop(top, record, aa, params, ¶ms_u);
-
- if (retval)
- goto out_top;
-
- if (params->mode != TRACING_MODE_TRACEFS)
+ retval = __timerlat_top_bpf_main_loop(tool);
timerlat_bpf_detach();
-
- if (params->user_workload && !params_u.stopped_running) {
- params_u.should_run = 0;
- sleep(1);
}
- timerlat_print_stats(params, top);
-
- actions_perform(¶ms->end_actions);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(top, record) && !stop_tracing) {
- printf("rtla timerlat hit stop tracing\n");
-
- if (!params->no_aa)
- timerlat_auto_analysis(params->common.stop_us,
- params->common.stop_total_us);
-
- return_value = FAILED;
- } else if (params->aa_only) {
- /*
- * If the trace did not stop with --aa-only, at least print the
- * max known latency.
- */
- max_lat = tracefs_instance_file_read(trace->inst, "tracing_max_latency", NULL);
- if (max_lat) {
- printf(" Max latency was %s\n", max_lat);
- free(max_lat);
- }
- }
-
-out_top:
- timerlat_aa_destroy();
- if (dma_latency_fd >= 0)
- close(dma_latency_fd);
- if (params->deepest_idle_state >= -1) {
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- restore_cpu_idle_disable_state(i);
- }
- }
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- timerlat_free_top(top->data);
- if (aa && aa != top)
- osnoise_destroy_tool(aa);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(top);
- actions_destroy(¶ms->threshold_actions);
- actions_destroy(¶ms->end_actions);
- if (params->mode != TRACING_MODE_TRACEFS)
- timerlat_bpf_destroy();
- free(params);
- free_cpu_idle_disable_states();
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops timerlat_top_ops = {
+ .tracer = "timerlat",
+ .comm_prefix = "timerlat/",
+ .parse_args = timerlat_top_parse_args,
+ .init_tool = timerlat_init_top,
+ .apply_config = timerlat_top_apply_config,
+ .enable = timerlat_enable,
+ .main = timerlat_top_main_loop,
+ .print_stats = timerlat_print_stats,
+ .analyze = timerlat_analyze,
+ .free = timerlat_free_top_tool,
+};
diff --git a/tools/tracing/rtla/src/trace.h b/tools/tracing/rtla/src/trace.h
index 3cd40dd3f06c..1e5aee4b828d 100644
--- a/tools/tracing/rtla/src/trace.h
+++ b/tools/tracing/rtla/src/trace.h
@@ -30,9 +30,6 @@ struct trace_seq *get_trace_seq(void);
int enable_tracer_by_name(struct tracefs_instance *inst, const char *tracer_name);
void disable_tracer(struct tracefs_instance *inst);
-int enable_osnoise(struct trace_instance *trace);
-int enable_timerlat(struct trace_instance *trace);
-
struct tracefs_instance *create_instance(char *instance_name);
void destroy_instance(struct tracefs_instance *inst);
diff --git a/tools/tracing/rtla/tests/hwnoise.t b/tools/tracing/rtla/tests/hwnoise.t
index 23ce250a6852..59abb227d1ca 100644
--- a/tools/tracing/rtla/tests/hwnoise.t
+++ b/tools/tracing/rtla/tests/hwnoise.t
@@ -10,7 +10,7 @@ check "verify help page" \
check "detect noise higher than one microsecond" \
"hwnoise -c 0 -T 1 -d 5s -q" 0
check "set the automatic trace mode" \
- "hwnoise -a 5 -d 10s" 2 "osnoise hit stop tracing"
+ "hwnoise -a 5 -d 10s" 2 "rtla hit stop tracing"
check "set scheduling param to the osnoise tracer threads" \
"hwnoise -P F:1 -c 0 -r 900000 -d 10s -q"
check "stop the trace if a single sample is higher than 1 us" \
diff --git a/tools/tracing/rtla/tests/osnoise.t b/tools/tracing/rtla/tests/osnoise.t
index 7574ec6a5a53..89ff89c465a2 100644
--- a/tools/tracing/rtla/tests/osnoise.t
+++ b/tools/tracing/rtla/tests/osnoise.t
@@ -10,7 +10,7 @@ check "verify help page" \
check "verify the --priority/-P param" \
"osnoise top -P F:1 -c 0 -r 900000 -d 10s -q"
check "verify the --stop/-s param" \
- "osnoise top -s 30 -T 1" 2 "osnoise hit stop tracing"
+ "osnoise top -s 30 -T 1" 2 "rtla hit stop tracing"
check "verify the --trace param" \
"osnoise hist -s 30 -T 1 -t" 2 "Saving trace to osnoise_trace.txt"
check "verify the --entries/-E param" \
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 5/7] tools/rtla: Fix -A option name in test comment
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (3 preceding siblings ...)
2025-08-21 3:57 ` [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-28 6:52 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
2025-08-21 3:57 ` [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
This was changed to --on-threshold when the patches were applied.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/tests/timerlat.t | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/tracing/rtla/tests/timerlat.t b/tools/tracing/rtla/tests/timerlat.t
index c71aed5534bf..b5d1e7260a9b 100644
--- a/tools/tracing/rtla/tests/timerlat.t
+++ b/tools/tracing/rtla/tests/timerlat.t
@@ -47,9 +47,9 @@ check "trace output through -t" \
"timerlat hist -T 2 -t" 2 "^ Saving trace to timerlat_trace.txt$"
check "trace output through -t with custom filename" \
"timerlat hist -T 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
-check "trace output through -A trace" \
+check "trace output through --on-threshold trace" \
"timerlat hist -T 2 --on-threshold trace" 2 "^ Saving trace to timerlat_trace.txt$"
-check "trace output through -A trace with custom filename" \
+check "trace output through --on-threshold trace with custom filename" \
"timerlat hist -T 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check "exec command" \
"timerlat hist -T 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (4 preceding siblings ...)
2025-08-21 3:57 ` [PATCH 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-28 8:09 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Add a check() parameter to indicate which text must not appear in the
output.
Simplify the code so that we can print failures as they happen rather
than trying to figure out what went wrong after printing "not ok". This
also means that "not ok" gets printed after the info rather than before,
which seems more intuitive anyway.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/tests/engine.sh | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/tools/tracing/rtla/tests/engine.sh b/tools/tracing/rtla/tests/engine.sh
index a97d644ead99..25cf0822eee5 100644
--- a/tools/tracing/rtla/tests/engine.sh
+++ b/tools/tracing/rtla/tests/engine.sh
@@ -43,6 +43,7 @@ check() {
tested_command=$1
expected_exitcode=${3:-0}
expected_output=$4
+ unexpected_output=$5
# Simple check: run rtla with given arguments and test exit code.
# If TEST_COUNT is set, run the test. Otherwise, just count.
ctr=$(($ctr + 1))
@@ -53,24 +54,29 @@ check() {
# Run rtla; in case of failure, include its output as comment
# in the test results.
result=$(eval stdbuf -oL $TIMEOUT "$RTLA" $2 2>&1); exitcode=$?
+ fail=0
+
# Test if the results matches if requested
- if [ -n "$expected_output" ]
+ if [ -n "$expected_output" ] && ! grep -qE "$expected_output" <<< "$result"
then
- grep -E "$expected_output" <<< "$result" > /dev/null; grep_result=$?
- else
- grep_result=0
+ fail=1
+ printf "# Output match failed: \"%s\"\n" "$expected_output"
fi
- if [ $exitcode -eq $expected_exitcode ] && [ $grep_result -eq 0 ]
+ if [ -n "$unexpected_output" ] && grep -qE "$unexpected_output" <<< "$result"
+ then
+ fail=1
+ printf "# Output non-match failed: \"%s\"\n" "$unexpected_output"
+ fi
+
+ if [ $exitcode -eq $expected_exitcode ] && [ $fail -eq 0 ]
then
echo "ok $ctr - $1"
else
- echo "not ok $ctr - $1"
# Add rtla output and exit code as comments in case of failure
echo "$result" | col -b | while read line; do echo "# $line"; done
printf "#\n# exit code %s\n" $exitcode
- [ -n "$expected_output" ] && [ $grep_result -ne 0 ] && \
- printf "# Output match failed: \"%s\"\n" "$expected_output"
+ echo "not ok $ctr - $1"
fi
fi
}
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (5 preceding siblings ...)
2025-08-21 3:57 ` [PATCH 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
@ 2025-08-21 3:57 ` Crystal Wood
2025-08-28 10:57 ` Tomas Glozar
6 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-21 3:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood, Jonathan Corbet
The basic functionality came with the consolidation; now hook up the
command line options, and add documentation and tests.
Cc: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
Documentation/tools/rtla/common_options.rst | 61 +++++++++++++++
.../tools/rtla/common_osnoise_options.rst | 8 ++
.../tools/rtla/common_timerlat_options.rst | 74 +++----------------
Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
.../tools/rtla/rtla-osnoise-hist.rst | 2 +
Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
.../tools/rtla/rtla-timerlat-hist.rst | 2 +
.../tools/rtla/rtla-timerlat-top.rst | 2 +
tools/tracing/rtla/src/actions.c | 8 +-
tools/tracing/rtla/src/actions.h | 2 +-
tools/tracing/rtla/src/osnoise_hist.c | 20 +++++
tools/tracing/rtla/src/osnoise_top.c | 20 +++++
tools/tracing/rtla/src/timerlat_hist.c | 6 +-
tools/tracing/rtla/src/timerlat_top.c | 6 +-
tools/tracing/rtla/tests/osnoise.t | 27 ++++++-
15 files changed, 168 insertions(+), 74 deletions(-)
diff --git a/Documentation/tools/rtla/common_options.rst b/Documentation/tools/rtla/common_options.rst
index 2dc1575210aa..77ef35d3f831 100644
--- a/Documentation/tools/rtla/common_options.rst
+++ b/Documentation/tools/rtla/common_options.rst
@@ -53,6 +53,67 @@
**--trace-buffer-size** *kB*
Set the per-cpu trace buffer size in kB for the tracing output.
+**--on-threshold** *action*
+
+ Defines an action to be executed when tracing is stopped on a latency threshold
+ specified by |threshold|.
+
+ Multiple --on-threshold actions may be specified, and they will be executed in
+ the order they are provided. If any action fails, subsequent actions in the list
+ will not be executed.
+
+ Supported actions are:
+
+ - *trace[,file=<filename>]*
+
+ Saves trace output, optionally taking a filename. Alternative to -t/--trace.
+ Note that nlike -t/--trace, specifying this multiple times will result in
+ the trace being saved multiple times.
+
+ - *signal,num=<sig>,pid=<pid>*
+
+ Sends signal to process. "parent" might be specified in place of pid to target
+ the parent process of rtla.
+
+ - *shell,command=<command>*
+
+ Execute shell command.
+
+ - *continue*
+
+ Continue tracing after actions are executed instead of stopping.
+
+ Example:
+
+ $ rtla |tool| |thresharg| 20 --on-threshold trace
+ --on-threshold shell,command="grep ipi_send |tracer|\_trace.txt"
+ --on-threshold signal,num=2,pid=parent
+
+ This will save a trace with the default filename "|tracer|\_trace.txt", print its
+ lines that contain the text "ipi_send" on standard output, and send signal 2
+ (SIGINT) to the parent process.
+
+ Performance Considerations:
+
+ |actionsperf|
+
+**--on-end** *action*
+
+ Defines an action to be executed at the end of tracing.
+
+ Multiple --on-end actions can be specified, and they will be executed in the order
+ they are provided. If any action fails, subsequent actions in the list will not be
+ executed.
+
+ See the documentation for **--on-threshold** for the list of supported actions, with
+ the exception that *continue* has no effect.
+
+ Example:
+
+ $ rtla |tool| -d 5s --on-end trace
+
+ This runs rtla with the default options, and saves trace output at the end.
+
**-h**, **--help**
Print help menu.
diff --git a/Documentation/tools/rtla/common_osnoise_options.rst b/Documentation/tools/rtla/common_osnoise_options.rst
index d73de2d58f5f..ba8e6674c220 100644
--- a/Documentation/tools/rtla/common_osnoise_options.rst
+++ b/Documentation/tools/rtla/common_osnoise_options.rst
@@ -1,3 +1,11 @@
+.. |threshold| replace:: **-a/--auto**, **-s/--stop**, or **-S/--stop-total**
+.. |thresharg| replace:: -s
+.. |tracer| replace:: osnoise
+
+.. |actionsperf| replace::
+ For time-sensitive actions, it is recommended to run **rtla** with
+ RT priority.
+
**-a**, **--auto** *us*
Set the automatic trace mode. This mode sets some commonly used options
diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documentation/tools/rtla/common_timerlat_options.rst
index 7854368f1827..1f5d024b53aa 100644
--- a/Documentation/tools/rtla/common_timerlat_options.rst
+++ b/Documentation/tools/rtla/common_timerlat_options.rst
@@ -1,3 +1,13 @@
+.. |threshold| replace:: **-a/--auto**, **-i/--irq**, or **-T/--thread**
+.. |thresharg| replace:: -T
+.. |tracer| replace:: timerlat
+
+.. |actionsperf| replace::
+ For time-sensitive actions, it is recommended to run **rtla timerlat** with BPF
+ support and RT priority. Note that due to implementational limitations, actions
+ might be delayed up to one second after tracing is stopped if BPF mode is not
+ available or disabled.
+
**-a**, **--auto** *us*
Set the automatic trace mode. This mode sets some commonly used options
@@ -55,67 +65,3 @@
Set timerlat to run without workload, waiting for the user to dispatch a per-cpu
task that waits for a new period on the tracing/osnoise/per_cpu/cpu$ID/timerlat_fd.
See linux/tools/rtla/sample/timerlat_load.py for an example of user-load code.
-
-**--on-threshold** *action*
-
- Defines an action to be executed when tracing is stopped on a latency threshold
- specified by **-i/--irq** or **-T/--thread**.
-
- Multiple --on-threshold actions may be specified, and they will be executed in
- the order they are provided. If any action fails, subsequent actions in the list
- will not be executed.
-
- Supported actions are:
-
- - *trace[,file=<filename>]*
-
- Saves trace output, optionally taking a filename. Alternative to -t/--trace.
- Note that nlike -t/--trace, specifying this multiple times will result in
- the trace being saved multiple times.
-
- - *signal,num=<sig>,pid=<pid>*
-
- Sends signal to process. "parent" might be specified in place of pid to target
- the parent process of rtla.
-
- - *shell,command=<command>*
-
- Execute shell command.
-
- - *continue*
-
- Continue tracing after actions are executed instead of stopping.
-
- Example:
-
- $ rtla timerlat -T 20 --on-threshold trace
- --on-threshold shell,command="grep ipi_send timerlat_trace.txt"
- --on-threshold signal,num=2,pid=parent
-
- This will save a trace with the default filename "timerlat_trace.txt", print its
- lines that contain the text "ipi_send" on standard output, and send signal 2
- (SIGINT) to the parent process.
-
- Performance Considerations:
-
- For time-sensitive actions, it is recommended to run **rtla timerlat** with BPF
- support and RT priority. Note that due to implementational limitations, actions
- might be delayed up to one second after tracing is stopped if BPF mode is not
- available or disabled.
-
-**--on-end** *action*
-
- Defines an action to be executed at the end of **rtla timerlat** tracing.
-
- Multiple --on-end actions can be specified, and they will be executed in the order
- they are provided. If any action fails, subsequent actions in the list will not be
- executed.
-
- See the documentation for **--on-threshold** for the list of supported actions, with
- the exception that *continue* has no effect.
-
- Example:
-
- $ rtla timerlat -d 5s --on-end trace
-
- This runs rtla timerlat with default options and save trace output at the end.
diff --git a/Documentation/tools/rtla/rtla-hwnoise.rst b/Documentation/tools/rtla/rtla-hwnoise.rst
index fb1c52bbc00b..3a7163c02ac8 100644
--- a/Documentation/tools/rtla/rtla-hwnoise.rst
+++ b/Documentation/tools/rtla/rtla-hwnoise.rst
@@ -1,5 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0
+.. |tool| replace:: hwnoise
+
============
rtla-hwnoise
============
diff --git a/Documentation/tools/rtla/rtla-osnoise-hist.rst b/Documentation/tools/rtla/rtla-osnoise-hist.rst
index f2e79d22c4c4..1fc60ef26106 100644
--- a/Documentation/tools/rtla/rtla-osnoise-hist.rst
+++ b/Documentation/tools/rtla/rtla-osnoise-hist.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: osnoise hist
+
===================
rtla-osnoise-hist
===================
diff --git a/Documentation/tools/rtla/rtla-osnoise-top.rst b/Documentation/tools/rtla/rtla-osnoise-top.rst
index 5d75d1394516..b1cbd7bcd4ae 100644
--- a/Documentation/tools/rtla/rtla-osnoise-top.rst
+++ b/Documentation/tools/rtla/rtla-osnoise-top.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: osnoise top
+
===================
rtla-osnoise-top
===================
diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentation/tools/rtla/rtla-timerlat-hist.rst
index 03b7f3deb069..9ca384432521 100644
--- a/Documentation/tools/rtla/rtla-timerlat-hist.rst
+++ b/Documentation/tools/rtla/rtla-timerlat-hist.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: timerlat hist
+
=====================
rtla-timerlat-hist
=====================
diff --git a/Documentation/tools/rtla/rtla-timerlat-top.rst b/Documentation/tools/rtla/rtla-timerlat-top.rst
index ab6cb60c9083..50968cdd2095 100644
--- a/Documentation/tools/rtla/rtla-timerlat-top.rst
+++ b/Documentation/tools/rtla/rtla-timerlat-top.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: timerlat top
+
====================
rtla-timerlat-top
====================
diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/actions.c
index aaf0808125d7..991139f9069f 100644
--- a/tools/tracing/rtla/src/actions.c
+++ b/tools/tracing/rtla/src/actions.c
@@ -127,17 +127,17 @@ actions_add_continue(struct actions *self)
* actions_parse - add an action based on text specification
*/
int
-actions_parse(struct actions *self, const char *trigger)
+actions_parse(struct actions *self, const char *trigger, const char *tracefn)
{
enum action_type type = ACTION_NONE;
- char *token;
+ const char *token;
char trigger_c[strlen(trigger)];
/* For ACTION_SIGNAL */
int signal = 0, pid = 0;
/* For ACTION_TRACE_OUTPUT */
- char *trace_output;
+ const char *trace_output;
strcpy(trigger_c, trigger);
token = strtok(trigger_c, ",");
@@ -160,7 +160,7 @@ actions_parse(struct actions *self, const char *trigger)
case ACTION_TRACE_OUTPUT:
/* Takes no argument */
if (token == NULL)
- trace_output = "timerlat_trace.txt";
+ trace_output = tracefn;
else {
if (strlen(token) > 5 && strncmp(token, "file=", 5) == 0) {
trace_output = token + 5;
diff --git a/tools/tracing/rtla/src/actions.h b/tools/tracing/rtla/src/actions.h
index b10a19d55c49..a4f9b570775b 100644
--- a/tools/tracing/rtla/src/actions.h
+++ b/tools/tracing/rtla/src/actions.h
@@ -48,5 +48,5 @@ int actions_add_trace_output(struct actions *self, const char *trace_output);
int actions_add_signal(struct actions *self, int signal, int pid);
int actions_add_shell(struct actions *self, const char *command);
int actions_add_continue(struct actions *self);
-int actions_parse(struct actions *self, const char *trigger);
+int actions_parse(struct actions *self, const char *trigger, const char *tracefn);
int actions_perform(struct actions *self);
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 2c2cdd467a67..dffb6d0a98d7 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -462,6 +462,8 @@ static void osnoise_hist_usage(char *usage)
" in nanoseconds",
" --warm-up: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
+ " --on-threshold <action>: define action to be executed at stop-total threshold, multiple are allowed",
+ " --on-end <action>: define action to be executed at measurement end, multiple are allowed",
NULL,
};
@@ -531,6 +533,8 @@ static struct common_params
{"filter", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{"trace-buffer-size", required_argument, 0, '7'},
+ {"on-threshold", required_argument, 0, '8'},
+ {"on-end", required_argument, 0, '9'},
{0, 0, 0, 0}
};
@@ -692,6 +696,22 @@ static struct common_params
case '7':
params->common.buffer_size = get_llong_from_str(optarg);
break;
+ case '8':
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '9':
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
default:
osnoise_hist_usage("Invalid option");
}
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 5a56c276f9da..95418f7ecc96 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -291,6 +291,8 @@ static void osnoise_top_usage(struct osnoise_params *params, char *usage)
" in nanoseconds",
" --warm-up s: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
+ " --on-threshold <action>: define action to be executed at stop-total threshold, multiple are allowed",
+ " --on-end: define action to be executed at measurement end, multiple are allowed",
NULL,
};
@@ -371,6 +373,8 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
{"filter", required_argument, 0, '1'},
{"warm-up", required_argument, 0, '2'},
{"trace-buffer-size", required_argument, 0, '3'},
+ {"on-threshold", required_argument, 0, '4'},
+ {"on-end", required_argument, 0, '5'},
{0, 0, 0, 0}
};
@@ -511,6 +515,22 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
case '3':
params->common.buffer_size = get_llong_from_str(optarg);
break;
+ case '4':
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '5':
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
default:
osnoise_top_usage(params, "Invalid option");
}
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index a9154f83f1a9..606c1688057b 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -1047,14 +1047,16 @@ static struct common_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '\5':
- retval = actions_parse(¶ms->common.threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\6':
- retval = actions_parse(¶ms->common.end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 42c3b0518749..48e055ba7850 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -783,14 +783,16 @@ static struct common_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '9':
- retval = actions_parse(¶ms->common.threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\1':
- retval = actions_parse(¶ms->common.end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
diff --git a/tools/tracing/rtla/tests/osnoise.t b/tools/tracing/rtla/tests/osnoise.t
index 89ff89c465a2..6598ca179c62 100644
--- a/tools/tracing/rtla/tests/osnoise.t
+++ b/tools/tracing/rtla/tests/osnoise.t
@@ -8,7 +8,8 @@ set_timeout 2m
check "verify help page" \
"osnoise --help" 0 "osnoise version"
check "verify the --priority/-P param" \
- "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q"
+ "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q -S 1 --on-threshold shell,command=\"tests/scripts/check-priority.sh osnoise/ SCHED_FIFO 1\"" \
+ 2 "Priorities are set correctly"
check "verify the --stop/-s param" \
"osnoise top -s 30 -T 1" 2 "rtla hit stop tracing"
check "verify the --trace param" \
@@ -22,4 +23,28 @@ check "verify the --entries/-E param" \
check_with_osnoise_options "apply default period" \
"osnoise hist -s 1" 2 period_us=600000000
+# Actions tests
+check "trace output through -t with custom filename" \
+ "osnoise hist -S 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
+check "trace output through --on-threshold trace" \
+ "osnoise hist -S 2 --on-threshold trace" 2 "^ Saving trace to osnoise_trace.txt$"
+check "trace output through --on-threshold trace with custom filename" \
+ "osnoise hist -S 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
+check "exec command" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
+check "multiple actions" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo -n 1' --on-threshold shell,command='echo 2'" 2 "^12$"
+check "hist stop at failed action" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo -n 1; false' --on-threshold shell,command='echo -n 2'" 2 "^1# RTLA osnoise histogram$"
+check "top stop at failed action" \
+ "timerlat top -T 2 --on-threshold shell,command='echo -n abc; false' --on-threshold shell,command='echo -n defgh'" 2 "^abc" "defgh"
+check "hist with continue" \
+ "osnoise hist -S 2 -d 1s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
+check "top with continue" \
+ "osnoise top -q -S 2 -d 1s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
+check "hist with trace output at end" \
+ "osnoise hist -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.txt$"
+check "top with trace output at end" \
+ "osnoise top -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.txt$"
+
test_end
--
2.48.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-21 3:57 ` [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere Crystal Wood
@ 2025-08-26 13:58 ` Tomas Glozar
2025-08-26 19:42 ` Crystal Wood
2025-08-26 18:05 ` Costa Shulyupin
1 sibling, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-08-26 13:58 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> The hist members were very similar between timerlat and top, so
> just use one common hist struct.
>
> output_divisor, quiet, and pretty printing are pretty generic
> concepts that can go in the main struct even if not every
> specific tool (currently) uses them.
>
Absolutely. Quiet and pretty printing are currently only used for top,
but they might make sense for hist, too, in the future. output_divisor
is actually always set to 1000 for osnoise-hist, once -n/--nano is
implemented for osnoise, it will also be used by both osnoise-hist and
osnoise-top, just like with rtla-timerlat.
For the commit message, maybe "Move hist/top-specific params into
common struct" would work better? "Elsewhere" doesn't quite capture
the idea for me.
> diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
> index ad5daa8210aa..7c68feed300e 100644
> --- a/tools/tracing/rtla/src/osnoise_top.c
> +++ b/tools/tracing/rtla/src/osnoise_top.c
> @@ -125,11 +125,12 @@ static void osnoise_top_header(struct osnoise_tool *top)
> {
> struct osnoise_params *params = top->params;
> struct trace_seq *s = top->trace.seq;
> + bool pretty = params->common.pretty_output;
Is there any specific motivation for doing this and not just using
params->common.pretty_output directly, like for the other parameters?
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure
2025-08-21 3:57 ` [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
@ 2025-08-26 14:15 ` Tomas Glozar
0 siblings, 0 replies; 27+ messages in thread
From: Tomas Glozar @ 2025-08-26 14:15 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> From: Costa Shulyupin <costa.shul@redhat.com>
>
> timerlat_params and osnoise_params structures contain 15 identical
> fields.
>
> Introduce a new header common.h and define a common_params structure to
> consolidate shared fields, reduce code duplication, and enhance
> maintainability.
>
> Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
> Signed-off-by: Crystal Wood <crwood@redhat.com>
There is an idea in the osnoise tracer that timerlat is somehow its
extension, for example, it uses struct osnoise_options for some of its
settings. But osnoise is a distinct tracer from timerlat, and this
mostly creates confusion and IMHO we should clearly separate them from
now on.
Reviewed-by: Tomas Glozar <tglozar@redhat.com>
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-21 3:57 ` [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere Crystal Wood
2025-08-26 13:58 ` Tomas Glozar
@ 2025-08-26 18:05 ` Costa Shulyupin
2025-08-26 20:39 ` Crystal Wood
2025-08-27 6:51 ` Tomas Glozar
1 sibling, 2 replies; 27+ messages in thread
From: Costa Shulyupin @ 2025-08-26 18:05 UTC (permalink / raw)
To: Crystal Wood; +Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Tomas Glozar
On Thu, 21 Aug 2025 at 06:58, Crystal Wood <crwood@redhat.com> wrote:
> The hist members were very similar between timerlat and top, so
> just use one common hist struct.
...
> @@ -27,4 +38,10 @@ struct common_params {
...
> + struct hist_params hist;
Moving `hist_params` into `common_params` could lead to
the `common_params` struct becoming a "god object" antipattern.
The `common_params` struct is intended to be tool-agnostic.
I suggest we use `hist_params` within the tools themselves,
rather than in `common_params`.
Thanks,
Costa
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-26 13:58 ` Tomas Glozar
@ 2025-08-26 19:42 ` Crystal Wood
2025-08-27 12:55 ` Tomas Glozar
0 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-26 19:42 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
On Tue, 2025-08-26 at 15:58 +0200, Tomas Glozar wrote:
> čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> >
> > The hist members were very similar between timerlat and top, so
> > just use one common hist struct.
> >
> > output_divisor, quiet, and pretty printing are pretty generic
> > concepts that can go in the main struct even if not every
> > specific tool (currently) uses them.
> >
>
> Absolutely. Quiet and pretty printing are currently only used for top,
> but they might make sense for hist, too, in the future. output_divisor
> is actually always set to 1000 for osnoise-hist, once -n/--nano is
> implemented for osnoise, it will also be used by both osnoise-hist and
> osnoise-top, just like with rtla-timerlat.
>
> For the commit message, maybe "Move hist/top-specific params into
> common struct" would work better? "Elsewhere" doesn't quite capture
> the idea for me.
OK.
>
> > diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
> > index ad5daa8210aa..7c68feed300e 100644
> > --- a/tools/tracing/rtla/src/osnoise_top.c
> > +++ b/tools/tracing/rtla/src/osnoise_top.c
> > @@ -125,11 +125,12 @@ static void osnoise_top_header(struct osnoise_tool *top)
> > {
> > struct osnoise_params *params = top->params;
> > struct trace_seq *s = top->trace.seq;
>
> > + bool pretty = params->common.pretty_output;
>
> Is there any specific motivation for doing this and not just using
> params->common.pretty_output directly, like for the other parameters?
Because that wouldn't be pretty :-)
(it just felt like it was repeated enough to be worth it)
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-26 18:05 ` Costa Shulyupin
@ 2025-08-26 20:39 ` Crystal Wood
2025-08-27 6:51 ` Tomas Glozar
1 sibling, 0 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-26 20:39 UTC (permalink / raw)
To: Costa Shulyupin
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Tomas Glozar
On Tue, 2025-08-26 at 21:05 +0300, Costa Shulyupin wrote:
> On Thu, 21 Aug 2025 at 06:58, Crystal Wood <crwood@redhat.com> wrote:
> > The hist members were very similar between timerlat and top, so
> > just use one common hist struct.
> ...
> > @@ -27,4 +38,10 @@ struct common_params {
> ...
> > + struct hist_params hist;
>
> Moving `hist_params` into `common_params` could lead to
> the `common_params` struct becoming a "god object" antipattern.
> The `common_params` struct is intended to be tool-agnostic.
>
> I suggest we use `hist_params` within the tools themselves,
> rather than in `common_params`.
Seems like that would get in the way of further consolidation of hist
code... and then you could just as well complain that the struct is
present when using one of the top tools, unless you separate *those*
out.
Just because someone someone came up with a name and called it
an "antipattern" doesn't mean there's always a benefit (relative to
cost) to breaking things up as much as you can. It was enough of a
nuisance as is to deal with separating timerlat_params, and now we've
got "common." littered all over the place (though sometimes that
indicates a good candidate for future code consolidation).
At this point I'm almost wishing I'd just made them all global variables
:-)
Keep in mind that we're refactoring existing code that is not designed
in a particularly object-oriented manner. This patchset certainly
doesn't reflect every cleanup that I'd like to see in this code, but I
think it's an improvement. There's plenty of room for followup patches.
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-26 18:05 ` Costa Shulyupin
2025-08-26 20:39 ` Crystal Wood
@ 2025-08-27 6:51 ` Tomas Glozar
1 sibling, 0 replies; 27+ messages in thread
From: Tomas Glozar @ 2025-08-27 6:51 UTC (permalink / raw)
To: Costa Shulyupin
Cc: Crystal Wood, Steven Rostedt, linux-trace-kernel, John Kacur
út 26. 8. 2025 v 20:06 odesílatel Costa Shulyupin
<costa.shul@redhat.com> napsal:
>
> Moving `hist_params` into `common_params` could lead to
> the `common_params` struct becoming a "god object" antipattern.
> The `common_params` struct is intended to be tool-agnostic.
>
> I suggest we use `hist_params` within the tools themselves,
> rather than in `common_params`.
>
I wouldn't worry about that at this point. Currently, both
rtla-osnoise and rtla-timerlat, which are the only tools in rtla, use
histograms, and share most of the histogram params. Furthermore,
histograms can be seen as extra data compared to top mode. In this
way, it is natural for hist_params to be a field in common_params.
See, for example, this part of the patch (in timerlat_bpf.c):
- if (params->entries != 0) {
+ if (params->common.hist.entries != 0) {
/* Pass histogram options */
- bpf->rodata->bucket_size = params->bucket_size;
+ bpf->rodata->bucket_size = params->common.hist.bucket_size;
There is more information now in the code, making it clear "entries"
is related to the histogram, plus if BPF sample collection is ever
extended to osnoise, this code can be shared. That would not be
possible if hist_params was moved to osnoise_params/timerlat_params.
If tools that do not use a histogram are added in the future, this
question can be revisited of course.
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/7] tools/rtla: Create common_apply_config()
2025-08-21 3:57 ` [PATCH 3/7] tools/rtla: Create common_apply_config() Crystal Wood
@ 2025-08-27 11:33 ` Tomas Glozar
2025-08-29 20:35 ` Crystal Wood
0 siblings, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-08-27 11:33 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> At some point it would be nice to have all of the common code named and
> located correctly, but it's a start. Do we want to stick with "common" or
> go with something less vague like "osn" for things that relate to the
> broader osnoise mechanism rather than the specific osnoise tracer?
For functions that set tracer options that reside in
/sys/kernel/tracing/osnoise and are used by both osnoise and timerlat
tracers (like osnoise_set_cpus and osnoise_set_workload), I think we
can call them tracer options, and make the function names
"tracer_set_cpus" etc. Or just use "common", that seems fine to me,
too.
> +++ b/tools/tracing/rtla/src/common.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#define _GNU_SOURCE
Nit: the newline is unnecessary after the SPDX identifier, other rtla
source files that don't start with a copyright comment after the SPDX
identifier (e.g. timerlat_bpf.c) don't have it.
> @@ -44,4 +103,12 @@ struct common_params {
> int output_divisor;
> int pretty_output;
> int quiet;
>+ int kernel_workload;
> };
It stood out to me that kernel_workload is moved to common, while
user_workload is not. On a second look though, osnoise has to make
sure kernel workload is created, but has no user workload option, so
it makes sense.
Reviewed-by: Tomas Glozar <tglozar@redhat.com>
Tomas
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere
2025-08-26 19:42 ` Crystal Wood
@ 2025-08-27 12:55 ` Tomas Glozar
0 siblings, 0 replies; 27+ messages in thread
From: Tomas Glozar @ 2025-08-27 12:55 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
út 26. 8. 2025 v 21:42 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> Because that wouldn't be pretty :-)
>
> (it just felt like it was repeated enough to be worth it)
>
Ah okay. In the context, it makes it look like the value is computed
inside the function rather than being a part of params, which might be
a bit confusing. Maybe I'm the only one confused by that though.
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-08-21 3:57 ` [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
@ 2025-08-27 13:34 ` Tomas Glozar
2025-08-29 20:46 ` Crystal Wood
0 siblings, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-08-27 13:34 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> Some bits like aa_only and the user stuff are in common even though they
> are only used by timerlat. In the case of user stuff I plan to submit
> patches for supporting that on osnoise, and it doesn't seem worthwhile to
> jump through hoops to move some of that code out of code that is otherwise
> able to be shared. For aa_only, making it non-common would have precluded
> sharing some code, and the code that the flag inhibits isn't tool-specific
> (unlike no_aa). Plus, there's other common code referring to tool->aa.
> ---
aa_only is implemented only for top, because the behavior would be the
same for hist: just do auto-analysis, no histogram, no top. Of course,
it doesn't hurt that it is included as a common parameter.
> + stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing;
> + if (stopped) {
> + printf("rtla hit stop tracing\n");
> + return_value = FAILED;
> + }
> +
Is the output change necessary? The original "osnoise hit stop
tracing"/"timerlat hit stop tracing" refers to the osnoise and
timerlat tracers, which stop tracing on threshold (unless mode is
TRACING_MODE_BPF
). We already have ops->tracer for the tracer name, that can be used here.
> /*
> * timerlat_top_bpf_main_loop - main loop to process events (BPF variant)
> */
> static int
> -timerlat_top_bpf_main_loop(struct osnoise_tool *top,
> - struct osnoise_tool *record,
> - struct osnoise_tool *aa,
> - struct timerlat_params *params,
> - struct timerlat_u_params *params_u)
> +__timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
The naming here should be consistent with the comment and with
timerlat-hist, that is, without the __ prefix, there is no other
timerlat_top_bpf_main_loop that would create a conflict in this
version of the patch.
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 5/7] tools/rtla: Fix -A option name in test comment
2025-08-21 3:57 ` [PATCH 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
@ 2025-08-28 6:52 ` Tomas Glozar
0 siblings, 0 replies; 27+ messages in thread
From: Tomas Glozar @ 2025-08-28 6:52 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> This was changed to --on-threshold when the patches were applied.
>
Right, that was changed at Arnaldo's suggestion in the next version of
the patchset. Good catch.
Reviewed-by: Tomas Glozar <tglozar@redhat.com>
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-08-21 3:57 ` [PATCH 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
@ 2025-08-28 8:09 ` Tomas Glozar
2025-08-29 21:34 ` Crystal Wood
0 siblings, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-08-28 8:09 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> Simplify the code so that we can print failures as they happen rather
> than trying to figure out what went wrong after printing "not ok". This
> also means that "not ok" gets printed after the info rather than before,
> which seems more intuitive anyway.
>
This change is causing some formatting issues, e.g.:
tests/hwnoise.t ... 2/6 # Output match failed: "rtla hit stop tracing"
# Error iterating on events
# Oops, error disabling tracer
#
# exit code 1
tests/hwnoise.t ... 3/6 not ok 3 - set the automatic trace mode
(the comment is on the same line as the previous test)
Furthermore, it's standard to first print "not ok" and then the
comments, see the documentation to Test::More [1], so I think we
should keep that.
[1] https://metacpan.org/pod/Test::More#ok
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions
2025-08-21 3:57 ` [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
@ 2025-08-28 10:57 ` Tomas Glozar
2025-08-29 21:47 ` Crystal Wood
0 siblings, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-08-28 10:57 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin,
Jonathan Corbet
čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> diff --git a/Documentation/tools/rtla/common_osnoise_options.rst b/Documentation/tools/rtla/common_osnoise_options.rst
> index d73de2d58f5f..ba8e6674c220 100644
> --- a/Documentation/tools/rtla/common_osnoise_options.rst
> +++ b/Documentation/tools/rtla/common_osnoise_options.rst
> @@ -1,3 +1,11 @@
> +.. |threshold| replace:: **-a/--auto**, **-s/--stop**, or **-S/--stop-total**
> +.. |thresharg| replace:: -s
> +.. |tracer| replace:: osnoise
> +
> +.. |actionsperf| replace::
> + For time-sensitive actions, it is recommended to run **rtla** with
> + RT priority.
> +
Unfortunately, real-time priority won't really help you in practice
for overflow-to-action latency, since the detection whether tracing
was stopped is only done once per second, when pulling the data. The
message should be instead just (something like):
"Due to implementational limitations,actions might be delayed up to
one second after tracing is stopped."
until either a trace event is implemented for stop tracing threshold
overflow (proposed in [1]), or rtla-osnoise is moved to BPF sample
collection, too.
[1] https://lore.kernel.org/linux-trace-kernel/CAP4=nvQWCWAOefHAqA82-VDb-00_y1-0fPOPBEyETJ2Q1EWEwg@mail.gmail.com/
> --- a/tools/tracing/rtla/tests/osnoise.t
> +++ b/tools/tracing/rtla/tests/osnoise.t
> @@ -8,7 +8,8 @@ set_timeout 2m
> check "verify help page" \
> "osnoise --help" 0 "osnoise version"
> check "verify the --priority/-P param" \
> - "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q"
> + "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q -S 1 --on-threshold shell,command=\"tests/scripts/check-priority.sh osnoise/ SCHED_FIFO 1\"" \
> + 2 "Priorities are set correctly"
> check "verify the --stop/-s param" \
> "osnoise top -s 30 -T 1" 2 "rtla hit stop tracing"
> check "verify the --trace param" \
> @@ -22,4 +23,28 @@ check "verify the --entries/-E param" \
> check_with_osnoise_options "apply default period" \
> "osnoise hist -s 1" 2 period_us=600000000
>
This is useful to have also for rtla-osnoise, thank you!
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/7] tools/rtla: Create common_apply_config()
2025-08-27 11:33 ` Tomas Glozar
@ 2025-08-29 20:35 ` Crystal Wood
0 siblings, 0 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-29 20:35 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
On Wed, 2025-08-27 at 13:33 +0200, Tomas Glozar wrote:
> čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> > At some point it would be nice to have all of the common code named and
> > located correctly, but it's a start. Do we want to stick with "common" or
> > go with something less vague like "osn" for things that relate to the
> > broader osnoise mechanism rather than the specific osnoise tracer?
>
> For functions that set tracer options that reside in
> /sys/kernel/tracing/osnoise and are used by both osnoise and timerlat
> tracers (like osnoise_set_cpus and osnoise_set_workload), I think we
> can call them tracer options, and make the function names
> "tracer_set_cpus" etc. Or just use "common", that seems fine to me,
> too.
That could add confusion though, when saying things like "the specific
osnoise tracer".
>
> > +++ b/tools/tracing/rtla/src/common.c
> > @@ -0,0 +1,64 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +#define _GNU_SOURCE
>
> Nit: the newline is unnecessary after the SPDX identifier, other rtla
> source files that don't start with a copyright comment after the SPDX
> identifier (e.g. timerlat_bpf.c) don't have it.
It just looked weird without it, since when there is a block comment at
the top, we usually do get a blank line before the code starts. I don't
really care either way, though.
>
> > @@ -44,4 +103,12 @@ struct common_params {
> > int output_divisor;
> > int pretty_output;
> > int quiet;
> > + int kernel_workload;
> > };
>
> It stood out to me that kernel_workload is moved to common, while
> user_workload is not. On a second look though, osnoise has to make
> sure kernel workload is created, but has no user workload option, so
> it makes sense.
FWIW, user_workload moves to common in the next patch.
>
> Reviewed-by: Tomas Glozar <tglozar@redhat.com>
Thanks!
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-08-27 13:34 ` Tomas Glozar
@ 2025-08-29 20:46 ` Crystal Wood
0 siblings, 0 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-29 20:46 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
On Wed, 2025-08-27 at 15:34 +0200, Tomas Glozar wrote:
> čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> >
> > Some bits like aa_only and the user stuff are in common even though they
> > are only used by timerlat. In the case of user stuff I plan to submit
> > patches for supporting that on osnoise, and it doesn't seem worthwhile to
> > jump through hoops to move some of that code out of code that is otherwise
> > able to be shared. For aa_only, making it non-common would have precluded
> > sharing some code, and the code that the flag inhibits isn't tool-specific
> > (unlike no_aa). Plus, there's other common code referring to tool->aa.
> > ---
>
> aa_only is implemented only for top, because the behavior would be the
> same for hist: just do auto-analysis, no histogram, no top. Of course,
> it doesn't hurt that it is included as a common parameter.
>
> > + stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing;
> > + if (stopped) {
> > + printf("rtla hit stop tracing\n");
> > + return_value = FAILED;
> > + }
> > +
>
> Is the output change necessary? The original "osnoise hit stop
> tracing"/"timerlat hit stop tracing" refers to the osnoise and
> timerlat tracers, which stop tracing on threshold (unless mode is
> TRACING_MODE_BPF
> ). We already have ops->tracer for the tracer name, that can be used here.
Certainly not necessary, but it didn't seem like an important
distinction to maintain -- unless there are scripts out there (beyond
our test cases) checking for it that we don't want to break. Though
for not-yet-written scripts I'd imagine having to deal with different
names could be an annoyance as well.
> > /*
> > * timerlat_top_bpf_main_loop - main loop to process events (BPF variant)
> > */
> > static int
> > -timerlat_top_bpf_main_loop(struct osnoise_tool *top,
> > - struct osnoise_tool *record,
> > - struct osnoise_tool *aa,
> > - struct timerlat_params *params,
> > - struct timerlat_u_params *params_u)
> > +__timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
>
> The naming here should be consistent with the comment and with
> timerlat-hist, that is, without the __ prefix, there is no other
> timerlat_top_bpf_main_loop that would create a conflict in this
> version of the patch.
Oops... I think there used to be a non-underscore version at some point
during development. Will fix.
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-08-28 8:09 ` Tomas Glozar
@ 2025-08-29 21:34 ` Crystal Wood
2025-09-01 12:50 ` Tomas Glozar
0 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-08-29 21:34 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
On Thu, 2025-08-28 at 10:09 +0200, Tomas Glozar wrote:
> čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> >
> > Simplify the code so that we can print failures as they happen rather
> > than trying to figure out what went wrong after printing "not ok". This
> > also means that "not ok" gets printed after the info rather than before,
> > which seems more intuitive anyway.
> >
>
> This change is causing some formatting issues, e.g.:
>
> tests/hwnoise.t ... 2/6 # Output match failed: "rtla hit stop tracing"
> # Error iterating on events
> # Oops, error disabling tracer
> #
> # exit code 1
> tests/hwnoise.t ... 3/6 not ok 3 - set the automatic trace mode
>
> (the comment is on the same line as the previous test)
I'm not seeing the "tests/hwnoise.t ... 2/6" part. What is printing
that?
> Furthermore, it's standard to first print "not ok" and then the
> comments, see the documentation to Test::More [1], so I think we
> should keep that.
>
> [1] https://metacpan.org/pod/Test::More#ok
https://xkcd.com/927/ :-P
I'm not a Perler, so I didn't recognize it as anything standardized.
Still seems backwards to me, both in terms of making it easier to see
which test failed, and in terms of being a pain to implement. And we
don't even get the benefit of seeing the test name printed before it
runs, to make it easier to see what's taking a long time.
Seems like Linux uses a variant of this, though:
Documentation/dev-tools/ktap.rst
I'll fix it, hopefully by sticking the error output into a variable or
something rather than duplicating logic. Or should we be using some
existing test infrastructure?
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions
2025-08-28 10:57 ` Tomas Glozar
@ 2025-08-29 21:47 ` Crystal Wood
0 siblings, 0 replies; 27+ messages in thread
From: Crystal Wood @ 2025-08-29 21:47 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin,
Jonathan Corbet
On Thu, 2025-08-28 at 12:57 +0200, Tomas Glozar wrote:
> čt 21. 8. 2025 v 5:58 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> > diff --git a/Documentation/tools/rtla/common_osnoise_options.rst b/Documentation/tools/rtla/common_osnoise_options.rst
> > index d73de2d58f5f..ba8e6674c220 100644
> > --- a/Documentation/tools/rtla/common_osnoise_options.rst
> > +++ b/Documentation/tools/rtla/common_osnoise_options.rst
> > @@ -1,3 +1,11 @@
> > +.. |threshold| replace:: **-a/--auto**, **-s/--stop**, or **-S/--stop-total**
> > +.. |thresharg| replace:: -s
> > +.. |tracer| replace:: osnoise
> > +
> > +.. |actionsperf| replace::
> > + For time-sensitive actions, it is recommended to run **rtla** with
> > + RT priority.
> > +
>
> Unfortunately, real-time priority won't really help you in practice
> for overflow-to-action latency, since the detection whether tracing
> was stopped is only done once per second, when pulling the data. The
> message should be instead just (something like):
>
> "Due to implementational limitations,actions might be delayed up to
> one second after tracing is stopped."
>
> until either a trace event is implemented for stop tracing threshold
> overflow (proposed in [1]), or rtla-osnoise is moved to BPF sample
> collection, too.
>
> [1] https://lore.kernel.org/linux-trace-kernel/CAP4=nvQWCWAOefHAqA82-VDb-00_y1-0fPOPBEyETJ2Q1EWEwg@mail.gmail.com/
OK. I'm glad there's at least something we can say there, since RST
didn't seem to like empty variables. :-P Looks like the workaround is
to set it to a space character.
I was going to ask if it should reference param->sleep_time instead,
but it looks like that's not actually wired up to any config
parameter...
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-08-29 21:34 ` Crystal Wood
@ 2025-09-01 12:50 ` Tomas Glozar
2025-09-02 19:08 ` Crystal Wood
0 siblings, 1 reply; 27+ messages in thread
From: Tomas Glozar @ 2025-09-01 12:50 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
pá 29. 8. 2025 v 23:35 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> I'm not seeing the "tests/hwnoise.t ... 2/6" part. What is printing
> that?
>
Test::Harness (which is one implementation of what is called a "TAP
harness") is printing that (the "prove" command which runs the tests),
it runs the tests, consumes the output and formats it.
> > Furthermore, it's standard to first print "not ok" and then the
> > comments, see the documentation to Test::More [1], so I think we
> > should keep that.
> >
> > [1] https://metacpan.org/pod/Test::More#ok
>
> https://xkcd.com/927/ :-P
>
> I'm not a Perler, so I didn't recognize it as anything standardized.
> Still seems backwards to me, both in terms of making it easier to see
> which test failed, and in terms of being a pain to implement. And we
> don't even get the benefit of seeing the test name printed before it
> runs, to make it easier to see what's taking a long time.
>
We can certainly modify the test system so that it works better for
us. The TAP standard that is used by the harness to process the output
of the RTLA test engine [1] does not specify where the additional
output should go, it's just a convention. I just say this might be
confusing to people who are used to the "not ok, then error" format,
which is associated with this type of test.
I'll have a look whether there is a way to easily print the test names
besides the number.
[1] https://testanything.org/tap-specification.html
> Seems like Linux uses a variant of this, though:
> Documentation/dev-tools/ktap.rst
>
Yes, this is used by kselftests [2], which are written in C.
[2] https://docs.kernel.org/dev-tools/kselftest.html
> I'll fix it, hopefully by sticking the error output into a variable or
> something rather than duplicating logic. Or should we be using some
> existing test infrastructure?
>
I wanted to use existing infrastructure, but could not find anything
suitable. I originally wanted to adopt the runtime test engine from
bpftrace, which is also an end-to-end test suite for a userspace
program closely related to the kernel. But bpftrace is licensed under
Apache 2, so it cannot be in the GPLv2 kernel source easily. I'm not
against suggestions, the test suite can always be migrated, that's not
the hard part.
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-09-01 12:50 ` Tomas Glozar
@ 2025-09-02 19:08 ` Crystal Wood
2025-09-03 16:15 ` Tomas Glozar
0 siblings, 1 reply; 27+ messages in thread
From: Crystal Wood @ 2025-09-02 19:08 UTC (permalink / raw)
To: Tomas Glozar
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
On Mon, 2025-09-01 at 14:50 +0200, Tomas Glozar wrote:
> pá 29. 8. 2025 v 23:35 odesílatel Crystal Wood <crwood@redhat.com> napsal:
> >
> > I'm not seeing the "tests/hwnoise.t ... 2/6" part. What is printing
> > that?
> >
>
> Test::Harness (which is one implementation of what is called a "TAP
> harness") is printing that
>
It would be nice to not depend on an out-of-tree test harness (does
anything else in the kernel use this?), especially without a prominent
comment mentioning it.
I've just been doing "sudo sh tests/whatever.t".
> (the "prove" command which runs the tests),
> it runs the tests, consumes the output and formats it.
Ugh, "prove" looks like it's some sort of formal rv thing... misleading
name for just running a test suite.
>
> > > Furthermore, it's standard to first print "not ok" and then the
> > > comments, see the documentation to Test::More [1], so I think we
> > > should keep that.
> > >
> > > [1] https://metacpan.org/pod/Test::More#ok
> >
> > https://xkcd.com/927/ :-P
> >
> > I'm not a Perler, so I didn't recognize it as anything standardized.
> > Still seems backwards to me, both in terms of making it easier to see
> > which test failed, and in terms of being a pain to implement. And we
> > don't even get the benefit of seeing the test name printed before it
> > runs, to make it easier to see what's taking a long time.
> >
>
> We can certainly modify the test system so that it works better for
> us. The TAP standard that is used by the harness to process the output
> of the RTLA test engine [1] does not specify where the additional
> output should go, it's just a convention. I just say this might be
> confusing to people who are used to the "not ok, then error" format,
> which is associated with this type of test.
I'm not suggesting that we break the convention; I just didn't realize
it was a widespread format.
>
> I'll have a look whether there is a way to easily print the test names
> besides the number.
>
> [1] https://testanything.org/tap-specification.html
It already does print the test name. If it didn't I probably would have
made more substantial changes to the test harness :-)
>
> > Seems like Linux uses a variant of this, though:
> > Documentation/dev-tools/ktap.rst
> >
>
> Yes, this is used by kselftests [2], which are written in C.
>
> [2] https://docs.kernel.org/dev-tools/kselftest.html
Would it make sense for us to use that?
Though the current docs linking to a wiki that's labelled "obsolete
content" isn't encouraging...
> But bpftrace is licensed under Apache 2, so it cannot be in the GPLv2
> kernel source easily.
Sigh...
-Crystal
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 6/7] tools/rtla: Add test engine support for unexpected output
2025-09-02 19:08 ` Crystal Wood
@ 2025-09-03 16:15 ` Tomas Glozar
0 siblings, 0 replies; 27+ messages in thread
From: Tomas Glozar @ 2025-09-03 16:15 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
út 2. 9. 2025 v 21:08 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> It would be nice to not depend on an out-of-tree test harness (does
> anything else in the kernel use this?), especially without a prominent
> comment mentioning it.
>
> I've just been doing "sudo sh tests/whatever.t".
>
Ah, I see, I should document the tests properly, I'll send a patch. To
clarify, "make check" uses Test::Harness on the RTLA tests. It's an
external tool but it seems it is usually installed on RHEL/Fedora so I
went with it.
>
> Ugh, "prove" looks like it's some sort of formal rv thing... misleading
> name for just running a test suite.
>
Yeah not exactly a good name, I always forget how it is named...
>
> It already does print the test name. If it didn't I probably would have
> made more substantial changes to the test harness :-)
>
Test::Harness only displays it in verbose mode which is not enabled,
since I thought it doesn't look as nice, I was maybe wrong.
>> Yes, this is used by kselftests [2], which are written in C.
>>
> >[2] https://docs.kernel.org/dev-tools/kselftest.html
>
> Would it make sense for us to use that?
>
> Though the current docs linking to a wiki that's labelled "obsolete
> content" isn't encouraging...
>
I don't think we need it or it would help us. The RTLA test engine in
bash is good enough IMO and customizable.
Tomas
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2025-09-03 16:15 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-21 3:57 [PATCH 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-08-21 3:57 ` [PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
2025-08-26 14:15 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 2/7] tools/rtla: Move top/hist union members elsewhere Crystal Wood
2025-08-26 13:58 ` Tomas Glozar
2025-08-26 19:42 ` Crystal Wood
2025-08-27 12:55 ` Tomas Glozar
2025-08-26 18:05 ` Costa Shulyupin
2025-08-26 20:39 ` Crystal Wood
2025-08-27 6:51 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 3/7] tools/rtla: Create common_apply_config() Crystal Wood
2025-08-27 11:33 ` Tomas Glozar
2025-08-29 20:35 ` Crystal Wood
2025-08-21 3:57 ` [PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
2025-08-27 13:34 ` Tomas Glozar
2025-08-29 20:46 ` Crystal Wood
2025-08-21 3:57 ` [PATCH 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
2025-08-28 6:52 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
2025-08-28 8:09 ` Tomas Glozar
2025-08-29 21:34 ` Crystal Wood
2025-09-01 12:50 ` Tomas Glozar
2025-09-02 19:08 ` Crystal Wood
2025-09-03 16:15 ` Tomas Glozar
2025-08-21 3:57 ` [PATCH 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
2025-08-28 10:57 ` Tomas Glozar
2025-08-29 21:47 ` Crystal Wood
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).